﻿<<<< HWLib Example Program >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

-- 情報 ----------------------------------------------------------------
ファイル名：		sample_time_measurement.c
作成日：			2013/11/13
更新日：			2014/01/23	"体裁修正" 
更新日：			2014/04/21	"u-boot-spl.axf を v13.1 で生成したファイルに変更"
更新日：			2014/07/29	"SoC EDS 14.0 用に Makefile を修正"
更新日：			2014/08/18	"誤植訂正、操作説明の表示を追加"
更新日：			2015/06/25	"SoC EDS 15.0 用の HWLib に対応。文字コードを UTF-8 に変更 (Linux の日本語表示)。
						 		割込みログの実装を改善 (割込み利用の場合のみ)"
更新日：			2016/03/14	"デバッグコンフィギュレーション設定変更（レジスタ定義読み込み）"
更新日：			2016/03/29	"デバッグコンフィギュレーション設定変更（レジスタ定義読み込み） ファイルの修正"
更新日：			2016/07/08	"マルチボード対応（Helio/Atlas/Sodia/C5SoCDevKit）"
更新日：			2017/05/22	"Arria 10 Soc DevKit 対応, DS-5 レジスタビュー表示にも対応"
更新日：			2018/07/02	"All in One ベアメタル・アプリケーション v17.1 への対応を実施"
更新日：			2019/02/25	"All in One ベアメタル・アプリケーション v18.1 への対応を実施"
更新日：			2021/04/23	"SoC EDS v20.1 / Arm DS 2020.1 への対応を実施、Helio は更新対象外(v18.1 用を使用)"
更新日：			2025/07/29	"SoC EDS v20.1 / Arm DS 2024.1 への対応を実施"

