メインページに戻る

「nビットマシン」のnとは何なのか?

初代ファミコンは8bitマシンでスーパーファミコンは16bitマシン、PS2は32bitマシンだと言われます。 「Windowsパソコンは2011年現在、32bitから64bitへの過渡期にある」という言い方もよく耳にします。ところで、この8/16/32/64という値は何なのでしょうか?

この値に正しい名称があるのかは判りませんが、ここではデータバス幅と呼ぶことにします。このバス幅は「CPUとメモリ間で一度に転送できるデータ量」と定義する諸氏が多く、「この数字が大きいほど一度に扱うデータ量も大きくなるので、高速で高性能なコンピュータとなる」と解説するサイトも多い様です。 確かにこのバス幅はCPU(しいてはそのCPUを搭載したコンピュータ)の性能を決める上で重要な「ビット数」ですが、実際にCPUを設計しようとすると、もう一つ重要な「ビット数」が登場します。

それはCPUがアドレス空間の中から1つのアドレスを指定するために必要なビット数です(この値が32bitなら、搭載可能なメモリは2の32乗語となります)。 このビット数はアドレスバス幅と呼ばれ、搭載できるメモリ容量つまりどれくらい大きなプログラムを搭載できるかを決める値であり、データバス幅と甲乙が付けがたい重要な値です。

自分でCPUを設計しようとすると、他にも命令のビット長(命令長)や、CPU内部に存在するレジスタやのビット長など様々な「ビット数」が登場します。コンピュータ・アーキテクチャの設計は、これら全ての「ビット数」を決定することから始めることになります。どのビット数から決めるかは設計者の自由です。 私は実装するメモリの容量に直結するアドレスバス幅を先に決めることにしました。

コンピュータアーキテクチャは、大は小を兼ねるか?

アドレスバス幅に限らず、各種のbit数の決定は、理論上は「大は小を兼ねる」という法則を適用できます。

極端な話、インテルやAMDの技術者が決定すべき全てのビット数を256bitとして新たなCPUを開発するならば史上最強の製品が生まれるかもしれません。 しかし256bitのCPUは32bitのCPUに比べ、設計の手間も試験の困難さも桁違いに大きくなります。

もし、そのCPUをシリコンウェハ上に作成するならば、製造工程のみを考えても、チップ面積・不良率共に32bitCPUの8倍となり、単純計算では製造価格は64倍、設計や試験の費用増加分を加味すると、おそあらく市場価格は32bitCPUの100倍以上になってしまうことでしょう。 しかも消費電力も8倍となります。これはでは(開発が技術的に可能であったとしても)企業戦略としては現実的ではありません。

