既存の Nios® II/e システムを Nios® V/m に移植してみた

##目次
- [1. はじめに](#1-はじめに)
- [2. 開発環境](#2-開発環境)
- [3. システム構成と構築手順](#3-システム構成と構築手順)
- [4. 動作確認](#4-動作確認)
- [5. おわりに](#5-おわりに)

##1. はじめに
インテル® Quartus® Prime Pro Edition v21.3 から、Nios® V/m プロセッサーが利用できるようになったようです。
Nios® V プロセッサーは、オープンソースの RISC-V 命令セット・アーキテクチャーをベースにした、インテル® FPGA 用の新しいソフトプロセッサーとのことです。
この記事では、既存の Nios® II/e システムを Nios® V/m に簡単に移植できるのかを試してみました。

尚、Nios® V プロセッサーの詳細については、@ys11qiitai さんの以下の記事が詳しく解説されており参考になります。
【参考】
・[Nios® V processor インストール、Hello World実行編](https://qiita.com/ys11qiitai/items/10a62072081341441e87)
・[Nios® V processor ブート、シミュレーション、デバッグ編](https://qiita.com/ys11qiitai/items/6cdd904f3c251de15877)


##2. 開発環境
基本的に下記のドキュメントを参考に開発環境の構築を行いました。
【参考】
・[Nios® V Processor Quick Start Guide  2021.10.04](https://www.intel.com/content/www/us/en/programmable/documentation/jmv1629188568604.html)

####2-1. ターゲット側

- **使用ボード：**
インテル® Arria® 10 SoC Development Kit
上記、Nios® V Processor Quick Start Guide に記載されている Nios® V/m Example Design が インテル® Arria® 10 SoC Development Kit 上でコンフィグレーションされているため、この記事でもこのボードを使用しています。
【参考】
・[Intel® Arria® 10 SoC Development Kit](https://www.intel.com/content/www/us/en/programmable/products/boards_and_kits/dev-kits/altera/arria-10-soc-development-kit.html)

- **サンプルデザイン：**
下記のページに掲載されているサンプルデザインをモディファイして使用しました。
【参考】
・[Embedded Peripherals IP - Performance Counter と Interrupt Latency Counter サンプル](https://malt.zendesk.com/hc/ja/articles/900006260763)
今回は、Performance Counter のみを使用するようにソースコードを変更しています。


####2-2. ホスト PC 側

- **オペレーティング・システム：**
Windows® 10 Enterprise （64bit） バージョン 1909

- **開発ツール：**
インテル® Quartus® Prime Pro Edition ソフトウェア・バージョン 21.3

- **オープンソース・ツール：**
 - [GNU RISC-V Embedded GCC（xpack-riscv-none-embed-gcc-8.3.0-2.3-win32-x64.zip）](https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/tag/v8.3.0-2.3)
 - [CMake（cmake-3.21.4-windows-x86_64.zip）](https://cmake.org/download/)
 - [xPack Windows ビルドツール（xpack-windows-build-tools-4.2.1-2-win32-x64.zip）](https://github.com/xpack-dev-tools/windows-build-tools-xpack/releases/)
 - ※ 注意：インテル® Quartus® Prime ソフトウェアには、上記のオープンソース・ツールは含まれていません。


##3. システム構成と構築手順
####3-1. ハードウェア・デザイン構成
今回動作させたハードウェア・デザインには以下のコンポーネント（Intel FPGA IP）が含まれています。
　① Clock Bridge
　② Reset Bridge
　③ Nios V/m Processor または、Nios II/e Processor
　④ On-Chip Memory (RAM or ROM)
　⑤ JTAG UART
　⑥ PIO (Parallel I/O)
　⑦ Performance Counter Unit

- **Nios® II/e システム：**
![niosII_system.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2164622/04a590eb-62a3-5dfb-4fe5-f2b28a237e99.png)
- **Nios® V/m システム：**
![niosv_system.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2164622/47900fd1-f5b9-4689-b4c7-89e621d9c8f8.png)

####3-2. ソースコード
今回使用した Performance Counter を動作させる C ソースコード Performance_Counter_Sample.c を以下に示します。

```c:Performance_Counter_Sample.c
/*******************************************************************************
 *  includes
 *******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <io.h>
#include "system.h"
#include "sys/alt_irq.h"
#include "altera_avalon_pio_regs.h"
#include "altera_avalon_performance_counter.h"

/*******************************************************************************
 *  re-definitions
 *  ※このセクションは"system.h"で定義された定数を、
 *    本ソースファイル内で使用するために再定義したものです。
 *    ご使用の際は右側の定数を"system.h"を参照の上、変更してお使いください。
 *******************************************************************************/
#define LED_CSR_ADR      (LED_BASE)     // LED のアドレス

#define PERF_COUNT_ADR   (PERFORMANCE_COUNTER_0_BASE)				// パフォーマンスカウンタのアドレス
#define PERF_SECTIONS	 (PERFORMANCE_COUNTER_0_HOW_MANY_SECTIONS)	// パフォーマンスカウンタのセクション数

/*******************************************************************************
 *  definitions (define, enum, typedef, etc..)
 *******************************************************************************/
#define LOOP_NUM 		(5) 			// for 文の回数。デフォルト 5
#define USLEEP_TIME		(1000000)		// usleep()に指定する値。デフォルト 1000000 = 1s

/*******************************************************************************
 *  proto types
 *******************************************************************************/
void PIO_Call_Back();

/*******************************************************************************
 *  main function
 *******************************************************************************/
int main()
{
	int i;
	printf("Nios V Start\n");

	// パフォーマンスカウンタのリセット
	PERF_RESET(PERF_COUNT_ADR);
	// パフォーマンスカウンタの起動
	PERF_START_MEASURING(PERF_COUNT_ADR);

	// セクション 1 計測開始
	PERF_BEGIN(PERF_COUNT_ADR, 1);
	{
		// LED を 消灯
		IOWR_ALTERA_AVALON_PIO_DATA(LED_CSR_ADR, 0x00);
		usleep(USLEEP_TIME);
		// LED 初期点灯
		IOWR_ALTERA_AVALON_PIO_DATA(LED_CSR_ADR, 0xFF);
		usleep(USLEEP_TIME);
	}
	// セクション 1 計測完了
	PERF_END(PERF_COUNT_ADR, 1);

	// セクション 2 計測開始
	PERF_BEGIN(PERF_COUNT_ADR, 2);
	{
		usleep(USLEEP_TIME);
	}
	// セクション 2 計測完了
	PERF_END(PERF_COUNT_ADR, 2);

	// for ループで、複数回測定
	for(i = 0; i < LOOP_NUM; i++){
		// セクション 3 計測開始
		PERF_BEGIN(PERF_COUNT_ADR, 3);
		{
			IOWR_ALTERA_AVALON_PIO_DATA(LED_CSR_ADR, 0xAA);
			usleep(USLEEP_TIME);
			IOWR_ALTERA_AVALON_PIO_DATA(LED_CSR_ADR, 0x55);
			usleep(USLEEP_TIME);
		}
		// セクション 3 計測完了
		PERF_END(PERF_COUNT_ADR, 3);
	}
	// Performnce Counter 結果をレポート
	perf_print_formatted_report(
			(void*)PERF_COUNT_ADR,	// パフォーマンスカウンタCSRアドレス
			alt_get_cpu_freq(),		// Nios Vの動作周波数(=パフォーマンスカウンタ)
			(PERF_SECTIONS-1),		// セクションポイントの数
			"Init",					// コンソール出力する際のセクション名
			"usleep 1s",
			"For Loop",
			"Unused",
			"Unused",
			"Unused"
	);

	printf("Nios V Finish\n");
	return 0;
}
```

####3-3. 構築手順

- **開発環境の構築**

1. Nios® V/m プロセッサーの IP ライセンス（無料）を[セルフサービス・ライセンスセンター](https://fpgasupport.intel.com/Licensing/license/index.html?r=1617866734000&navi=8)から入手します。
2. Nios® V/m プロセッサーの IP ライセンスをインテル® Quartus® Prime Pro Edition v21.3 に設定します。
3. オープンソース・ツールをセットアップします。ダウンロードしたオープンソース・ツールの .zip または .tar ファイルを <Intel Quartus Prime installation directory>/niosv ディレクトリーに解凍します。
4. インストールしたオープンソース・ツールをデザインフローに組み込むために、Windows のコマンドプロンプトより PATH 変数を設定します。

　`set PATH=C:/intelFPGA_pro/21.3/niosv/xpack-riscv-none-embed-gcc-8.3.0-2.3/bin;%PATH%`
　`set PATH=C:/intelFPGA_pro/21.3/niosv/cmake-3.21.4-windows-x86_64/bin;%PATH%`
　`set PATH=C:/intelFPGA_pro/21.3/niosv/xpack-windows-build-tools-4.2.1-2/bin;%PATH%`

- **ハードウェア・デザインの準備**

1. Platform Designer で [Generate HDL] をクリックして、上記 Nios® V/m システムのデザインを Generate します。
2. Quartus Prime から [Processing] ⇒ [Start Compilation] を選択して、ハードウェアのフルコンパイルを実行し、.sof ファイルを生成します。

- **ソフトウェア・デザインフロー**

1. ボード・サポートパッケージ（BSP）を作成します。Windows のコマンドプロンプトより Nios V Command Shell を起動して、以下のコマンドラインを実行し BSP ファイルを生成します。
`C:\intelFPGA_pro\21.3\niosv\bin\niosv-shell`
`cd C:\Work\NiosII_NiosV_Performance_Counter\top_NiosV`
`niosv-bsp -c --quartus-project=ghrd_10as066n2.qpf --qsys=niosv_system.qsys --type=hal software/niosV_performance_counter_bsp/settings.bsp`
![niosV_performance_counter_bsp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2164622/50477f47-56f8-3973-f12f-5b1bb9110aaf.png)

2. アプリケーション・プロジェクト・ファイルを生成します。Nios V Command Shell から以下のコマンドラインを実行し、アプリケーションの CMakeLists.txt を生成します。
`niosv-app --bsp-dir=software/niosV_performance_counter_bsp --app-dir=software/niosV_performance_counter --srcs=software/niosV_performance_counter --elf-name=niosV_performance_counter.elf`
![niosV_performance_counter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2164622/a560642e-15dd-715a-4ac6-d289a0437a03.png)

3. アプリケーション・プロジェクトをビルドします。Nios V Command Shell から以下のコマンドラインを実行します。
これにより、build フォルダ内に .elf ファイルの形でアプリケーションが生成されます。
`cmake -S software/niosV_performance_counter -G "Unix Makefiles" -B software/niosV_performance_counter/build`
`make -C software/niosV_performance_counter/build`
![niosV_performance_counter-build.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2164622/e9b6656f-9728-86d6-ae56-fb2b0a8772dd.png)
参考として、Nios® II/e と Nios® V/m の .objdump コード抜粋を以下に示します。
Nios® V/m では RISC-V 命令セットになっていることがわかります。
![objdump_log.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2164622/721a0ade-8551-10bc-4c31-614ffc7596e2.png)

4. On-Chip RAM ブート用 .hex ファイルの作成
Nios® II/e と Nios® V/m の両方とも、今回は .sof ファイルを書き込むとプロセッサーが起動して、サンプルソフトウェアが動き出すように On-Chip RAM にソフトウェアを抱え込ましています。
Nios V Command Shell から以下の elf2hex コマンドを実行し、.hex ファイルを作成します。
その後、生成した .hex ファイルを Quartus Prime Project のトップ階層に置き、再度 Quartus Prime でフルコンパイルします。
`cd C:/Work/NiosII_NiosV_Performance_Counter/top_NiosV/software/niosV_performance_counter/build`
`elf2hex niosV_performance_counter.elf -b 0x0 -w 32 -e 0x4ffff niosv_system_onchip_memory2_0_onchip_memory2_0.hex`

【参考】
.sof ファイルの書き込みでソフトウェアを起動させる方法については、@ys11qiitai さんの下記記事が参考になります。
・[ Nios® V processor ブート、シミュレーション、デバッグ編 ⇒ 2. ブート方法 ](https://qiita.com/ys11qiitai/items/6cdd904f3c251de15877#2-%E3%83%96%E3%83%BC%E3%83%88%E6%96%B9%E6%B3%95) 


##4. 動作確認

1. インテル® Arria 10 SOC Development Kit を準備します。
① 電源ケーブルを接続します。
② オンボード USB-Blaster II を PC と接続します。
③ 電源スイッチを ON にします。
![A10SoC_board.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2164622/c959633a-26b9-0b37-08b1-ad2d65008290.png)

2. .sof ファイルを Arria 10 SOC Development Kit に書き込みます。Nios V Command Shell から以下のコマンドを実行します。
● Windows の書き込みコマンド例：
`quartus_pgm -c 1 -m JTAG -o p;output_files\ghrd_10as066n2.sof@1`
● Linux の書き込みコマンド例：
`quartus_pgm -c 1 -m JTAG -o p\;output_files\ghrd_10as066n2.sof@1`

3. Nois の Command Shell を起動して terminal を実行します。これにより以下のようなサンプルプログラムによる Performance Counter での計測結果が表示されます。
`juart-terminal`
![execute_log.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2164622/9779c336-0bdb-30e7-085e-09ba4dded19a.png)


##5. おわりに
最後まで記事をお読みいただきありがとうございます。
今回の確認で使用したデザインでは、既存の Nios® II/e システムを Nios® V/m に簡単に置き換えることができました。
この記事を読んで興味を持たれた方も是非一度 Nios® V/m を試してみてはいかがでしょうか。