確認 HWLib バージョン：	13.1 (SoC EDS 13.1)
確認 HWLib バージョン：	14.0 (SoC EDS 14.0 patch0.02)
確認 HWLib バージョン：	15.0 (SoC EDS Version: 15.0.1, Build: 60)
確認 HWLib バージョン：	15.1 (SoC EDS Version: 15.1.1, Build: 60)
確認 HWLib バージョン：	16.0 (SoC EDS Version: 16.0, Build: 211)
確認 HWLib バージョン：	16.1 (SoC EDS Version: 16.1.0, Build: 196)
確認 HWLib バージョン：	17.0 (SoC EDS Version: 17.0, Build: 595)
確認 HWLib バージョン：	17.1 (SoC EDS Version: 17.1, Build: 585)
確認 HWLib バージョン：	18.1 (SoC EDS Version: 18.1, Build: 625)
確認 HWLib バージョン：	github.com/altera-opensource - tag: rel_socfpga_v2020.10_21.03.01_pr
　　　　　　　　　　　　　Download: [ https://github.com/altera-fpga/u-boot-socfpga/releases/tag/rel_socfpga_v2020.10_21.03.01_pr ]
確認 HWLib バージョン：	github.com/altera-opensource - tag: rel_socfpga_v2024.01_24.11.03_pr
　　　　　　　　　　　　　Download: [ https://github.com/altera-fpga/u-boot-socfpga/releases/tag/rel_socfpga_v2024.01_24.11.03_pr ]

※ 本 HWLib Example を利用する場合には、プロジェクト 「ALT-HWLib-All-In-One_vXX.X_r○」 をインポートし、
　 TOP ディレクトリーに本 HWLib Example ファイルをコピーしてコンパイル対象とすることで、
　 Makefile を修正すること無く各種評価ができるようになっています（FPGA のコンフィギュレーションデータ等を共有するため）。

※ SoC EDS v13.1 以前のツールを利用する場合には、本サンプルに含まれる Makefile に下記変更を加えて下さい。
　【変更前】 CROSS_COMPILE := arm-altera-eabi-　　... SoC EDS v14.0 以降を利用の場合
　【変更後】 CROSS_COMPILE := arm-none-eabi-　　..... SoC EDS v13.1 以前を利用の場合
　 リンカスクリプト（cycloneV-dk-ram-hosted.ld）内に記述されるラベル（2 カ所）にも変更が必要な場合があります。
　【変更前】 __cs3_reset_cycloneV_dk_ram
　【変更後】 __cs3_reset_generic
　 他、HWLib のバージョン違いにより一部の API でコンパイルエラーが発生する場合があります。
　 その場合は、適宜サンプルコードを変更してご利用下さい。

**************************************************************************************
* Copyright (C) 2013-2025 MACNICA,Inc. All Rights Reserved.                          *
*   This software is licensed "AS IS".                                               *
*   Please perform use of this software by a user's own responsibility and expense.  *
*   It cannot guarantee in the maker side about the damage which occurred by the ab- *
*   ility not to use or use this software, and all damage that occurred secondarily. *
**************************************************************************************

※ 本サンプルでは、DS Intel SoC FPGA Edition (Altera Edition) のレジスタ・ビューには
　 標準では表示されない下記ペリフェラルのレジスタ表示に対応しています。
　  * DMA Controller（DMA-330）
　  * L2Cache Controller（L2C-310）
　  * Cortex-A9 MPCore 内蔵 SCU（Snoop Control Unit）
　  * Cortex-A9 MPCore 内蔵 Interrupt Controller（GIC: PL-390）
　  * Cortex-A9 MPCore 内蔵 Timer（Global Timer, Private Timer, Watchdog Timer）
　
　レジスタ・ビューのカスタマイズ方法は、マクニカサイトの技術情報をご参照ください。
　『Arm DS 活用テクニック ～レジスタ・ビュー［2/3］レジスタ定義の自作』
　 https://www.macnica.co.jp/business/semiconductor/articles/intel/115085 

※ config.mk ファイル内のシンボル定義を変更することで、ターゲットボードの選択が可能です。
　 下記から 1 行だけを選択します（その他の行は # でコメントアウトします）。
　#######################
　# Select Target Board #
　#######################
　TARGET_BOARD := atlas		← Atlas-SoC / DE0-Nano-SoC
　#TARGET_BOARD := sodia		← Mpression Sodia Evaluation Board 
　#TARGET_BOARD := c5socdk		← Cyclone V SoC Development Kit 
　#TARGET_BOARD := a10socdk		← Arria 10 SoC Development Kit 
　#TARGET_BOARD := de10nano		← DE10-Nano

※ 本サンプルでは、HPS 側の PUSH スイッチ 4 つと DIPSW (SLIDE) 4 つを
　 操作することでソフトウェアの動作を切り替える仕組みを実装しております。
　
　但し、ターゲットボードに Atlas-SoC / DE0-Nano-SoC / DE10-Nano を選択した場合、
　HPS 側には前述のスイッチが不足する状態となるため、以下の対応でご利用頂く実装としています。
　 * PUSHSW0 ... FPGA 側の PUSH BUTTON (KEY0, KEY1) を同時押し 
　 * PUSHSW1 ... FPGA 側の PUSH BUTTON (KEY0) を単押し
　 * PUSHSW2 ... FPGA 側の PUSH BUTTON (KEY1) を単押し
　 * PUSHSW3 ... HPS 側の USER PUSH BUTTON (KEY2) を単押し
　 * DIPSW[3:0] ... FPGA 側の SLIDE スイッチ (SW3, SW2, SW1, SW0) 
　
　Arria 10 SoC Development Kit を選択した場合は、全てのスイッチ（PUSH × 4、
　DIPSW (SLIDE) × 4）を HPS 側ではなく FPGA 側をご利用頂く実装としています。
　
　FPGA 側のスイッチを利用するため当該スイッチ用の PIO を実装した .sof にて
　事前に FPGA のコンフィギュレーションを行って頂く必要があります。

※ FPGA のコンフィギュレーション用の .sof ファイルは、DS ワークスペース以下
　 ALT-HWLib-All-In-One_vXX.X_r○\target_board の中に格納してあります。
　（必要に応じて Quartus Programmer 等で書き込みしてください）


-- 概要 ----------------------------------------------------------------
HWLib の The Global Timer Manager API を用いて、処理時間計測の仕組みを実装した
サンプルプログラムです。

下記のソース/ヘッダファイルを別のプロジェクトに追加することで同様の仕組みで
処理時間を計測することができます。
 - util_time_measurement.c
 - util_time_measurement.h

＜■ 処理時間計測用関数の一覧および説明＞
// All Functions
/***********************************************************************/
/* Usage: void util_time_init(void);                                   */
/* Usage: void util_time_record_start_point(uint32_t index);           */
/* Usage: void util_time_record_end_point(uint32_t index);             */
/* Usage: void util_time_print_result_by_counter(uint32_t index);      */
/* Usage: void util_time_print_result_by_seconds(uint32_t index);      */
/* Usage: void util_time_print_result_all(void);                       */
/* Usage: void util_time_print_result_all_and_clear(void);             */
/***********************************************************************/

void util_time_init(void);
 → 初期化処理です。本機能を利用する際に必ず最初に呼び出してください。

void util_time_record_start_point(uint32_t index);
 → 計測開始したいポイントに関数呼び出しを実装してください。

　　<uint32_t index>
　　 index は同時に複数個所の計測を行う際の計測ポイント識別用の番号となります。
　　 0～31 の適当な番号を指定して下さい。

　　同時計測ポイントを増やしたい場合は、ヘッダファイル内の
　　#define UTIL_TIME_MAX_TRACE の定義値を増やすことで対応可能です。

　　※ 引数の index 値は、全ての関数で同じ仕様として実装しています。

void util_time_record_end_point(uint32_t index);
 → 計測終了するポイントに関数呼び出しを実装してください。
　　※ 引数の index 値には、対応する開始ポイントと同じ値を指定して下さい。

void util_time_print_result_by_counter(uint32_t index);
 → index で指定した計測結果 (1 件) を「Global Timer のカウンタ値」として表示します。

void util_time_print_result_by_seconds(uint32_t index);
 → index で指定した計測結果 (1 件) を「時間」として表示します。

void util_time_print_result_all(void);
 → 全件の計測結果を「カウンタ値」と「時間」の両方で表示します。

void util_time_print_result_all_and_clear(void);
 → 全件の計測結果を「カウンタ値」と「時間」の両方で表示します。
　　また、全ての計測結果情報をクリアします。


＜■ 注意＞
※ 計測結果の「時間」は、HPS のメインクロック (mpu_clk) を 800MHz の設定とした場合に
　 正しい時間で表示されることを前提にしています。

異なるクロックの環境で計測を行う場合には、ヘッダファイル内の下記定義を変更することで対応可能です。
  #define	UTIL_TIME_GLOBALTIMER_PRESCALE   1
  #define	UTIL_TIME_NSEC_PER_COUNT         10

例えば、600MHz の環境で計測する場合には下記の値に変更します。
  #define	UTIL_TIME_GLOBALTIMER_PRESCALE   2
  #define	UTIL_TIME_NSEC_PER_COUNT         20

UTIL_TIME_GLOBALTIMER_PRESCALE は、Global Timer のプリスケーラ設定値となります。
UTIL_TIME_NSEC_PER_COUNT は、時間を計算する際に Global Timer カウンタの差分値に乗算されます。

※ Global Timer のカウント周期のナノ秒未満の値は全て切り捨て誤差となるため、
　 プリスケーラの値をナノ秒未満の誤差が少なくなる設定値として利用して下さい。
　 Global Timer を別用途で利用している場合などで、プリスケーラ値を変更できない場合には、
　 カウンタ値の計測結果をご利用ください（カウント周期の掛け算は別で行う）。

※ 上記パラメータ (UTIL_TIME_GLOBALTIMER_PRESCALE, UTIL_TIME_NSEC_PER_COUNT) を自動計算するための
　 Excel シートを用意しました。
　 → プロジェクト内のファイル：ParameterSettings_for_TimeMeasurement.xlsx をご利用ください。


-- 使い方 --------------------------------------------------------------

　　①．アーカイブを SoC EDS (DS) へインポートします。
　　~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	１．SoC EDS（DS）のメニューから「ファイル(F) -> インポート(I)...」を実行します。
	　　※ 注意：SoC EDS (DS) は Embedded_Command_Shell から起動してください。
		↓
	２．インポートダイアログ上のインポート・ソースの選択(S)： として
	　　「一般 -> 既存プロジェクトをワークスペースへ」を選択して［次へ(N)>］を実行します。
		↓
	３．アーカイブ・ファイルの選択(A) のチェックを有効にして、
	　　［参照(R)...］ボタンから起動されるファイル選択ダイアログにて
	　　「ALT-HWLib-All-In-One_vXX.X_r○.tar.gz」を選択します。
		↓
	４．「終了(F)」を実行してインポートを完了します。
		↓
	５．ALT-HWLib-All-In-One_vXX.X_r○ の中に格納してある
	　　config.mk ファイル内の ENABLE_EXAMPLE_TIME の定義を "1" に設定してプロジェクトをビルドすると、
	　　ターゲットボードの DIP スイッチを 「Command モード」 に設定してコンソールから "time" コマンドを入力することにより、
	　　util/cmd.c 内から sample_time_measurement.c の sample_time_measurement_test_cmd() 関数が呼び出されます。

　# ENABLE_EXAMPLE_TIME    : sample_time_measurement.c
　ENABLE_EXAMPLE_TIME      := 1


　　②．ALT-HWLib-All-In-One_vXX.X_r○ プロジェクトをビルドします。
　　~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	１．ALT-HWLib-All-In-One_vXX.X_r○ プロジェクトの config.mk を必要に応じて修正します。
		↓
	２．プロジェクト・エクスプローラ上で ALT-HWLib-All-In-One_vXX.X_r○
	　　の右クリックメニューから「プロジェクトのビルド(B)」を実行します。

　　③．デバッグを実行します。
　　~~~~~~~~~~~~~~~~~~~~~~~~
	１．SoC EDS（DS）のメニューから「実行(R) -> デバッグの構成(B)...」を実行します。
		↓
	２．デバッグの構成ダイアログ上で、左側のツリー上で
	　　「DSデバッガ -> ALT-HWLib-All-In-One_vXX.X_r○」が選択された状態にします。
		↓
	３．接続タブの［参照...］ボタンからデバッグハードウェアの選択ダイアログを起動して、
	　　適切な Connection を選択します。
	　　（例えば、Atlas ボードと USB-Blaster II 接続なら「DE-SoC on localhost[USB-1]:DE-SoC USB-1」）
		↓
	４．［デバッグ(D)］を実行すると、プログラムがロードされた後に sample_app.c 内の main() でブレイクします。
	　　以降、デバッガで動作をご確認下さい。　


-- 詳細（sample_time_measurement_test_cmd() 以降） ----------------------

◎ sample_time_measurement_test_cmd() 関数内の下記の記述にて、サンプルコードを呼び出しています。
　　//// Sample Function Call!!! |---->
　　printf(">>>> Execute sample_time_measurement_init(); !!! <<<<\r\n");
　　sample_time_measurement_init();
　　
　　printf(">>>> Execute sample_time_measurement_test_main(); !!! <<<<\r\n");
　　sample_time_measurement_test_main();
　　//// Sample Function Call!!! <----|


◎ 各サンプル関数の概要を示します。

sample_time_measurement_init();
	→ ターゲット・ボードの HPS 用 DIPSW, PUSHSW のための GPIO 設定を行います（テストプログラム操作用）。
	→ 時間計測処理の初期化（void util_time_init）を呼び出します。

sample_time_measurement_test_main();
	→ 無限ループを行い、HPS 用 PUSHSW、 DIPSW の操作を契機に下記の処理を呼び出します。
	　- DIPSW[3:0] .. 計測対象識別用の index 値として利用します。
	　- PUSHSW0    .. 計測結果の全件表示を行い無限ループから抜けます（util_time_print_result_all）（テストを終了します）。
	　- PUSHSW1    .. 計測結果の全件表示とクリアを呼び出します（util_time_print_result_all_and_clear）。
	　- PUSHSW2    .. DIPSW を index 値として計測開始を記録（util_time_record_start_point）。
	　- PUSHSW3    .. DIPSW を index 値として計測終了を記録し、1 件分の計測結果を表示します（util_time_record_end_point、 util_time_print_result_by_counter、 util_time_print_result_by_seconds）。

★ ポイント ★
無限ループ処理が走っている状態で、PUSHSW2 を押した後、任意の秒数待機した上で PUSHSW3 を押してみて下さい。
計測結果として、待機した時間に応じた時間が表示されます。

【実行時のアプリケーションコンソール】
───────────────────────────────────────────
==== Start While(1) loop process!!! (Exit PUSHSW0(SW8) becomes ON.) ====　　<--- 無限ループ開始の表示 
　　：
-- test : util_time_record_start_point(1) --　　<---- PUSHSW2 押下で表示されます。
-- test : util_time_record_end_point(1) --　　　<---- PUSHSW3 押下で表示されます（以下の結果表示も PUSHSW3 契機）。
-- test : util_time_print_result_by_counter(1) --
== Time Mesurement Result by Counter ==
[TIME# 1]
 - Progress of GlobalTimerCounter: 349495959
   [Start=0x0000000A82E4621B, End=0x0000000A97B944B2]

-- test : util_time_print_result_by_seconds(1) --
== Time Mesurement Result by Seconds ==
[TIME# 1]
 - Elapsed Seconds (nsec): 3.494959 (3494959590)　　<---- 計測結果"秒数"の表示。ここが待機時間と ≒ になります。  
───────────────────────────────────────────

------------------------------------------------------------------------
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 以上 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