個人でCPU(しいてはコンピュータ)を作成する場合も話は同じです。 もちろん個人作る場合は「チップ面積」や「不良率」が問題になるのではなく、[時間」と「費用」が問題となります。より解りやすく言い換えると「耐えうる半田付けの手間隙」と「部品購入に必要な懐具合」と言えます。

「部品代が10万円、睡眠と食事以外は全て半田付けに費やし1ヶ月かけて8bitマシンを作りました」はありえても、「部品代1000万円、睡眠と食事以外は全てハンダ付けに費やし3年かけて256bitマシンを作りました」は(開発が技術的に可能であったとしても)個人の趣味としては現実的ではないのです。

コンピュータアーキテクチャは、小は大を兼ねるか?

では、逆に「小は大を兼ねる」はどうでしょうか?

例えば、アドレスバス幅もデータバスもも4ビットとして設計したらどうなるでしょうか?
この場合、メモリ空間はデータ領域を含めて0から15番地までとなります。作成できるプログラムはせいぜい10stepが限界です。命令構成もロード/ストア/加算/条件分岐の4つ程度になるかと思います。

それでも、コンピュータはコンピュータです。事実1970年代にはこのように極端にバス幅を縮めたアーキテクチャのコンピュータを趣味として自作された方が少なからずおりました。当時は256bitのSRAMを1個購入すると1週間分のバイト代が消えるほど半導体が高価だった時代ですから、どんなに技術力があっても、個人のお金で作成できるコンピュータにはおのずと限界があったのです。

それから40年、この記事を書いている2011年現在、256KBのSRAMは「5個300円」で入手可能になりました(2011年2月現在、秋月電子通商HPより)。予算面のみを考えると、40年前には絶対不可能であった大容量メモリコンピュータの自作可能です。これはバス幅の設計の自由度が高まったという喜ばしいことではありますが、具体的なビット数の決定がますます難しくなったという事でもあります。

オセロゲームと円周率、再び

設計に迷いが生じた時には、何が当初の目標だったのかを問い直すのが一番です。

プログラム次第で、オセロゲームにもなるし円周率の算出機にもなる。

これが今回の製作を思い立った時に立てた目標です。bitあたりのSRAM価格は40年前の約1億分の1です。しかし、予算的にはアドレス空間は任意に設計できたとしても、 配線の手間などを考えると各種のビット長は小さいほうが製作しやすいことも事実です。

設計作業で相反する選択に迷った場合は、欲張らず、安全・確実・簡単な方を選ぶ。

40年前にオリジナル計算機の作成に失敗した理由は、設計段階で構想がどんどん広がってしまい、あれもこれもと欲張っているうちに作成不可能な設計図が出来上がってしまったのが原因でした。今回はその反省をもとに、上記の鉄則(?)も自分に課しました。

これの鉄則をビット数の設計にあてはめると、ビット数をどれくらい大きくできるかではなく、最低何ビットあれば良いのかを考えることの方が優先するのは明らかです。

アドレスバスは12bitに決定

参考までにインベーダゲームを調べてみたところ、株式会社タイトーの正規品は8kバイトのプログラムメモリを有することがわかりました。ビット数に直すと13bitとなります。しかし、当時個人の趣味としてゲームプログラムを作っていた方々の専門誌への投稿等を見てみますと、2Kバイト程度のメモリでもインベーダーゲーム(の様な)プログラムを書き上げておりました。また、1Kバイト程度のメモリでオセロゲームをプログラムされた方もおりました。

いろいろ調べた結果、オセロゲームにもなるし円周率の算出機にもなるためには、最低でも10~12ビット程度のアドレス空間が必要だという結論に達しました。更に、74シリーズのTTLとして市販されているカウンターやレジスタは4bit(または8bit)単位の処理を前提としている物が多いので、10bitとか11ビットでは無駄が生じる可能性があることも経験として知っておりました。

以上の考察から、アドレス空間(=アドレスバス幅)は12bitとすることに決定しました。


分岐命令がデータバス幅を決める?

アドレスバス幅を12bitとした場合、データバス幅は何bitが最適なのでしょうか?
この問題の答を求めるのに最適なアプローチは分岐命令の実装を考えることです。

コンピュータの個々の命令(機械語命令)は命令の種類を表すビット列(オペコード)と、その命令を実行する為に必要な値を表すビット列(オペランド)に分けて考えることができます。CPUの種類やそのCPUが持つ命令セットによっては、オペコードとオペランドの境界が可変であったり、オペコードなのかオペランドなのか判断に迷う補助的なビット列がある命令や、意味の無いビット列を含む場合もありますが、一般には下記の様な構成となっています。

 オペコード(nビット)   オペランド(mビット) 

 n+m = 命令長


分岐命令の場合、オペランドは分岐先のアドレスですから、アドレス空間(アドレスバス幅)が12bitならば、オペランドの長さも12bitとなります。(注1)

一方、オペコードのビット長はそのCPUに実装する命令数が決まれば自ずと決まります。コンピュータの黎明期には命令数が4つ(ロード・ストア・加算・条件分岐)しかない物もありましたが、実用的なプログラミングができる事を前提とすると、減算/論理演算/無条件分岐/入出力命令なども欲しいところです。最低でも8種類、できれば16種類程度の命令が欲しいところです。8種類~16種類はビット数にすると3bitないし4bitとなりますが、TTLで多ビットを扱う場合、bit数は4の倍数にすると有利(注2)ですので、オペコードは4bitと決めました。

従って、分岐命令の場合、全体の長さは16ビット(オペコード4bit+オペランド12bit)となります。なお、命令の種類によって命令サイズが変える方法(インテル8080やザイログZ-80が採用)もありますが、命令を解釈する回路(インストラクションデコーダ)が複雑になると思い見送りました。従って今回作成するマシンは全ての命令が16ビットとなります。

(注1)メモリをバンク(ページ)に分け、バンク切替を行う命令を設ける、あるいは分岐できるアドレスを限定(偶数番地のみ等)する等の手法を用いる事によりオペランドで確保できる大きさ以上のアドレス空間を扱うことも可能です。
このため厳密には必ずしも「オペランド長=アドレス空間」とは限りません。

(注2)74シリーズのTTLは、レジスタやカウンタ等の多くが4bit分(あるいは8bit分)を1つのパッケージに納めたものが多いため。

命令の長さは16bitで、数値は整数8bitなら、データ長は何ビット?

メモリに格納されるデータは「命令」だけではありません。演算対象や演算結果という「数値」もメモリに格納されます。 これらの「数値」も16ビットとするならば、メモリに格納されるデータは「命令」であれ「値」であれ同サイズとなり無駄な領域が生じません。

しかし、計算結果などの「数値」も16ビットで扱うということは、CPU内部の演算器や、値を一時的に記憶するレジスタも全て16ビットで構築することになります。これでは部品数も配線の手間も大きくなってしまいます。1970年代に大手各社が製造した16ビットミニコンは、高価な部品を使っても、組立に膨大な人件責を費やしても、それに見合う価格で販売することが出来ましたが、個人の趣味ではそうもいきません。円周率が算出できる性能を目標の1つにしてはいますが、高精度の浮動小数点演算までは不要です。数値としては整数のみの8ビットもで十分と判断しました。

従って、同じメモリ上に存在するデータが一方では16bitの命令、他方は8bitの数値という異なるビット数となりました。この場合の対処法は幾つかあります。一つは大きい方の幅(16bit)に合わせ、小さい値(数値8bit)を格納する際に余るビット領域に意味の無い値(普通は0)を詰め込んでしまう方法です。メモリが安く手に入る現在、この方法も一考の価値はありますが、やはり無駄なメモリ領域が大量に発生するのは気持ちの良いものではありません。

いろいろ考えた結果、結局データバス幅を8bitとし、16bitの命令をメモリから取り出す際は、命令を前半8bitと後半8bitの2回に分けて取り出す方法を採用することにしました。命令を解釈する回路(インストラクションデコーダ)は多少複雑になりますが、命令の種類に関係なく全ての命令を2回に分けて取りだすので、命令毎に命令の長さが異なる方式(例えばZ-80は1バイト命令~4バイト命令が混在)よりは単純な回路で済みそうです。

(参考)もしFPGAで作るなら、

ここで、参考までに部品購入やハンダ付けを行わず、コンピュータアーキテクチャの確認のみをFPGAで実現しようとしている学生のみなさんにアドバイス。

FPGA上に作るならアドレスバスを16ビットとし、メモリに格納されるデータは「命令」であれ「値」であれ同じく長さにすることをお勧めします。これならば相対アドレス分岐を実装する場合でも、相対アドレスを求める加算器と、数値の足し算につかう加算器を同一のHWとして実現する勉強にもなります。また、プログラマーの視点からみた場合も、アドレス値をあたかも数値のようにメモリに保存ができますので、サブルーチンの戻り番地をどうやって保存するかと言う問題の解決も容易です。

またオペランドは12ビットでも、その12ビットが示すメモリ上の値をアドレス値とするアドレッシングモード(間接参照)や、メモリの一部をレジスタとみなして、レジスタ値をアドレスとして使うアドレッシングモード(レジスタ参照)も比較的容易に実装できるかと思います。

但し、ブロックダイアグラムは簡単に書けても、実際に動作させるためにはかなり複雑な制御回路の記述が必要です。最低でも1年以上、真面目にVHDLやVerilogの記述を勉強した程度の技量は必要かと思います。

最近はWeb上に、卒業論文そのものではありませんが、それに似たコンテンツをアップされている方が結構いらっしゃるようです。「FPGAで計算機を作る」という様な内容も散見されます。しかし、理論やアーキテクチャの記述ばかりが丁寧で、実際に動作させたプログラムに関しては全く言及されていないものも目に付きます。 もし、これからFPGAでコンピュータを作る予定がある方がおられましたら、机上の理論ではなく、是非、実際に何かのプログラムを動かせるところまで、自らの手で確かめて欲しいと思います。


メインページに戻る