7839

雑草魂エンジニアブログ

レジスタファイル・命令・シーケンサ

現在、CSの勉強のために、コンピュータアーキテクチャ (電子情報通信レクチャーシリーズ)を読んでいる。

P.17

f:id:serip39:20220226172001j:plain
主記憶装置を含む演算実行機構

前回は主記憶装置に焦点を当てたが、今回はレジスタ、制御信号群に焦点をあて整理をしてみる。

レジスタファイル

f:id:serip39:20220227111448j:plain

レジスタファイルは、複数のレジスタが集まったものである。レジスタもメモリ同様にアドレスを持っており、アドレスを使ってアクセスすることができる。(AVRのデータシートを確認すると、AVRの汎用レジスタは32個のレジスタで構成されており、アドレス付けされていることが確認できる。)また、レジスタファイルは2つの読み出しポートと1つの書き込みポートの3ポートを備えている。

主記憶装置とレジスタファイルの違い

主記憶装置 レジスタファイル
メモリ DRAM 高速SRAM
アクセス 1回に1語のみ 3ポートの並列アクセス可能
(2語の読出しと1語の書込み)

上記の図ではレジスタ内部を省略していたが、3ポートの並列アクセスを可能にするにはマルチポートのレジスタが必要となる。マルチポートを実現するには、差動ビット線方式とシングルエンドの2つがある。

f:id:serip39:20220227030526j:plain

  • Decoder:入力されたアドレスに応じて、一つのwordlineを選択してHIGHにする回路
  • wordline:任意のwordlineがHIGHになると、横一列の各セルの入出力が可能となる
  • Write Amp:書き込みデータ信号を作動のビット線信号に変換する回路
  • Senese Amp:セルから読み出された差動信号を検出して結果を出力する回路
  • read/write:読み込み・書き込み選択信号

差動ビット線方式 ReadもWriteもできるポートが2個ある。ただし、ポートを増やした分だけ、WriteAmpとSenseAmpも追加する必要がある。

シングルエンド 2つのReadポートと1つのWriteポートがある。差動ビット線方式ではないため、WriteAmpとSenseAmpは不要である。

両者の違いは以下の通りである。

  • 差動ビット線方式:2つの異なるアドレスレジスタへの同時書き込みが可能
  • シングルエンド:Writeポートは1つしかないので、複数のアドレスへの同時書き込みは不可能

そして、上記の簡易図は、シングルエンドを採用していることを想定している。(回路面積などの問題に関しては、今回割愛している。)

汎用レジスタとアキュムレータ

f:id:serip39:20220301005631j:plain

CPUの内部の一時記憶装置であるレジスタには大きく分けて2つの方式がある。

  1. 汎用レジスタ方式
    演算データを一時的に保管するレジスタを複数持つ場合、この複数のレジスタ群を「汎用レジスタ(GR)」と呼ぶ。そして、汎用レジスタは、レジスタファイルというハードウェアモジュールで実装される。
  2. アキュムレータ方式
    演算データを保管するレジスタが1つしかない場合、このレジスタを「アキュムレータ(Accumulator:"AC"or"A")」と呼ぶ。アキュムレータ方式の場合、演算は必ずアキュムレータとメモリ間で行われる。

汎用レジスタの場合、2つのレジスタ間で演算ができるため、高速演算が可能である。アキュムレータ方式は、汎用レジスタ方式と比較して、回路が簡単なため安価に実装できる。

命令

命令とは、制御信号を生成して、コンピューターの動作を決定するものである。

コンピュータの発明の最も偉大な点は、命令を一つのデータ(命令語, instruction word)として表現できることである。

プログラムは、命令の集まったものであり、上から順番に命令を実行することで処理が進む。命令もデータとして格納できることで、毎回入力せずとも同じ処理を繰り返し実行できている。今となっては当たり前に感じるが、この命令も一つのデータとして表現することがコンピュータ発明の偉大な点というのは、すごく腑に落ちた。具体的には、プログラムという命令の集まりはメモリに格納されており、命令は1つずつ順番に取り出され(fetch)、解読(decode)・実行(execute)されることで処理が進行される。

命令の種類

  1. 算術論理演算命令
  2. データ転送命令(メモリ⇆レジスタ間のデータ移動、メモリ操作)
  3. 条件分岐命令

以下のブロック図をもとに、命令がどのように実行されるかを確認する。 f:id:serip39:20220306165204j:plain

