Changes between Initial Version and Version 1 of Ex02 乗算アルゴリズムの実装2017


Ignore:
Timestamp:
Apr 24, 2017 12:58:30 PM (9 years ago)
Author:
nakasato
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Ex02 乗算アルゴリズムの実装2017

    v1 v1  
     1トップ:http://galaxy.u-aizu.ac.jp/note/wiki/CAEX2017 
     2 
     3= 課題4:乗算の実装 = 
     4第5版教科書上巻p.177の「3.3 乗算」をよく読んで、乗算をおこなうプログラムを作ってください。 
     5乗数A、被乗数B、積Cは32ビットです。求める乗算結果は64ビットではなく、下位の32ビットだけで十分です。 
     6つまり、乗数と被乗数は最大16ビットまでを仮定してください。 
     7  
     8今後演習で設計するMIPSプロセッサは、シフト命令をサポートしていませんので、以下のような工夫が必要になります。 
     9 
     10== 左シフト == 
     111ビット左シフトは2倍することと同等なので加算命令によって実現できます。 
     12 
     13シフト命令を使う場合: 
     14{{{ 
     15sll $8,$9,1 
     16}}} 
     17 
     18加算命令の場合: 
     19{{{ 
     20add $8,$9,$9 
     21}}} 
     22 
     23ここで気をつけなければならないのは、加算によるオーバーフローです。 
     24最上位ビットが1である数を2倍すると(正確には同じ数を足し合わせると)、 
     25最上位ビットで桁上がりを生じるため、add 命令ではオーバーフロー例外が発生します。  
     26xspimでは、このためプログラムが停止するので、 左シフトするための加算はaddではなく、 
     27オーバーフローを無視するadduを使用してください。 
     28 
     29一方、演習の後半で設計するプロセッサはオーバーフローをチェックしませんので、 
     30回路シミュレーション時はadduをaddに戻す必要があります。 
     31詳しいことは、該当回の際に説明します。なお、今回作成するプログラムはadduを利用したものを保存しておくこと。 
     32 
     33== 右シフト == 
     341ビット右シフトを他の命令で単純に実現することは困難です。  
     35そこで今回は乗算アルゴリズムとハードウエアの直列バージョン(教科書上巻p.212)に 
     36あるアルゴリズムを、左シフトのみを使うように修正して乗算を実現します。 
     37 
     38[[Image(http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex02%E8%AA%B2%E9%A1%8C2016/mult_chart.gif)]] 
     39 
     40乗算で使われる右シフトは、ビットを下位から順に調べることだけが目的なので、 
     41左シフトを使って同等の機能を実現することができます。  
     42 
     43下のように、右シフトの結果と定数1とのandをとる代わりに、 
     44初期値として1をレジスタに入れておき、これを左シフトしたものとand をとるようにします。 
     45 
     46シフト命令を使う場合: 
     47{{{ 
     48  srl $8,$8,1 
     49  andi $9,$8,1 
     50}}} 
     51 
     52加算命令の場合: 
     53{{{ 
     54  addi $10,$0,1     # $10に1を代入(前処理) 
     55    : 
     56  addu $10,$10,$10  # 左シフト。通常でslr命令だった部分に相当 
     57  and $9,$8,$10     # 通常でandi命令だった部分に相当 
     58}}} 
     59 
     60この様にして各ビットが1か0かを調べられます。 
     61 
     62[[Image(http://galaxy.u-aizu.ac.jp/note/raw-attachment/wiki/Ex02%E8%AA%B2%E9%A1%8C2016/shift_ex.gif)]] 
     63 
     64シフト命令を使う方法(上)だと結果は 0…01(32ビット) か 00…0(32ビット)の2通りだけですが、 
     65加算命令を使用した方法(下)だと、そのビットが0のときは 00…0 ですが、そのビットが1だった場合、 
     66その結果もそれが何桁目かによって、結果を左にシフトしています。 
     67ですから、結果が0であるか否かで条件分岐をすることになります。 
     68 
     69== 初期化部分 == 
     70{{{ 
     71        .data  
     72A:      .word 13  
     73B:      .word 37  
     74C:      .word 0 
     75 
     76       ... 必要な変数の領域を追加する .... 
     77        .text  
     78main:       ... プログラムを書く ....  
     79 
     80 
     81exit:   j exit 
     82}}} 
     83 
     84作成ファイル名は「ex02_p4.s」としてください。 
     85 
     86= 課題5:行列積 = 
     87以下のC言語で書かれた行列乗算のプログラムを参考にして、行列積C = A x Bを計算するプログラムを作ってください。 
     88 
     89== 行列A == 
     90{{{ 
     910  1  0  0 
     922  0  0  0  
     930  0  0  3 
     940  0  4  0 
     95}}} 
     96 
     97== 行列B == 
     98{{{ 
     991  2  3  4 
     1005  6  7  8  
     1019 10 11 12 
     10213 14 15 16 
     103}}} 
     104 
     105 
     106== テンプレート == 
     107作成ファイル名は「ex02_p5.s」としてください。 
     108 
     109{{{ 
     110        .data  
     111A:      .word 0  
     112        .word 1  
     113        .word 0  
     114        .word 0  
     115    ... 配列Aの要素を書く ....  
     116 
     117B:      .word 1  
     118        .word 2  
     119        .word 3  
     120        .word 4  
     121    ... 配列Bの要素を書く ....  
     122 
     123C:      .space 64 ## 結果行列の保存用 
     124 
     125       ... 必要な変数の領域を追加する .... 
     126        .text  
     127main:  
     128exit:   j exit 
     129}}} 
     130 
     131== C言語バージョン == 
     132{{{ 
     133 
     134#include <stdio.h> 
     135main() 
     136{ 
     137  static int mat1[4][4] = { 
     138    { 1, 0, 0, 0 }, 
     139    { 0, 1, 0, 0 }, 
     140    { 0, 0, 1, 0 }, 
     141    { 0, 0, 0, 1 }, 
     142  }; 
     143  static int mat2[4][4] = { 
     144    {  1,  2,  3,  4 }, 
     145    {  5,  6,  7,  8 }, 
     146    {  9, 10, 11, 12 }, 
     147    { 13, 14, 15, 16 }, 
     148  }; 
     149  static int result[4][4]; 
     150 
     151  int  i, j, k; 
     152  int  s; 
     153  int  m1, m2; 
     154 
     155  /* 行列の乗算 */ 
     156  for( i = 0; i < 4; i++ ) { 
     157    for( j = 0; j < 4; j++ ) { 
     158      s = 0; 
     159      for( k = 0; k < 4; k++ ) { 
     160        mask = 1; 
     161        m1 = mat1[i][k];  /* 被乗数 */ 
     162        m2 = mat2[k][j];  /* 乗数 */ 
     163        s += m1 * m2 
     164      } 
     165      result[i][j] = s; 
     166    } 
     167  } 
     168 
     169  /* 結果の表示 */ 
     170  for( i = 0; i < 4; i++ ) { 
     171    for( j = 0; j < 4; j++ ) { 
     172      printf("%3d", result[i][j]);  
     173    } 
     174    printf("\n"); 
     175  } 
     176} 
     177}}}