FC2カウンター FPGAの部屋 Vivado HLS 2017.3.1 における識別子の違いによる任意精度固定小数点データ型の動作の違い1
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

Vivado HLS 2017.3.1 における識別子の違いによる任意精度固定小数点データ型の動作の違い1

Zynq+Vivado HLS 勉強会で使用する予定のVivado HLS 2017.3 における識別子の違いによる任意精度固定小数点データ型の動作の違いをブログに書いて置く。

任意精度固定小数点データ型とは、任意のビット長の固定小数点のデータ型のことだ。整数+小数のビット幅と整数のビット幅を選ぶことができる。更に量子化モードとオーバーフローモードを選ぶことができる。つまり、自動的に飽和演算してくれるわけだ。とっても便利な任意精度固定小数点データ型を調査していこう。

なお、任意精度固定小数点データ型については、”Vivado Design Suite ユーザー ガイド 高位合成 UG902 UG902 (v2017.3) 2017 年 10 月 04 日”の189ページからの”任意精度固定小数点デー タ型”を参照のこと。

まずは、ap_fixed_test.h から貼っておく。

// ap_fixed_test.h
// 2017/11/03 by marsee
//

#ifndef __ap_fixed_test_H__
#define __ap_fixed_test_H__

typedef ap_fixed<4, 3, AP_TRN_ZERO, AP_SAT> ap_fixed_def;
// for simulation test
// ap_fixed<4, 3, AP_TRN_ZERO, AP_SAT>
// ap_fixed<4, 3, AP_TRN_ZERO, AP_WRAP>
// ap_fixed<4, 3, AP_RND, AP_SAT>
// ap_fixed<4, 3, AP_TRN, AP_SAT>

// for synthesis test
// ap_fixed<4, 3, AP_TRN_ZERO, AP_SAT>
// ap_fixed<4, 3, AP_TRN_ZERO, AP_WRAP>

#endif


ap_fixed_test.cpp を貼っておく。

// ap_fixed_test.cpp
// 2017/11/03 by marsee
//

#include <ap_fixed.h>

#include "ap_fixed_test.h"

int ap_fixed_test(ap_fixed_def in0, ap_fixed_def in1,

	
	
ap_fixed_def &out){

	
out = in0 * in1;

	
return(0);
}


ap_fixed_test_tb.cpp を貼っておく。

// ap_fixed_test_tb.cpp
// 2017/11/03 by marsee
//

#include <stdio.h>
#include <ap_fixed.h>

#include "ap_fixed_test.h"

int ap_fixed_test(ap_fixed_def in0, ap_fixed_def in1,

	
	
ap_fixed_def &out);

int main(){
	
ap_fixed_def out;

	
ap_fixed_test(1.5, 1.5, out);
	
printf("1.5 x 1.5 = %f\n", (float)out);

	
ap_fixed_test(-1.5, 1.5, out);
	
printf("-1.5 x 1.5 = %f\n", (float)out);

	
ap_fixed_test(2, 2, out);
	
printf("2 x 2 = %f\n", (float)out);

	
ap_fixed_test(-2, 2, out);
	
printf("-2 x 2 = %f\n", (float)out);

	
ap_fixed_test(3, 3, out);
	
printf("3 x 3 = %f\n", (float)out);

	
ap_fixed_test(-3, 3, out);
	
printf("-3 x 3 = %f\n", (float)out);

	
return(0);

}


ap_fixed_test プロジェクトを示す。
ap_fixed_test_1_171103.png

C シミュレーションを行った。結果を示す。
ap_fixed_test_2_171103.png

ここで使用している任意精度固定小数点データ型は全ビット数が4ビット、整数部3ビット、小数部1ビットだ。つまり、2の補数表示をすると、-4 〜 +3.5 までの 0.5 刻みの小数ということになる。
今回の量子化モードは AP_TRN_ZERO : 0 への切 り捨て (デフォル ト )
オーバーフロー・モードは AP_SAT : 飽和

1.5 x 1.5 = 2.000000
-1.5 x 1.5 = -2.000000
2 x 2 = 3.500000
-2 x 2 = -4.000000
3 x 3 = 3.500000
-3 x 3 = -4.000000


1.5 x 1.5 = 2.25 だが、0.5 刻みなので、0 へ切り捨てされて 2.0 になった。
-1.5 x 1.5 = -2.25 だが、やはり 0 方向に切り捨てるので、切り上がって -2.0 になった。
2 x 2 = 3.5 は整数部が負の値を含めて3ビットなので、実質2ビットで整数の絶対値を表すため、+3.5 〜 -4.0 なので、3.5が正の値の最大値であるため飽和演算されている。
-2 x 2 = -4.000000 は正しい。
3 x 3 = 3.500000 は正の値の飽和演算のテスト、正の最大値。
-3 x 3 = -4.000000 は負の値の飽和演算のテスト、負の最大値。

次にオーバーフローモードを AP_WRAP : 折り返し (デフォル ト )にする。
typedef ap_fixed<4, 3, AP_TRN_ZERO, AP_WRAP> ap_fixed_def;
結果を示す。

1.5 x 1.5 = 2.000000
-1.5 x 1.5 = -2.000000
2 x 2 = -4.000000
-2 x 2 = -4.000000
3 x 3 = 1.000000
-3 x 3 = -1.000000


飽和演算が無くなったので、飽和演算をしていた下の演算の値が桁上げが無いためおかしくなっている。
2 x 2 = -4.000000
3 x 3 = 1.000000
-3 x 3 = -1.000000
AP_WRAP は演算してもオーバーフローしない時の演算に使用すると良い。飽和演算をするよりも使用リソースが少なくなる。

オーバーフロー・モードを AP_SAT に戻して、
量子化モードを AP_RND : 正の無限大への丸め にしてみよう。
typedef ap_fixed<4, 3, AP_RND, AP_SAT> ap_fixed_def;
結果を示す。

1.5 x 1.5 = 2.500000
-1.5 x 1.5 = -2.000000
2 x 2 = 3.500000
-2 x 2 = -4.000000
3 x 3 = 3.500000
-3 x 3 = -4.000000


今回は、1.5 x 1.5 = 2.500000 が変わっている。正の無限大への丸めなので、2.25 が 2.5 に丸められている。

量子化モードを AP_TRN : 負の無限大への切り捨て にしてみよう。
typedef ap_fixed<4, 3, AP_TRN, AP_SAT> ap_fixed_def;
結果を示す。

1.5 x 1.5 = 2.000000
-1.5 x 1.5 = -2.500000
2 x 2 = 3.500000
-2 x 2 = -4.000000
3 x 3 = 3.500000
-3 x 3 = -4.000000


今度は、-1.5 x 1.5 = -2.500000 となって、負の無限大への切り捨て となっているのがわかる。

このように量子化モードやオーバーフローモードで結果が変わってくる。
C コードを合成してもリソース使用量が変わるので次回やってみよう。
  1. 2017年11月03日 06:29 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/3961-8a01c6b9
この記事にトラックバックする(FC2ブログユーザー)