四畳半テクノポリス

コロナのストレスで気が狂い、D進した院生

アルバイト始めました

どうも、前期に授業取りすぎて半分落としたとり天です。

ついこないだなのですが、知り合いからGPGPU関連のアルバイトを御紹介いただきまして、それをやることにしました。

バイトと言っても在宅で時間を自由に決められるので、昼間に時間を取りにくい僕に合ってると思います。

今もらってる仕事はドキュメントの作成なんで高専の学生実験みたいな感じですね。

スタックマシンの実装方法

状態遷移図

今回は前回作成したスタックマシン型のCPUをVerilogで実装する。そのためにCPUの動作を表した状態遷移図の作成を行った。

f:id:toriten1024:20160327005438p:plain

状態遷移図の各状態での動作は以下に示す通りである。

  1. 命令フェッチ
  2. 命令デコード
  3. データフェッチ
  4. データ操作命令実行
  5. 演算命令実行

 である。S1ではプログラム・カウンタの値から命令の読み出しを行う、S2では命令の解釈を行う、S3では必要であればデータのフェッチを行う、S4とS5は命令の実行であり、S4ではデータ操作命令の実行、S5では演算命令の実行を行う。

 メインメモリに二度アクセスするPush命令とPop命令を除き、命令の行う処理は1サイクルで実行できる内容であるが、デバッグのしやすさと、動作の理解のしやすさを考え、マルチサイクルで命令の実行を行う。

コンピュータシステムの構成

CPUだけではコンピュータとして成立せず、プログラムを実行できないので、CPUにメインメモリを接続する。このメインメモリには初期状態では実行するプログラムや、プログラム上で扱う定数などが格納されている。またプログラム実行時の変数等もメインメモリ上で扱われることになる。

メインメモリとCPUは10bitのアドレスバス、16bitのCPUデータ入力バス、16bitのCPUデータ出力バス、1bitのメモリ制御信号により接続される、

アドレスバスはメモリ上のデータを参照したり、メモリ上でデータを格納したり、する時にメインメモリ上のアドレスを指定するために使用される。CPUデータ入力バスはメインメモリからデータを読み出すのためのデータバスである。CPUデータ出力バスはCPUからメインメモリへデータを書き出すためのデータバスである。メモリ制御信号はメインメモリに対して行う操作を書き込みか、読み込みか指定するために使用される。今回の場合は読み込み/書き込みどちらの線を1にしたかで動作をしてできるようにする。

f:id:toriten1024:20160327215005p:plain

バスの動作は例えば0x0ff番地にデータ0x0064を書き込みたい場合は、アドレスバスを0xffに,CPUデータバスに0x64を指定し、書き込み信号を1にすれば良い。この状態でシステムクロックの立ち上がりが発生すると指定したアドレスにデータの書き込みが行われる。

 

Verilogによるスタックマシンの作成

スタックマシン

 スタックマシンとはデータをスタックと呼ばれるデータ構造を用いた計算機である。スタックと呼ばれるLastInFirstOutのデータ構造Push(データの挿入)、Pop(データの取り出し)、演算、という3種類の操作を行うことで計算を行う。このあたりに関しては詳しく解説しているサイトを見てほしい。

 多くのインタプリタ型言語の処理系で用いられる中間言語はスタックマシンであることが多い、しかし現在流通しているCPUのほとんどはレジスタと呼ばれるCPU内部の商用呂のランダムアクセスメモリを用いたものである。そこでverilogを用いてスタックマシンを作成してみようという考えに至った。HDLを用いたFPGA上で動作するスタックマシンは別に珍しいものではなく前例も多く存在するが、今回の目的はエクササイズであり、作成するスタックマシンは実用性では無く、なるべくシンプルな命令体系にすることに重点を置く。

今回作成するCPU

今回作成するCPUは命令長と扱える数値の大きさから、16bitCPUとした。命令も16bit、扱える数も16bitである。マルチサイクルプロセッサで、1命令の実行に4クロックの時間を要する。

 命令体系

純粋なスタックマシンは基本的にPush,Pop、演算という操作で計算を行うが、それだけではプログラムの制御ができないので、制御命令も必要となる、次の表に示すのが今回設計するCPUの命令セットである。

 

命令 バイナリ 機能
ADD 0b00000100_00000000 スタックから2つPopし加算結果をPushする
SUB 0b00001000_00000000 スタックから2つPopし減算結果をPushする
MUL 0b00001100_00000000 スタックから2つPopし乗算結果をPushする
DIV 0b00010000_00000000 スタックから2つPopし除算結果をPushする
PUSH 0b100001XX_XXXXXXXX XXで指定したアドレスの値をPushする
POP 0b100010XX_XXXXXXXX スタックから1つPopしXXで指定したアドレスに格納する
JMP 0b100011XX_XXXXXXXX XXで指定したアドレスにプログラムカウンタを飛ばす
IZ 0b000100XX_XXXXXXXX スタックのトップが0ならXXで指定したアドレスにプログラムカウンタを飛ばす
INZ 0b000100XX_XXXXXXXX スタックのトップが0でないならXXで指定したアドレスプログラムカウンタを飛ばす

 

命令は16ビットから10ビットまでにかけての命令を示すコードと、10ビット目から1ビット目にかけてのアドレスを示すフィールドで構成する。命令のフィールド先頭の16ビット目が命令のタイプを示しており、このビットが1だとPUSHなどのデータ制御命令とJMPなどのプログラム制御命令である。0だと演算命令である。

 

次回以降は今回設計した命令セットをVerilogで実装してゆく