用語の説明

  • 主記憶装置メモリ
    • CPUと内部バスで接続され、プログラムや命令が格納されている(RAM)
  • メモリアドレスレジスタ(Memory Address Regster:MAR)
    • メモリに対してこれから操作するアドレスを格納しておくレジスタ
    • メモリはこの値を参照して指定されたアドレスにアクセスする
  • メモリデータレジスタ(Memory Data Register:MDR)
    • メモリから読み出したデータを格納しておくレジスタ
    • メモリに書き込むデータを格納しておくレジスタ
  • 制御装置
    • メモリにあるプログラムや命令を1個ずつ取り出し(fetch)、解読(decode)して制御する
  • プログラムカウンタ(Program Counter:PC)
    • 次に実行する命令のアドレスを格納しておくレジスタ
    • 一度参照されると、自動的に次の命令のアドレスにカウントアップする
    • 命令アドレスレジスタ、逐次制御カウンタとも呼ばれる
  • MUX(multiplexer)
    • 複数の信号を入力として受け取り、1つの信号を出力する回路
  • 命令レジスタ(Instraction Register:IR)
    • メモリから読み出した命令を格納しておくレジスタ
  • 命令デコーダ(Instraction Decoder:IDC
    • IRに保存されている命令を解読して、ALUや各種レジスタへの制御信号を生成する
  • 演算装置
    • 制御装置から送られてくる制御信号に従い、ALUとレジスタで算術論理演算を行う
  • アキュムレータ(accumulator:A, AC, ACC)
    • 演算の対象となるデータや演算結果を格納しておくレジスタ
    • 演算結果を保持するアキュムレータのビット数がCPUの演算処理のビット数となる
  • ALU(Arithmetic Logic Unit)
    • 算術演算, 論理演算, ビットシフト操作を行う
  • フラグレジスタ(Flag Register:FR)
    • 以下のような演算結果の状態(ステータス)を格納しておくレジスタ
      • OF(Overflow Flag):桁あふれ
      • SF(Sign Flag):演算結果が負の値
      • ZF(Zero Flag):演算結果がゼロ
  • 汎用レジスタ(General Register:GR)
    • アキュムレータとメモリアドレスレジスタを兼ね備えたレジスタ
    • 演算結果やデータを一時的に保存する
    • メモリのアクセス時にアドレス指定に使用する

CPUとメモリの間でのデータのやり取りは必ずメモリアドレスレジスタ(MAR)とメモリデータレジスタ(MDR)を介して行われるものとする。

  • メモリからデータを読み出す際は、まず、読み出すデータのあるアドレスをMARに設定し、読み出し信号を送ると、(MAR)番地のデータがMDRに設定される。そして、MDRから、IRやGRなどにデータが送られる。
  • メモリにデータを書き込む際は、まず、書き込み先のアドレスをMARに設定し、書き込むデータをMDRに設定する。そして、書き込み信号を送ると、MDRの内容が(MAR)番地に書き込まれる。

命令フェッチ

プログラムカウンタにプログラムの先頭の命令アドレスが設定されている状態から、メモリから最初の命令を読み出す。 f:id:serip39:20220306165229j:plain

  1. PCにある先頭の命令アドレスをMARに設定し、PCをカウントアップして次の命令を指すようにする
  2. CPUがメモリから命令を読み出す(フェッチする)
    • メモリは(MAR)番地のデータをMDRに書き込む
    • CPUは読み出したデータをIRに格納する
  3. IDCでIRのデータを解読して、制御信号を生成する(現時点では、命令を解読すると、必要な制御信号が必要なタイミングで生成されることとする。本来であれば、命令に対してCPUの各部分を時系列で制御する必要がある。)

上記を繰り返すことで、命令の集まりであるプログラムが順番に実行されて、処理を実現することができる。

メモリ操作命令(メモリからレジスタへのデータ転送)

演算対象となるデータはメモリ(RAM)に保存されているので、演算処理を実行する前に、まずメモリからレジスタにデータを転送する。 f:id:serip39:20220306165244j:plain

  1. 命令フェッチ・デコード(メモリのアドレス[X]からレジスタ[R1]にデータを転送する命令(LoadWord))
  2. 転送するデータのメモリのアドレス[X]をMARに設定する
  3. メモリは[X]番地のデータをMDRに書き込む
  4. MDRからGRの[R1]にデータが転送される

算術論理演算命令

レジスタに演算対象となるデータがある状態で、算術演算を実行する。例として、R1 + R2 -> R3 の加算をした場合を考える。 f:id:serip39:20220306165334j:plain

  1. 命令フェッチ・デコード(R1 + R2 -> R3 の加算をする命令(ADD))
  2. IDCから演算対象となる入力アドレスがGRに設定される
  3. GRから演算対象の2つのデータが読み出され、ALUに入力される
  4. IDCから演算制御信号がALUに設定され、演算結果の書き込みアドレスがGRに設定される
  5. ALUで演算が実行され、演算結果がGRに書き込まれる

メモリ操作命令(レジスタからメモリへのデータ転送)

計算した演算結果はレジスタに格納されているので、レジスタからメモリにデータを転送する。 f:id:serip39:20220306165351j:plain

  1. 命令フェッチ・デコード(レジスタ[R3]からメモリのアドレス[Z]にデータを転送する命令(StoreWord))
  2. 転送するデータのメモリのアドレス[Z]をMARに設定する
  3. IDCから読み出しアドレス[R3]がGRに設定される
  4. GRから[R3]のデータが出力され、MDRに書き込まれる
  5. メモリは[Z]番地にMDRのデータを書き込む

上記の流れで、それぞれの処理が実行される。条件分岐命令に関しては、次のシーケンサの部分で説明する。

シーケンサ

プログラムの実行は、どういう命令をどの順番でフェッチするかで決定される。次にどの命令を実行するかを決定し、命令アドレスを生成する回路が、シーケンサである。シーケンサは、プログラムカウンタ(PC)と呼ばれるレジスタと付加回路で構成されている。命令アドレスの決定は以下の3パターンがある。

  1. 現在の命令の次の命令を実行する。図中では、「+1」と表記しているが、命令長が4バイトの場合、次の命令を指すためには+4とする必要がある。
  2. 無条件分岐命令の場合、次の命令のアドレスを命令レジスタからプログラムカウンタに入れる。
  3. 条件分岐命令の場合、フラグレジスタの条件判定の結果に基づいて、次の命令レジスタのアドレスを決定する。

分岐命令

直前の命令の結果、演算結果がゼロとなりフラグレジスタに「ZF」が格納されているとする。 f:id:serip39:20220306165410j:plain

  1. 命令フェッチ・デコード(直前の命令の結果がゼロの場合は、[Y]へ。それ以外は、次の命令を実行する。)
  2. IDCから、分岐先アドレス[Y]をMUXに設定する
  3. FRから直前の演算結果を読み出し、ZFをMUXに設定する
  4. ZFであったため、[Y]を次の命令アドレスとして設定する

まとめ

レジスタファイル、命令、シーケンサを通して、CPUの内部の動きを理解することができた。

関連書籍