[高位合成] データ型関連の話

# データ型などのあれこれ
高位合成においてC/C++でのデータ型などがどのような扱いなのかを説明します。
今回は基本的なもののみです。

## 動作環境

IDE：VitisHLS 2023.1

## ソースコード

https://github.com/kiiisy/VitisHLS_sample

## 概要
以下の流れで説明していきます。

1. 標準の型
2. 高位合成専用の型
3. 構造体

### 標準の型

| 型                  | 通常のC/C++サイズ| 高位合成サイズ  |
|:-------------------:|:--------------:|:------------:|
| bool                | 1byte          | 1bit         |
| char                | 1byte          | 8bit         |
| unsigned char       | 1byte          | 8bit         |
| short               | 2byte          | 16bit        |
| unsigned short      | 2byte          | 16bit        |
| int                 | 4byte          | 32bit        |
| unsigned int        | 4byte          | 32bit        |
| long                | 8byte          | 64bit        |
| unsigned long       | 8byte          | 64bit        |
| long long           | 8byte          | 64bit        |
| unsigned long long  | 8byte          | 64bit        |
| float               | 4byte          | 32bit        |
| double              | 8byte          | 64bit        |

※通常のC/C++は64bit環境を想定しています

:::note warn
OSがWindowsかLinuxかによってサイズが異なるので注意。
![SCR-20250430-hwpq.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290770/e38259e2-9b70-49a6-a7c0-62303a36338d.png)
:::

また、C99から導入された```stdint.h```も使用できます。
floatとdouble以外はこちらを使用した方がいいと思います。

| 型       | サイズ  |
|:--------:|:------:|
| intN_t   | N bit  |
| uintN_t  | N bit  |


### 高位合成の型

```ap_int.h```をインクルードすれば任意のビット幅も使用できます。

| 型            | サイズ  |
|:-------------:|:------:|
| ap_int< N >   | N bit  |
| ap_uint< N >  | N bit  |

**N**は1〜1024まで指定可能

1024bit以上を扱いたい場合は、以下の通りにマクロを上書きしてあげると
最大*4096*bitまで扱えます。

```c++
#define AP_INT_MAX_W 4096
#include "ap_int.h"

ap_int<4096> tmp;
```

また、```ap_fixed.h```をインクルードすれば固定小数点も扱えます。
固定小数点を扱うメリットとしては動作が早くなります。
デメリットとしては精度が落ちてしまいます。

| 型                         | サイズ  |
|:--------------------------:|:------:|
| ap_fixed< W, I, Q, O, N >  | W bit  |
| ap_ufixed< W, I, Q, O, N > | W bit  |

**W**はビット幅。
**I**は整数値を表すビット幅。
Q, O, Nは指定しなくても問題ないため今回は説明は省きます。(丸め込みとかの設定です)

※固定小数点を知らない方は以下のサイトを参考にしてみてください。

https://qiita.com/izuki_y/items/fb3936192f6ec3f555b2

### 構造体

構造体もC/C++同様に使用できます。
この場合どのように合成されるのか？ですが、2通りのパターンがあります。
- 個別の信号として合成される(分割)
- 1つのベクタとして合成される(集約)

以下を例にします。

```c++
struct MyType
{
    short data1;
    int data2;
};
```

```c++
MyType my_data;
#pragma HLS DISAGGREGATE variable = my_data
```

```DISAGGREGATE```プラグマを使用すれば個別の信号として扱われます。

```c++
MyType my_data;
#pragma HLS AGGREGATE variable = my_data
```

```AGGREGATE```プラグマを使用すれば1つのベクタとして扱われます。

:::note info
プラグマを指定しなけばデフォルトで個別の信号として扱われます。
ただし、状況によってはベクタになるかもです。
:::

:::note info
インターフェースで構造体を使用すると、強制的に1つのベクタで扱われます。
:::

また、通常のC/C++同様に構造体にはアライメントがあります。
なにも指定しなければアライメントは4byte(32bit)になります。

以下がアライメントのイメージです。

![SCR-20250505-oyhh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290770/fab7f162-9d76-4da5-a7df-6cecb4427854.png)

以下の場合は注意してください。無駄にリソースを食うかもしれません。

![SCR-20250505-oyuh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290770/fb331fad-5348-47cb-a8a9-cff402baa3a6.png)

もしアライメントを変更したい場合は、以下のように定義してください。
※Nは2のべき乗のみ

```c++
struct __attribute__((aligned(N))) xxx
{
}
```

今回は以上。