Cmod A7ボード(FPGA)を使って、オリジナル16ビットCPUコアMoscoviumの開発を進めています。
独自仕様のマイコンだけではなく、その開発環境としてBlockly for Moscoviumの整備も進めてきました(詳細はこちらから)。今回は、Blocklyで数学関数を使うための拡張がテーマです。
Moscovium用に数学関数を整備した以下記事がありますので、それを基本として、Blocklyに実装して行こうと思います(以下リンク参照)。
「#16-9 数学関数を整備しよう」
上の記事では、半精度浮動小数演算コプロセッサH-FPUを使いました。半精度浮動小数は16ビット長で、10進数換算の有効数字約3桁です。有効数字が小さいため、テイラー展開で実装するにも、より少ない項数で収束していました。
Blockly for Moscoviumは、Nihoniumコア+単精度浮動小数演算コプロセッサS-FPUにも、対応しています。つまり、上の記事では半分(H-FPU)しか対応しておらず、S-FPU対応が未実施です。
単精度浮動小数は32ビット長で、10進数換算の有効数字約7桁なので、テイラー展開の項数を少し多くとれば良いだけかな?と、言う印象です。今回、テイラー展開の項数以外に考慮する必要のあった、指数exp()関数についての追加考察をしておきます。
exp()関数の求め方については、引数xの整数部分と小数部分に分けてexp()関数を計算するという方法までは解説済みです。以下にまとめておきます。
exp (xi)はネイピア数eとした時、√eの正数べき乗なのでループを回して掛け算すれば良い、と、結論しておりました(こちらの記事を参照)。確かにH-FPU版ならば、そういう手もあったかもしれないのですが、それでも最大23回(※)もの掛け算が必要です。1回のexp()関数を求めるのに、これではあまりに遅すぎて使い物になりません。
H-FPU版では、使い得るxi値の範囲が高々24個だったため、16ビット×24個=48バイトのテーブル参照で実装しました。
※16ビット半精度浮動小数では、int (2×x)≧23で、exp (xi)→∞に発散する為。
一方、S-FPUでは、int (2×x)が178以上でexp (int (2×x)÷2)→∞(無限大、INF)へ発散します。つまりS-FPU版では、なんと、最大178回の掛け算が必要となります。更に輪をかけて遅くなります。看過できません。
H-FPU版と同様なテーブル参照に持ち込むと、32ビット×178個=712バイトのテーブルが必要となり、これも少々否定的です(テーブルサイズが大き過ぎます)。何か別な手段でexp (xi)を求める必要が生じました。
そこで、Aa1+a0=(Aa1)×(Aa0)の関係式を使う事にしました。
最大178回の乗算が、最大8回の乗算に帰着しました。
bjで場合分けした最後の式に於いて、bj=0または1です。exp (2j−1)は定数なのでテーブル参照に持ち込むことができます。テーブルサイズは32ビット×8個=32バイトと、こちらも現実的なサイズですね。これで実現可能な水準に到達しました。
テイラー展開等を使って求める「基本関数」と、基本関数の組み合わせで求めることのできる「派生関数」に分類してみると以下となります。
ああ、派生関数の何と多き事か!こちら「#16-9 数学関数を整備しよう」の記事では、基本関数だけを作っておいて、派生関数については「各自対応」って、ことで放置していました。今回はBlocklyに組み込もうというのですから、派生関数も全部作らないとなりません。
作り方は解っているので「作業だけ」、なのですが、評価(デバッグ)は必要だったし、地味に疲れました……。
関数を求めるプログラムはランタイムライブラリとして、アセンブラで記述しておきました。以下、Blocklyに適応させて行きたいと思います。
今回追加しようとするのは計12種類の関数です。ドロップダウンリストが長くなると使い難いと思いますので、適切な数に分割して実装します。形式や関連性などに従って、以下3種類に分類してみました。
上の分類に従って、BlocklyのMathカテゴリに以下の通り追加しました。
動作仕様などについての詳細は、こちらのリンクからご確認ください。
Blockly.XML→Moscovium.ASM変換スクリプトを更新すると共に、数学関数ライブラリを追加しました。まとめて、こちらからダウンロードしてください。
以下のバナーからGitHubを参照しても、必要ファイルにアクセスする事が可能です。
Blockly for Moscovium開発環境の構築については、こちらの記事をご参照ください。
追加した数学関数ブロックを評価(デバッグ)するために以下プログラムを作成しました。
実験用プログラム:test_func_plot.xml
※ブラウザによっては、XMLファイルをレンダリングして表示してしまうので、「右クリック ⇒ リンク先を保存」などしてください。
Blockly for MoscoviumのXMLタブに貼り付けて、ご利用ください。Blockly.XML→Moscovium.ASM変換手順を参照して、Moscoviumマイコンに書き込んでください。
数学関数ブロックを使って、指定範囲の関数値を計算して表示するプログラムと、なっています。出力された数値データをExcel等に貼り付けると、グラフを描いたり期待値との比較が実行できます。
FPUを搭載したMoscoviumまたはNihoniumマイコン(例えば以下)のデザインでシミュレーションして、評価します。Vivadoを使ったシミュレーションの実行方法についてはこちらをご覧ください。
FPU搭載マイコン例:
半精度浮動小数演算コプロセッサH-FPU用の数学関数の評価については、こちら「#16-9 数学関数を整備しよう」の記事で実施済みなので省略します。単精度浮動小数演算コプロセッサS-FPUでの評価を実施してみましょう。
実験サンプル:シミュレーション結果ログ
PLOT
00000000 00000000
3da14285 3e8fabb0
3e214285 3ecb2e56
3e71e3c7 3ef8d84a
:
: (中略)
:
411c3870 4047fb28
411d7af5 4048c92d
411ebd7a 4049965f
41200000 404a62c1
END
Test Pass
CPI: 39385/ 22961( 0)= 1715/1000
finish: 1595240 ns
ログ出力されたのは、32ビット単精度浮動小数のバイナリデータです。VivadoのVerilogシミュレータで浮動小数を表示すると有効数字6桁ほどに丸められてしまい、期待値との比較で誤差の評価ができない(※)ため、バイナリデータで出力しておいて、適切な有効数字の浮動小数に変換して評価を実施しました。
※単精度浮動小数float型の有効数字は約6.9桁なので、6桁では桁数不足。
S-FPUでの評価結果をド〜ン🎆と、以下図に示して考察を続けます。
評価結果考察:
「地味に疲れた」理由がご理解いただけたら幸いです(1^^;)。
皆様のアプリケーションで、どの様な浮動小数演算が必要なのか?は存じ上げませんが、一通りの数学関数を用意したので、大抵の用途には耐え得るはずです。Good job → 自分d(1^−^)v。