tag:blogger.com,1999:blog-19367002173466925152024-03-19T17:41:30.472+09:00Shts!まぁなんかいろいろ作ってますShtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.comBlogger100125tag:blogger.com,1999:blog-1936700217346692515.post-51927056542495820242023-05-20T12:10:00.002+09:002023-05-20T12:43:29.036+09:00NNCase V1.7を試す話(実機実行編)<script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<br /><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCYn-2e8qtZa3L3TIGHzSuTDI6tdqK5YMBJsQL1oLdC39oQusQ_wBwIkIh1cPW8qMknmDAwLV4jucWLOVBX6D2KExK5iRJ1UQY5ElXEKVhUoypWrc1g43gi1LhL3D09yafMiPkKKw0g7J05fre6uEzPWPqlHpHMdtAebXBxRb_19anbWFNJQtRavMd/s5456/DSC00920.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3632" data-original-width="5456" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCYn-2e8qtZa3L3TIGHzSuTDI6tdqK5YMBJsQL1oLdC39oQusQ_wBwIkIh1cPW8qMknmDAwLV4jucWLOVBX6D2KExK5iRJ1UQY5ElXEKVhUoypWrc1g43gi1LhL3D09yafMiPkKKw0g7J05fre6uEzPWPqlHpHMdtAebXBxRb_19anbWFNJQtRavMd/w400-h266/DSC00920.JPG" width="400" /></a></div><br /></div><div><a href="https://www.shtsno24.tokyo/2023/05/nncase-v17sim.html" target="_blank">前回のSim実行編</a>にて、NNCaseのSimが動くところまで確認しました。今回はその続きで、実機で動かす話になります<div></div></div><div><br /></div><div><h1 style="text-align: left;">1.テスト環境</h1><div>今回の環境(ホスト)は以下の通りです</div>
<ul style="background-color: white; color: #666666; font-family: "Trebuchet MS", Trebuchet, Verdana, sans-serif; font-size: 13.2px; line-height: 1.4; margin: 0.5em 0px; padding: 0px 2.5em;"><li style="margin: 0px 0px 0.25em; padding: 0px;">RPi4 4GB(Raspbian 11:bullseye)</li><li style="margin: 0px 0px 0.25em; padding: 0px;">Docker(23.0.5, build bc4487a)</li><li style="margin: 0px 0px 0.25em; padding: 0px;">NNCase(v1.7.1)</li><li style="margin: 0px 0px 0.25em; padding: 0px;">nncaseruntime(v1.7.1)</li><li style="margin: 0px 0px 0.25em; padding: 0px;">kendryte-standalone-sdk</li><li style="margin: 0px 0px 0.25em; padding: 0px;">kendryte-gnu-toolchain</li></ul>
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<div>基本的な流れとしては、toolchainを入れてからstandalone-sdkを入れ、nncaseのruntimeを入れる形となります</div><div><br /></div><div>またK210のボードとして、Maix Bitを使いました</div><div><a href="https://wiki.sipeed.com/hardware/zh/maix/maixpy_develop_kit_board/maix_bit.html" target="_blank">Sipeedのプロダクトページ</a><br /><a href="https://www.switch-science.com/products/5702" target="_blank">スイッチサイエンスの販売ページ</a></div><div><a href="https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-5JE5" target="_blank">千石電商の販売ページ</a></div><div><br /></div><div><br /></div><h1 style="text-align: left;">2.インストール</h1><div>まずはtoolchainのインストールからになります。</div><div>
<pre><code>$ git clone --recursive https://github.com/kendryte/kendryte-gnu-toolchain
$ cd /kendryte-gnu-toolchain/riscv-gcc
$ ./contrib/download_prerequisites
$ cd /kendryte-gnu-toolchain
$ ./configure --prefix=/opt/kendryte-toolchain --with-cmodel=medany --with-arch=rv64imafc --with-abi=lp64f
$ make -j4
</code></pre>
今回は/opt/kendryte-toolchainに突っ込みました。次にsdkを入れます。</div><div>
<pre><code>$ git clone https://github.com/kendryte/kendryte-standalone-sdk
</code></pre>
</div><div>kendryte-standalone-sdk/srcにビルドしたいプロジェクトを突っ込んでいくみたいです。最後にnncaseruntimeを入れていきます。</div><div><pre><code>$ wget https://github.com/kendryte/nncase/releases/download/v1.7.1/nncaseruntime-k210.zip -P ./kendryte-standalone-sdk/lib/nncase/v1
$ unzip -o ./kendryte-standalone-sdk/lib/nncase/v1/nncaseruntime-k210.zip -d ./kendryte-standalone-sdk/lib/nncase/v1</code></pre></div><div>sdkのディレクトリにsrc/lib/nncase/v1があり、この中にruntimeを入れている格好になっています。アップデートの際にはここを上書きすることで対応することができます。</div><div>参考:<a href="http://blueeyes.sakura.ne.jp/2021/05/20/4032/" target="_blank">とりあえずKendryte K210に触れる(1) - 環境構築</a></div><div><br /></div><h1 style="text-align: left;">3.コンパイル</h1><div>前回のSim実行環境の<a href="https://github.com/shtsno24/k210_yolox_example" target="_blank">サンプルコードと実機用のコード</a>をまとめたものを上げておきます。</div><div>build_yolox.sh内のcompile_pathをsdkの場所に書き換えることで実行できるはずです。</div><div>差分としては、Maix Bitのへの対応がメインになります。</div><div>コンパイルをすると、モデルの変換結果や実機に入れるbinなどが生成されます。</div><div><br /></div><div>参考:<a href="https://github.com/kendryte/nncase/tree/v1.7.1/examples/yolox">https://github.com/kendryte/nncase/tree/v1.7.1/examples/yolox</a></div><h1 style="text-align: left;">4.実行結果<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtdbr361cKpwVbK25QDwVy0Zo1NdN5fgiYfEAfDgM-rBXdV7yEpQ_3tUSr3RpkUIJPBojzGPAr8Z47-9gCR8dFkn4m8i34I-Zrpf3GOmbR1UA4nLP0v9CvJehjElj3jZbp3ZdjBP5XAncK6FfnSoj3u7kCNYJlc3tWwwITz7WUsSM7kq7BhzjT5iL1/s5456/DSC00920.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="3632" data-original-width="5456" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtdbr361cKpwVbK25QDwVy0Zo1NdN5fgiYfEAfDgM-rBXdV7yEpQ_3tUSr3RpkUIJPBojzGPAr8Z47-9gCR8dFkn4m8i34I-Zrpf3GOmbR1UA4nLP0v9CvJehjElj3jZbp3ZdjBP5XAncK6FfnSoj3u7kCNYJlc3tWwwITz7WUsSM7kq7BhzjT5iL1/w400-h266/DSC00920.JPG" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">実機実行の結果。Simと微妙に異なる</td></tr></tbody></table></h1>実際に動かすとちゃんと認識していることが分かるかと思います。しかしながら<a href="https://www.shtsno24.tokyo/2023/05/nncase-v17sim.html" target="_blank">Sim結果</a>とは異なっている部分もあり、何起因の差分化は考える必要がありそうです。</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTU_HFPqCBuaQMVVnkXHfi2xB8dsaCjef50dQPjBkp4D82Mi8-7QkR3UZhoJ1QB7SttG5cXGWIeu_1BYw9iTd_pRoLFLVbDOJEN2cCsTqnI3KLbwzpN1JrMhHnIc5EeM48uBN8NhmCBwLzEMZGmM6yH-fCEST1fpsG_e5qT8wnai10Jiea7Npmru9r/s467/nncase_v1_aarch64.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="436" data-original-width="467" height="374" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTU_HFPqCBuaQMVVnkXHfi2xB8dsaCjef50dQPjBkp4D82Mi8-7QkR3UZhoJ1QB7SttG5cXGWIeu_1BYw9iTd_pRoLFLVbDOJEN2cCsTqnI3KLbwzpN1JrMhHnIc5EeM48uBN8NhmCBwLzEMZGmM6yH-fCEST1fpsG_e5qT8wnai10Jiea7Npmru9r/w400-h374/nncase_v1_aarch64.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">実行結果(UART)<br />1回目実行では1100ms程度かかるらしい</td></tr></tbody></table><br /><div>実行速度は1100ms程度のようでした。起動直後の1回しかは測定していないので、もう少し条件を詰めて確認する必要があるかと思われます。</div><div><br /></div><div><h1 style="text-align: left;">5.まとめ</h1><div><br /></div><div>今回は<a href="https://www.shtsno24.tokyo/2023/05/nncase-v17sim.html" target="_blank">Sim編の続き</a>として実機実行までの流れをやってみました。とりあえずどんな感じで動かせばよいかぐらいは分かったかと思います。この話の発展として別のDNNモデルを実行したり、性能改善を行ったり、カメラをつけて実行等があるかと思いますが、今回はここまでにしたいと思います。</div>
<br /><br /><br />
<div style="text-align: center;">
©2023 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div><br /><br />Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-4264815836849915382023-05-02T12:25:00.002+09:002023-05-20T12:10:53.735+09:00NNCase V1.7を試す話(Sim実行編)<div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuRhMWxVTL7Vso0SEA5URvjzBatGPdXXnFoKefXeTV7pl3Cig_3kqxheOEDuIawJB8roZ6iPdpgNuXwUN2NqOm29n7ZlacmSxl-gMqHGZm4GmUig58ZI21YF7ugvaXVSS_VpZlj4-89dXRTeZLsTGQxir9CmpxMm7ALHBjzCtj0xkAjYIMBS624hQo/s5456/DSC00920.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3632" data-original-width="5456" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuRhMWxVTL7Vso0SEA5URvjzBatGPdXXnFoKefXeTV7pl3Cig_3kqxheOEDuIawJB8roZ6iPdpgNuXwUN2NqOm29n7ZlacmSxl-gMqHGZm4GmUig58ZI21YF7ugvaXVSS_VpZlj4-89dXRTeZLsTGQxir9CmpxMm7ALHBjzCtj0xkAjYIMBS624hQo/w400-h266/DSC00920.JPG" width="400" /></a></div></div><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<br />
社会人2年目になり業務量が増えてきた中の人です。今回は<a href="https://www.shtsno24.tokyo/2022/12/2022.html" target="_blank">以前やっていたが公開していなかった</a>NNCaseのv1.x系(kmodel v5)を試す話になります。<div>2023/5/20追記:<a href="https://github.com/shtsno24/k210_yolox_example/tree/master" target="_blank">サンプルコードを公開</a><br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">1.NNCase v1.xの特徴</h1><div>以前のバージョンと比較した際の一番の変更点としては、従来のコマンドラインベースのものからPythonの1ライブラリとしての実装に変更されています。kmodelの元ネタになるonnxやkerasのモデルを生成するコードに追加することもできます。ビルド済みのwhlが公式から提供されており、CPUはx86-64、OSはWin/Linux/Mac版があります。</div><div>これ以外の点では、対応する演算の種類が増えている、K210の上位機種に当たるK510への対応といった部分のアップデートがなされています。これに合わせる形?でkmodelのバージョンもv5に上がっています。</div><div><br /></div><h1 style="text-align: left;">2.テスト環境</h1><div><br /></div><div>今回の環境は以下の通りです。</div><div><ul style="text-align: left;"><li>RPi4 4GB(Raspbian 11:bullseye)</li><li>Docker(23.0.5, build bc4487a)</li><li>NNCase(v1.7.1)</li></ul></div><div>NNCaseのv1.xはarm64に対応するwhlを出していないのですが、中身を一部変更してビルドしました(基本的にはx86-64と同じコードになります)。またビルドのデバッグがやりたかったので、Docker環境にねじ込みました。今回はK210を動かすところまではいかないので、NNCaseのみの紹介にします</div><div><br /></div><h1 style="text-align: left;">3.インストール</h1><div><br /></div><div>x86-64環境であればインストールは簡単で、<a href="https://github.com/kendryte/nncase/releases/tag/v1.7.1" target="_blank">公式のリリース</a>からwhlを持ってきてインストールするだけになります。(今回試しているarm64の場合は自前でビルドする必要が出てくるので面倒でした)</div><div><br /></div><div><h1>4.コンパイルとSim実行</h1><div><br /></div><div>v1.7.1でのコンパイルとSim実行手順は<a href="https://github.com/kendryte/nncase/tree/v1.7.1/examples/yolox" target="_blank">基本的にはここ</a>にいろいろ書いてあります。このディレクトリを手元に落としてきて動かすのが最初はよいかと思います。<br />このディレクトリは以下のような感じになっています。
<pre><code>.
|- tools:モデルの変換とSimを実行するためのコード
|- images:入力画像
|- model:もとになるモデル(onnx)
|- cpu
`-k210:実機実行用のコード
</code></pre>
</div><div>README.mdを見たところ、画像の入ったディレクトリを見に行くオプションがすべてimagesではないところだったのですが、手元で試したところimagesに変更しても動くことが分かりました。</div>
<pre style="text-align: left;"><code>python tools/compile.py model/yolox_nano_224.onnx yolox_nano_224_quant.kmodel --imgs_dir ./images/ --legacy --target k210<br />
python tools/simulate.py yolox_nano_224_quant.kmodel ./images/dog.jpg</code></pre>
</div><div style="text-align: left;">環境内でmatplotlibの表示機能が使えるのであれば、Sim結果としてこんな感じの画像が得られるはずです</div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDNajoMhtz4VOF2_EVcSklHPBeE5D8reNnPyzdE_Pc_qsVcDjpKQxFka2eDKRdbsAj27C7MkLs9RWWqz6boXtLG1SG-GkKKiaz569njGzko5TlRgujMF9pkUk9P-uC-0Odcr-dPmzBauLnDWEDR1DFeAd8W7gLI7SMvxefm187oCDU9a0GqEjs5wH1/s640/sim_result.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="480" data-original-width="640" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDNajoMhtz4VOF2_EVcSklHPBeE5D8reNnPyzdE_Pc_qsVcDjpKQxFka2eDKRdbsAj27C7MkLs9RWWqz6boXtLG1SG-GkKKiaz569njGzko5TlRgujMF9pkUk9P-uC-0Odcr-dPmzBauLnDWEDR1DFeAd8W7gLI7SMvxefm187oCDU9a0GqEjs5wH1/w400-h300/sim_result.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Sim結果<br />実機実行の結果とは異なるので要注意</td></tr></tbody></table><div style="text-align: left;"><br /></div><div style="text-align: left;"><h1 style="text-align: left;">5.まとめ</h1><div style="text-align: left;"><br /></div><div style="text-align: left;">今回はNNCase v1.7を使ってSimを実行してみました。変なことをしなければすんなり動くはずであり、K210の実機が無くても結果が確認できるのでお手軽に試せるかと思います。</div><div style="text-align: left;"><a href="https://www.shtsno24.tokyo/2023/05/nncase-v17.html" target="_blank">次回はK210搭載のボードを使って実機実行していきたい思います</a>。</div><br /><h1 style="text-align: left;">n.おまけ</h1><div><br /></div><div>以前使っていたM5StickV+MaixPyの組み合わせではkmodelのv5に対応していなかったのですが、まさかの<a href="https://github.com/kendryte/canmv" target="_blank">kendryteがMaixPyではない別のツールを作って対応しようとしていました</a>。(boardのディレクトリにm5stick的なものがあったが、M5StickVで動くかどうかは不明)。</div><div><div>参考1:<a href="https://github.com/sipeed/MaixPy/issues/434">https://github.com/sipeed/MaixPy/issues/434</a></div><div>参考2:<a href="https://github.com/kendryte/canmv">https://github.com/kendryte/canmv</a></div><div><br /></div></div><div>
<div style="text-align: center;">
©2023 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div></div><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><br /></div>Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-89635384641656468252023-02-05T16:43:00.002+09:002023-02-05T16:45:29.655+09:00Verilator使ってみた<script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br /><div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJygUsztZHCRuNTHrI-OXOZn20W2UtyXK7fssG6j8-DHkKNZ1wQbEvDvHp78wfvwBg0UpLaGalim2dRYhIqA5agrzArhfXwi-4yeIbW95IWUVJlG3DEFSkziF5J8IZPYhNteCDWNs0z1IcnSqHWOlPQIr-QNpBK_yUtnlAHPw1ABTD0JDKyjtXRhQb/s256/verilator_256_200_min.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="200" data-original-width="256" height="313" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJygUsztZHCRuNTHrI-OXOZn20W2UtyXK7fssG6j8-DHkKNZ1wQbEvDvHp78wfvwBg0UpLaGalim2dRYhIqA5agrzArhfXwi-4yeIbW95IWUVJlG3DEFSkziF5J8IZPYhNteCDWNs0z1IcnSqHWOlPQIr-QNpBK_yUtnlAHPw1ABTD0JDKyjtXRhQb/w400-h313/verilator_256_200_min.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><a href="https://www.veripool.org/verilator/">https://www.veripool.org/verilator/</a>より引用</td></tr></tbody></table><div class="separator" style="clear: both; text-align: center;"><br /></div>Verilog初心者の中の人です。今回はVerilogシミュレーションツールであるVerilatorをお試ししてみました。またこのツールの売りであるSim実行速度を簡易的に計測したので、併せて紹介します。<br />
<br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">1.Verilatorとは何か</h1><div><a href="https://www.veripool.org/verilator/" target="_blank">Verilator</a>はVerilog/SystemVerilog向けのRTLシミュレーションシステムの一種になります。LGPL3/Artistic License2.0で配布されており商用利用も可です。この手のツールは大体がライセンス必須のクローズドソースであることが多いですが、Verilatorはその点で異なったものになります。Verilatorの売りはSimの実行速度であり、有償のツールと同等かそれ以上の性能が出ると主張しています[<a href="https://github.com/verilator/verilator#performance" target="_blank">1</a>]。</div><div><br /></div><h1 style="text-align: left;">2.お試ししてみる</h1><br /><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeR9wW9LrU6bf1Qq4Pc5I9XVaL4xB-PVVZsYhf8LTR60L4m-ekErSHV9zjhO87Nv0xeIpAw6QjUzYEfgevhUBEP9yZC5h1XLaNwUgGKCX3ye7lW2vD6i6yPW5YmTkWYk3cifuzpfj-SP5Tw_QGLMoc89wZAe77gPBxpO2NDycPiSRLJvQ4ie6YpN5b/s1920/Verilator_test3.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1150" data-original-width="1920" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjeR9wW9LrU6bf1Qq4Pc5I9XVaL4xB-PVVZsYhf8LTR60L4m-ekErSHV9zjhO87Nv0xeIpAw6QjUzYEfgevhUBEP9yZC5h1XLaNwUgGKCX3ye7lW2vD6i6yPW5YmTkWYk3cifuzpfj-SP5Tw_QGLMoc89wZAe77gPBxpO2NDycPiSRLJvQ4ie6YpN5b/w400-h240/Verilator_test3.png" width="400" /></a></div><br /></div><div>今回は簡単なUART送信回路を作成し、そのテストベンチをVerilatorで書いてみました。</div><div>(<a href="https://github.com/shtsno24/Verilator_Test" target="_blank">コードはこちらから</a>)</div><div>今回は<a href="https://msyksphinz.hatenablog.com/entry/2020/05/06/040000" target="_blank">FPGA開発日記さんの記事</a>を参考にしながら、.vcdの波形出力まで行うテストベンチを書きました。またUART送信回路自体は、FPGA上での実機動作が確認できているものを流用しました。書いてみた感想としてはTB本体の準備はそこまで差がないのですが、Verilator(C++)の方が入力するデータの準備や出てきたデータを料理が楽でした。また実行時間もVerilogのTBを実行していた時と比べ何となく速い気がしました。</div><div><br /></div><h1 style="text-align: left;">3.Verilog版TestBenchとの比較</h1><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikyCJof0Fm_P5AWR65PkXi717bQBRi1dA-JF93EkINHhaW91bj8B_kHUxTZ3lR5Xx_jKdFuDgERYv7oSJB4_gORqDpNJ_9k_Vgr3RdA5ci5aSUb-crFxGQgvZueOqaytMGWQ3eXF6sRlEMTxgQRe-kkjZgHRaGE9JS8FmsNErxepXEPjJxiJ8iNR_u/s1797/Verilator_test5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="805" data-original-width="1797" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikyCJof0Fm_P5AWR65PkXi717bQBRi1dA-JF93EkINHhaW91bj8B_kHUxTZ3lR5Xx_jKdFuDgERYv7oSJB4_gORqDpNJ_9k_Vgr3RdA5ci5aSUb-crFxGQgvZueOqaytMGWQ3eXF6sRlEMTxgQRe-kkjZgHRaGE9JS8FmsNErxepXEPjJxiJ8iNR_u/w400-h179/Verilator_test5.png" width="400" /></a></div><div><br /></div><div>実行時間が体感で速そうだったので、実際に計測してみました(Verilator公式でも高速実行アピールがあるので、本当だとは思っていましたが)。計測方法としては、対象回路に対して同じタイミングで信号を印加するTBをVerilogとVerilator(C++)で準備し、Simにかかった時間をパラメータごとに10回計測し均しました。計測の諸条件は以下の通りです。</div><div><ul style="text-align: left;"><li>PC:XPS13(9310)</li><li>CPU:Intel Corei7-1185G(3GHz)</li><li>RAM:16GB</li><li>OS:Ubuntu 20.04.5 LTS (GNU/Linux 5.4.72-microsoft-standard-WSL2 x86_64)</li><li>Icarus Verilog version 10.3</li><li>Verilator 5.005 devel rev v5.004-76-g5ef373500</li><li>g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0</li><li>Sim内で変わるパラメータは終了ステップ数のみ(100スタートで10倍毎に計測)</li><li>実行時間はLinuxのtimeコマンドで計測</li><li>.VCDファイル生成時間を両者ともに含む</li><li>コンパイラの最適化設定は両者デフォルトの状態</li></ul></div><div>実測結果は以下のようになりました。</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqybdgpHLxiIKaYb9I66EUUbfXeomZ5u6v0XApBWkYyx3mh8FrRQjShvqKYGy9XV97FlTTL0UJ2Y3bN26HcQ_j9xaNm7R58SJr2Nx18e-uvnyVPIoncrLIAs8FWfOJGrGW4J6dEY5lZoww9GSDVVoxCCczDFnP87AOCOi8Kdiwccis4gbyK-vYozd8/s1600/analysis_result_log.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="900" data-original-width="1600" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqybdgpHLxiIKaYb9I66EUUbfXeomZ5u6v0XApBWkYyx3mh8FrRQjShvqKYGy9XV97FlTTL0UJ2Y3bN26HcQ_j9xaNm7R58SJr2Nx18e-uvnyVPIoncrLIAs8FWfOJGrGW4J6dEY5lZoww9GSDVVoxCCczDFnP87AOCOi8Kdiwccis4gbyK-vYozd8/w400-h226/analysis_result_log.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">x軸実行ステップ、y軸実行時間のグラフ<br />(両対数グラフなことに注意)</td></tr></tbody></table><div><br /></div><div>このグラフから実行ステップ数が短いとVerilatorを使ってもそこまで高速化の恩恵が得られないのですが、ある程度以上のステップ数になるとVerilatorの方が10倍のオーダで高速に実行できそうなことが分かりました。(<a href="https://github.com/shtsno24/Verilator_Test/blob/master/UART_COPI/log/analysis_result.log" target="_blank">生データはこちら</a>)</div><div><br /></div><h1 style="text-align: left;">4.その他</h1><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5B_Pod53bKyORH4ZsmjT_q3-g9Ml3Fp8llZaYfH3_UHMBW59bHuQrKSGq9U1ppUrlEwnd_QfmJiDngk7mqHkLEBM4zy3nK3N-HJRbPAmaYKLRkbWCKZL9fzjjXg5ZNoArRDo2McSUdyOFDhR_Arw28bmVdl5L6iAionXerbtUaMveXq7tkzo1LDU6/s1450/Verilator_test6.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="366" data-original-width="1450" height="101" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5B_Pod53bKyORH4ZsmjT_q3-g9Ml3Fp8llZaYfH3_UHMBW59bHuQrKSGq9U1ppUrlEwnd_QfmJiDngk7mqHkLEBM4zy3nK3N-HJRbPAmaYKLRkbWCKZL9fzjjXg5ZNoArRDo2McSUdyOFDhR_Arw28bmVdl5L6iAionXerbtUaMveXq7tkzo1LDU6/w400-h101/Verilator_test6.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">不定が扱われない様子<br />(左:Verilog、右:Verilator)</td></tr></tbody></table><div><br /></div><div>Verilog側で出ていた出力波形の不定がVerilator側では出ていないことに気が付きました。これはVerilatorが信号を4値(0, 1, Z, X)としてではなく2値(0, 1)として扱うことに起因しているようです[<a href="https://msyksphinz.hatenablog.com/entry/2017/11/25/153211" target="_blank">2</a>]。不定伝搬等を検出するためにはいくつかの工夫が必要だと思われます。</div><div><br /></div><div>
<div style="text-align: center;">
©2023 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div><br />Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-27674085595661090762022-12-31T22:07:00.003+09:002022-12-31T22:16:38.469+09:002022年にやったことまとめ<div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFIDc4EeNhTDCB0moms2UMyUd1uvZF3Dl5khumWjEbnapyHhDZpe26WxOawsRWhfRGlAiCmdPTGqI9Pl0SVGI3S-NibMjqB2oTP7_BJv2C741DZpWguG1zvC1RMRwkXWxsEBNG2Zvjvtt2vgtB_Ph_CAtHtWOamHoALsNBqcPIgiwcrqIdPXUN4R_r/s4032/IMG_5028~photo.HEIC" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFIDc4EeNhTDCB0moms2UMyUd1uvZF3Dl5khumWjEbnapyHhDZpe26WxOawsRWhfRGlAiCmdPTGqI9Pl0SVGI3S-NibMjqB2oTP7_BJv2C741DZpWguG1zvC1RMRwkXWxsEBNG2Zvjvtt2vgtB_Ph_CAtHtWOamHoALsNBqcPIgiwcrqIdPXUN4R_r/w400-h300/IMG_5028~photo.HEIC" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">手が滑って買ったオシロ</td></tr></tbody></table></div><br />
5月以来の更新になった中の人です。社会人になり休日のありがたみを実感しているこの頃であります。今回はブログに載せていないものも含めて、2022年に作ったものを振り返る話になります。
<br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">
1.PYNQとVitis HLSで作るFMA演算IP</h1><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzAKY3nPjSTxF6SMIqtbOJb_ILsTK5He5AN4frBEMnHOsfAVmzt_uO83Q_mIaCuseJKsDORrsLuPgx_DOrx4FcIqbKeD5yVSoUOkx-Jp2IELpyDMozPTXlhGO196ZWLKbEltiZNcn3bcHD8Jt4XeGS3Fe2Wad1xuWADppzsgMZb5gMKZdUJ6HZkgLJ/s3143/IMG_4446.HEIC" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="2357" data-original-width="3143" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzAKY3nPjSTxF6SMIqtbOJb_ILsTK5He5AN4frBEMnHOsfAVmzt_uO83Q_mIaCuseJKsDORrsLuPgx_DOrx4FcIqbKeD5yVSoUOkx-Jp2IELpyDMozPTXlhGO196ZWLKbEltiZNcn3bcHD8Jt4XeGS3Fe2Wad1xuWADppzsgMZb5gMKZdUJ6HZkgLJ/w400-h300/IMG_4446.HEIC" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">テストで使用したFPGA(PYNQ-Z2)</td></tr></tbody></table><div><br /></div><div>一応ブログとして挙げたネタなのでそこまで詳しく解説はしないのですが、FMA用のIPを高位合成で作成して性能評価を行った話でした。</div><div><a href="https://www.shtsno24.tokyo/2022/03/pynqvitis-hlsfmaip1hls.html" target="_blank">記事へのリンク</a></div><div><br /></div><h1 style="text-align: left;">2.Rust初心者が、Rust+RPi PicoでST7789使用TFT LCD(Waveshare Pico LCD 1.3)を使う話</h1><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4LJHMV_3IVuO35LiEGtqR5a1CWW-qckXy834g7dJBJzGfdzyCBIxIjmcFjK0Hk9FV0W-sz6kmeJocqkIWuqNYmblUZ5g2BKjvQxMshFSpGGDtJltKC11iwfE0tWSX73AN9RJGHbY-k_qIDt_IlY7jVGDK24CfV_Df2Rx6BrvXNsoa5kI7UoZTr_Ep/s5444/DSC02690_thumb.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="3062" data-original-width="5444" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4LJHMV_3IVuO35LiEGtqR5a1CWW-qckXy834g7dJBJzGfdzyCBIxIjmcFjK0Hk9FV0W-sz6kmeJocqkIWuqNYmblUZ5g2BKjvQxMshFSpGGDtJltKC11iwfE0tWSX73AN9RJGHbY-k_qIDt_IlY7jVGDK24CfV_Df2Rx6BrvXNsoa5kI7UoZTr_Ep/w400-h225/DSC02690_thumb.JPG" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">とりあえずLCDを動かしてみた</td></tr></tbody></table><div><br /></div><div>こちらもブログネタで、Rust+RPi PicoでLCDを操作する話でした。これについてはブログを上げた後に裏でいろいろいじってました(が諸事情で非公開)。</div><div><a href="https://www.shtsno24.tokyo/2022/05/rustrustrpi-picost7789tft-lcdwaveshare.html" target="_blank">記事へのリンク</a></div><div><br /></div><h1 style="text-align: left;">3.激安プロジェクタ分解</h1><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0oYTdSP96WX47IfD0WtNxnO_p_gRFAHlGlIazEH7oLFzfn2uVTZi0rnAGuJNgK_Th1Qx48LWJyxhU8GHMMJEqBsDLRyaIq0Qvmw7JITxU42X9ftZFPOEJYCCN18qGlRYg31MfxxymyC80wCxcmTLnkNFrOef2YJYJQ44WLCpIC5QvtvgJPkj9pTwk/s4032/IMG_4774~photo.HEIC" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0oYTdSP96WX47IfD0WtNxnO_p_gRFAHlGlIazEH7oLFzfn2uVTZi0rnAGuJNgK_Th1Qx48LWJyxhU8GHMMJEqBsDLRyaIq0Qvmw7JITxU42X9ftZFPOEJYCCN18qGlRYg31MfxxymyC80wCxcmTLnkNFrOef2YJYJQ44WLCpIC5QvtvgJPkj9pTwk/w400-h300/IMG_4774~photo.HEIC" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><div class="separator" style="clear: both;">カバーを外したプロジェクタ</div></td></tr></tbody></table><div class="separator" style="clear: both; text-align: center;"><br /></div><div>完全なる好奇心で\4k弱のプロジェクタを購入し分解しました。今は動作する状態まで組み立てて使っていないのですが、そのうちLEDの換装とかをして遊ぼうかと思っています。記事を書け。</div><div><a href="https://ec.geo-online.co.jp/shop/g/g986121701/" target="_blank">プロジェクタの販売ページ</a></div><div><br /></div><h1 style="text-align: left;">4.TinyFPGA BX用拡張ボード</h1><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia0EWuwhSGY8xXWZOvJ41KDPY_9SBJRvOTP2ar2ZYcAQfj0icDgzvdw6ArEYU1KpdP6IzlZbukH7vTvy4NHdzmPYmKSd9I1eTbgxyh1DwZDoWCjnBQnj-kFz9PWq_AYSzI9p5fc8k_dfpKwQ-MEo5z2kero5zSpRVTa2kOoZI0APyBIRt4U3hncrYH/s6000/DSC02731.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="4000" data-original-width="6000" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia0EWuwhSGY8xXWZOvJ41KDPY_9SBJRvOTP2ar2ZYcAQfj0icDgzvdw6ArEYU1KpdP6IzlZbukH7vTvy4NHdzmPYmKSd9I1eTbgxyh1DwZDoWCjnBQnj-kFz9PWq_AYSzI9p5fc8k_dfpKwQ-MEo5z2kero5zSpRVTa2kOoZI0APyBIRt4U3hncrYH/w400-h266/DSC02731.JPG" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">左から試作(1)、試作(2)、完成品</td></tr></tbody></table><div style="text-align: center;"><br /></div><div>TinyFPGA BX用に拡張ボードを作ってました。実は以前にも作っていたのですが、出来がそこまでよくなかったので再設計してみました。あとはHDLの学習もかねて74HC595を制御するドライバの作成なども行っていました。記事を書(ry</div><div><br /></div><h1 style="text-align: left;">5.nncase V1.x試してみた</h1><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEic2O7OSaCmOrjFG04qIQXDaPZfP3rmTsBXr7FV6RqiW5P1O1vGsGSIC5rRBkMQyN47GDXmYLBHTQZ7XeZlWX5WKvLccUfqc7Lie2gl2Ljne9MX5Ii3lz5bVzbbcKeX-z36yeJmRmTLjFz_jWmCdBEzJkG0JOcyOm3xUrNu7Vz9ngfko-_KpzYXLkKS/s1024/IMG_4820~photo.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="447" data-original-width="1024" height="175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEic2O7OSaCmOrjFG04qIQXDaPZfP3rmTsBXr7FV6RqiW5P1O1vGsGSIC5rRBkMQyN47GDXmYLBHTQZ7XeZlWX5WKvLccUfqc7Lie2gl2Ljne9MX5Ii3lz5bVzbbcKeX-z36yeJmRmTLjFz_jWmCdBEzJkG0JOcyOm3xUrNu7Vz9ngfko-_KpzYXLkKS/w400-h175/IMG_4820~photo.JPG" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">実際に画像を読ませて認識させた結果</td></tr></tbody></table><div style="text-align: center;"><br /></div><div>以前nncase V0.4の動作確認記事を書きましたが、あの後で更新がいろいろ入ったので新しいバージョンでの動作確認環境の構築を行いました。aarch64+Dockerの環境でnncaseの実行とK210向けのバイナリ生成まで動く環境を作ることができました。記事を(ry</div><div><br /></div>
<h1 style="text-align: left;">6.レゴで作る90°ステッパー</h1><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKXZc87_VRbDuihMvCRZ0TRrPHT9YtK12RfIP6Yx8A_LoXn_54wAtbicSVypsXrclF6f_2ekZtfo68K7x9Ao5u6QJBoC32qGjMfQ6X9ICgdcYFYJW3lUwtNmkQBz_k_WCBL7FayeKtbAsYEMH767ArsjC0ra93mCEuOHmHIfas2uTm4rcPHmwOoLmU/s2048/IMG_4990~photo-full.jpg" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1152" data-original-width="2048" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKXZc87_VRbDuihMvCRZ0TRrPHT9YtK12RfIP6Yx8A_LoXn_54wAtbicSVypsXrclF6f_2ekZtfo68K7x9Ao5u6QJBoC32qGjMfQ6X9ICgdcYFYJW3lUwtNmkQBz_k_WCBL7FayeKtbAsYEMH767ArsjC0ra93mCEuOHmHIfas2uTm4rcPHmwOoLmU/w400-h225/IMG_4990~photo-full.jpg" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">作成したステッパー</td></tr></tbody></table><div><br /></div><div>レゴでシーケンシャルミッション等を作る際に必要な90°ステッパーを作りました。たまたまできてしまった代物でした。記事(ry</div><div><br /></div><h1 style="text-align: left;">7.電源基板を作る話</h1><div style="text-align: center;"><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1TRsuG_Zcvyx9ESiGaNsCarnL71TLIM-w4knC02eVcQdamZGMD1p6akigJd2xaOGCbp9KkWMcEeWOYAGcQQ6lUh8wqxz6ohv5GywVf75VZUlGHAOGFGyWYQjL_AAq1TmO0mAfbzTu6NNknyOoIfXb9bze0zEaPhPw1-EEYF58KULnmOA6iu4EHrqy/s707/StamP_PAM2401.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="406" data-original-width="707" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1TRsuG_Zcvyx9ESiGaNsCarnL71TLIM-w4knC02eVcQdamZGMD1p6akigJd2xaOGCbp9KkWMcEeWOYAGcQQ6lUh8wqxz6ohv5GywVf75VZUlGHAOGFGyWYQjL_AAq1TmO0mAfbzTu6NNknyOoIfXb9bze0zEaPhPw1-EEYF58KULnmOA6iu4EHrqy/w400-h230/StamP_PAM2401.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">試作中の基板</td></tr></tbody></table></div><div><br /></div><div>ちょっと気が向いたので、電源基板を作っています。オレオレ規格を策定するところから始まっているので先は長そうですが、いろいろ試すいい機会だと思っています。記(ry</div><div><br /></div><h1 style="text-align: left;">8.終わりに<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrXySFxjZLAAOGsQeRi5FFp878Sepgqqk_jJ8yd1o289D-gN2IiXKOoTlq6hu65PACy1KpAaYMxkZGww6tStQ15-UYPXxPQ_N6SKYpkl-aJhs4BHQQ9VcNNjOHAzoO1ppI0oO_y24u2iw7BJIaaXbZQkQNb8BxrzL1gWsrRHAr2cvu9LUavhACqFEj/s4032/IMG_4973~photo.HEIC" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrXySFxjZLAAOGsQeRi5FFp878Sepgqqk_jJ8yd1o289D-gN2IiXKOoTlq6hu65PACy1KpAaYMxkZGww6tStQ15-UYPXxPQ_N6SKYpkl-aJhs4BHQQ9VcNNjOHAzoO1ppI0oO_y24u2iw7BJIaaXbZQkQNb8BxrzL1gWsrRHAr2cvu9LUavhACqFEj/w400-h300/IMG_4973~photo.HEIC" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><div>MFTokyo2022に行ってました。</div></td></tr></tbody></table></h1><div>今年は業務でいろいろ作る方に気力を吸い取られたため、あまり活動できなかった部分がありました。来年以降はもう少しいろいろやりたいところです。</div><div><br /></div><div>...そんなことより記事を書け。</div><br />
<br />
<div style="text-align: center;">
©2022 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
<br /><br /><br />Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-9808507278528888672022-05-29T13:41:00.000+09:002022-05-29T13:41:32.060+09:00Rust初心者が、Rust+RPi PicoでST7789使用TFT LCD(Waveshare Pico LCD 1.3)を使う話<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzYIsJ_b2OHsZiq51-pnv_pJzQqm9wuq9nyPMEjOwtbF2IJV0B27N6yrQLwc1amG7znewihvcxkjp3jD-R3ojwSLKtpov6WKIjDSAKRvnLSswcqu7WdOq5zWA9JPaClhWbmoPOAa5T5TNVtMLAo3A6CROVc3MZMPxTKlHR74DwGPuPnNhP15KWfGr0/s5333/DSC02690_thumb.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2999" data-original-width="5333" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzYIsJ_b2OHsZiq51-pnv_pJzQqm9wuq9nyPMEjOwtbF2IJV0B27N6yrQLwc1amG7znewihvcxkjp3jD-R3ojwSLKtpov6WKIjDSAKRvnLSswcqu7WdOq5zWA9JPaClhWbmoPOAa5T5TNVtMLAo3A6CROVc3MZMPxTKlHR74DwGPuPnNhP15KWfGr0/w400-h225/DSC02690_thumb.JPG" width="400" /></a></div><br /><div><br /></div> いつの間にかひよっこ社会人になっていた中の人です。研究室とは勝手が違う中、ひたすら研修を進めています。<br /> さて今回は<a href="https://www.shtsno24.tokyo/2021/02/rpi-picorustwin10-powershell-wsl.html" target="_blank">以前紹介したRust+RPi Picoのお話</a>の続き?で、Waveshare社製Pico LCD 1.3をRust環境で使う話になります。<br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">0.開発環境とアップデート</h1><div><br /></div><div> 以前の記事では、WSL上でクロスコンパイルをし、PowerShell環境でelf2uf2を使って最終的なバイナリを作っていたと思います。</div><div> その後、<a href="https://docs.rs/crate/elf2uf2-rs/latest" target="_blank">elf2uf2-rs</a>が登場し、.cargo/config.tomlで設定すれば、cargo runだけで.uf2への変換からボードへのアップロードも自動で行えるようになりました。らくちん。さらに、記事を書いた後環境を丸ごと吹き飛ばした関係もあり、今回はすべてPowerShell上に環境を構築しました。</div><div> また以前の記事以降にrp2040-halのアップデート等があり、関数の書き方などが変わっています(<a href="https://github.com/rp-rs/sample-project" target="_blank">rp-rs/sample-project</a>も<a href="https://github.com/rp-rs/rp2040-project-template" target="_blank">rp-rs/rp2040-project-template</a>の方が推奨に切り替わった)。</div><div><br /></div><h1 style="text-align: left;">1.ピンアサインの確認</h1><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit3HbknxoF5akWfzzfiXoH550v9TrEWneyndZ1qkg6bhuAHeM-5FRrLaTk7lHOVE-faJ7M2grddYiY1NvPTmYsFvsYRtckFJrdIpoIjCwTL5IvpxLMo0oDM97j3hi-M7hby9ici6BsZtOizXLImXO2k0n_NsvuiIax4WS0BA7dH27nhWHTkze7Fsfm/s800/Pico-LCD-1.3-details-inter.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="571" data-original-width="800" height="285" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit3HbknxoF5akWfzzfiXoH550v9TrEWneyndZ1qkg6bhuAHeM-5FRrLaTk7lHOVE-faJ7M2grddYiY1NvPTmYsFvsYRtckFJrdIpoIjCwTL5IvpxLMo0oDM97j3hi-M7hby9ici6BsZtOizXLImXO2k0n_NsvuiIax4WS0BA7dH27nhWHTkze7Fsfm/w400-h285/Pico-LCD-1.3-details-inter.jpg" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;">ピンアサイン</div><div class="separator" style="clear: both; text-align: center;">(<a href="https://www.waveshare.com/wiki/Pico-LCD-1.3">https://www.waveshare.com/wiki/Pico-LCD-1.3</a>より引用)</div><div><br /></div><div> 今回使用するボードも以前と同じくRPi Picoを使います。そしてLCDとして、Waveshare社から発売されている<a href="https://www.waveshare.com/wiki/Pico-LCD-1.3" target="_blank">Pico LCD 1.3</a>を使います。今回は<a href="https://www.switch-science.com/catalog/7327/" target="_blank">SwitchScience</a>で購入しました。</div><div> このLCDを制御しているST7789はSPIで通信するので、PicoのSPI1を使います。注意事項があるとすれば、本来のSPI1であればGP8/GP12のいずれかをデータ転送(<span face="-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"" style="background-color: white; color: #24292e; font-size: 16px;">Controller In Peripheral Out/Master In Slave Out</span>)で使います。しかしST7789の場合、GP8をデータ/コマンド選択ピン、GP12はローアクティブのリセットピンとして使うので注意が必要です。同様にGP13はバックライトの制御で使うので注意してください。GP8/GP12/GP13はGPIOピンとして使います。</div><div><br /></div><div>参考:<a href="https://datasheets.raspberrypi.com/pico/Pico-R3-A4-Pinout.pdf">https://datasheets.raspberrypi.com/pico/Pico-R3-A4-Pinout.pdf</a></div><div><br /></div><h1 style="text-align: left;">2.画面描画</h1><div><br /></div><div> 今回は<a href="https://github.com/Floyd-Fish/ST7789-STM32" target="_blank">Floyd-FishさんのSTM32向けCライブラリ</a>を参考に、レジスタの初期設定と各ピクセルの描画を行いました。データシートをよく見ずに書き始めたので、自分が分かっていないレジスタと設定値が存在しています(後から見返したら<a href="https://www.waveshare.com/w/upload/a/ae/ST7789_Datasheet.pdf" target="_blank">データシート</a>に載っていた件)。なので、ここではレジスタの設定値の話はパスします。</div><div> 全体のコードは<a href="https://github.com/rp-rs/rp2040-project-template" target="_blank">rp-rsさんのLチカのテンプレート</a>をベースに手を入れました。一番悩んだのがSPIやGPIOをラップした関数を作ることで、いまだにわかっていない部分がいろいろあります。が、とりあえず動いたのでここではヨシッ。関門だった初期化関数も一応かけました(この書き方が組み込みRustのお作法にかなっているのかがよくわからん)。</div><div> (<a href="https://github.com/shtsno24/rust-pico-waveshare-1-3inch-lcd" target="_blank">今回作成したコードはこちらから</a>)</div><div><br /></div><h1 style="text-align: left;">3.まとめ</h1><div><br /></div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="266" src="https://www.youtube.com/embed/UnVssEl5PBc" width="320" youtube-src-id="UnVssEl5PBc"></iframe></div><div><br /></div><div> 今回はRust+RPi PicoでTFT LCDを使う話でした。いろいろな方のコードを<strike>切ったりはったり</strike>参考に作りました。特にrp2040-halの開発元が公開しているサンプルコードは役立ちました。ちゃんとRustを触るのは初めてで困ることも多かったですが、最低限の機能を実装し、どうにかこうにか動くところまで行けました。まだ使っていないマイコンの機能もあるので、仕事が忙しくなる前にもう少し遊んでみようかと思います(UARTのポーリングし続けないと切られる問題や、GP8の切り替えがdelayを挟まないとデータ転送のタイミングとずれてくる問題)。</div><div><br /></div><h1 style="text-align: left;">4.参考</h1><div><br /></div><div>SPIのサンプル:<a href="https://github.com/rp-rs/rp-hal/blob/main/rp2040-hal/examples/spi.rs">https://github.com/rp-rs/rp-hal/blob/main/rp2040-hal/examples/spi.rs</a></div><div>ラップ関数のサンプル:<a href="https://github.com/rp-rs/rp-hal/blob/main/boards/rp-pico/examples/pico_spi_sd_card.rs">https://github.com/rp-rs/rp-hal/blob/main/boards/rp-pico/examples/pico_spi_sd_card.rs</a></div><div>開発環境周りで参考にした<a href="https://qiita.com/ochaochaocha3" target="_blank">@ochaochaocha3</a>さんのQiita:<a href="https://qiita.com/ochaochaocha3/items/1969d76debd6d3b42269" target="_blank">https://qiita.com/ochaochaocha3/items/1969d76debd6d3b42269</a></div><div>LCDのスペック:<a href="https://www.waveshare.com/wiki/Pico-LCD-1.3">https://www.waveshare.com/wiki/Pico-LCD-1.3</a></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div>
<div style="text-align: center;">
©2022 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-62907576285498987792022-03-16T00:53:00.003+09:002022-03-16T09:17:16.676+09:00PYNQとVitis HLSで作るFMA演算IP(4):おまけネタ<script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhPixW8KfXBYzJw-Tyu1c7eFxn3_CxmdACOVjOUUyDh-x3Q9kDH1lEm7IGdhjMrHYZLT4L9O5fmbj6FV_XRf2osLGADBUSBCjeyKYubW0QaHPRL1Ub0XRp0xaMJhjvSnAklo_B9b4PxXy9l5F_J7Af9YAtb-IrhmrTqygcPdaYWpk_HZE3iIq-ttf_s=s3143" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="2357" data-original-width="3143" src="https://blogger.googleusercontent.com/img/a/AVvXsEhPixW8KfXBYzJw-Tyu1c7eFxn3_CxmdACOVjOUUyDh-x3Q9kDH1lEm7IGdhjMrHYZLT4L9O5fmbj6FV_XRf2osLGADBUSBCjeyKYubW0QaHPRL1Ub0XRp0xaMJhjvSnAklo_B9b4PxXy9l5F_J7Af9YAtb-IrhmrTqygcPdaYWpk_HZE3iIq-ttf_s=s400" width="400" /></a></div>
<br /><a href="https://www.shtsno24.tokyo/2022/03/pynqvitis-hlsfmaip3.html" target="_blank">前回までで</a>、FMA演算IPを作成することができました。今回はおまけ編で、データ型を変えたり並列数を増やしたりしてみます。
<br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">1.いろいろなデータ型に対応させる</h1><div><br /></div><div> せっかくの専用回路だし、いろいろなデータ型に対応させてみましょう。今回は参考例として16bit固定小数点(q4.12)に対応させてみます。</div><div> ...とはいうものの、高位合成用のサンプルコードはテンプレート関数で記述されているうえに、データ型は<a href="https://github.com/shtsno24/FMAUnit4PYNQ/blob/master/Code/FMA.hpp" target="_blank">FMA.hpp</a>内のusing data_type = float;の部分で一元的に管理しています。なので、ここの部分を固定小数点ように書き換えればいいわけです。</div><div> Vitis HLSでは固定小数点用のライブラリとしてap_fixed.hが提供されており、これを使用して記述すればいいわけです(書き換えるとusing data_type = ap_fixed<data_width, 4>;となる)。あとは、データ幅を16bitに下げればOKです(constexpr data_width = 16;)。</div><div> <a href="https://github.com/shtsno24/FMAUnit4PYNQ/blob/master/FMAUnit_PYNQ/FMA.ipynb" target="_blank">JupyterNotebookのコード</a>については、最初のせるのarray_typeをnp.int16、fractionを12、enable_fp2fixをTrueにすれば動くはずです。</div><div><br /></div><h1 style="text-align: left;">2.AXI-Streamのデータ幅を増やす</h1><div><br /></div><div> こちらに関しては、FMA.cppのbus_widthを書き換え、JupyterNotebookのbus_widthを書き換えます。また回路を作成する際に使用したDMA IPのStream Data Widthを指定の値にします。DMA IPの設定値からわかるように、データ幅は64, 128, 256, 512, 1024といった値しかとることができません。注意しましょう。</div><div> データ幅を増やすことで、並列数を増やすことができます。DMAの転送能力次第な部分はありますが、そこそこの速度向上が達成できそうな雰囲気でした(160万個のデータを流して210MFLOP程度)。</div><div><br /></div><h1 style="text-align: left;">3.遭遇したトラブル</h1><div><br /></div><div><ul style="text-align: left;"><li>AXI-Streamのデータ幅について、fp32+1024bitの時やfix16+256bitの場合でHLSのCoSimの段階から結果がおかしくなっていた。CSimの段階では正常な計算結果を返すし、他のデータ幅の場合とはデータ幅とデータ型以外変えていないので、まったくもって謎だった。</li><li>float配列とデータバスのunionを作成し、型変換を実装する予定だったが、ap_intやap_fixedをunionのメンバに入れるとコンパイルが通らなくなるのでやめた。</li><li>float配列とCの組み込み整数型のunionを含むコードをVivado HLSで高位合成かけようとしたところ、合成に失敗した。Vitis HLSを使うと、合成がかかった。</li><li>回路が動きそうでも動かない場合、Vivadoのプロジェクトを作り直すと動く場合があった。</li><li>この記事を書くのに、中の人の睡眠時間とGT7のプレイ時間が削られまくった。</li></ul></div><div><br /></div>
<br />
<br />
<div style="text-align: center;">
©2022 shts All Right Reserved.</div><br />Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-2740058784246266692022-03-16T00:51:00.004+09:002022-03-16T09:16:08.116+09:00PYNQとVitis HLSで作るFMA演算IP(3):実機での実行<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhK-OC5u10tIkV5hi_QxdJyK5yEKrqLFc0fpnkif4Qo6nh_yMDxk9Hesi__0_n51p6CZBTsW1t2olPcx6DhIR3P0pND4ZT2SrIkYypBKLqEWaFtwBKGDvKULv9Bbjef0f0HDXqKfU3mTneYmmC35Zh0xmlPJ7wDc61o3DmjFD2rwABJNt2uADwVW8no=s3143" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="2357" data-original-width="3143" src="https://blogger.googleusercontent.com/img/a/AVvXsEhK-OC5u10tIkV5hi_QxdJyK5yEKrqLFc0fpnkif4Qo6nh_yMDxk9Hesi__0_n51p6CZBTsW1t2olPcx6DhIR3P0pND4ZT2SrIkYypBKLqEWaFtwBKGDvKULv9Bbjef0f0HDXqKfU3mTneYmmC35Zh0xmlPJ7wDc61o3DmjFD2rwABJNt2uADwVW8no=s400" width="400" /></a></div>
<div class="separator"><br /></div><div class="separator"> <a href="https://www.shtsno24.tokyo/2022/03/pynqvitis-hlsfmaip2.html" target="_blank">前回</a>と<a href="https://www.shtsno24.tokyo/2022/03/pynqvitis-hlsfmaip1hls.html" target="_blank">前々回</a>で、とりあえ回路情報の入ったbitstreamファイルまで生成できました。今回は実機実装していきます。</div><div class="separator"> <a href="https://github.com/shtsno24/FMAUnit4PYNQ" target="_blank">今回作成した回路はこちらから。</a></div>
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div>1.実機のコードについて</h1><div><br /></div><div> 今回の回路構成の場合、DMAの関数に64bitの配列を渡す必要があるように見えるのですが、実際には計算で使うデータ型(今回の場合はfp32:np.float32)の配列を使用して問題ないです。ただし、配列の総サイズ(bit)が64bitで割り切れる必要があります。割り切れない場合は、ゼロパディングで埋めるといいでしょう。</div><div> 今回作成したIPはAXI-Liteで制御するのですが、開始の制御以外にループ回数の指定を行います(0x10にint32でループ回数を書き込む)。また、0x00に1を書き込むことで、IPの開始を制御できます。そのほかとしては、dmaの転送設定を自作IPの開始前に行うあたりが少し特殊かもしれないです。</div><div> 一応参考としてIPの実行時間を計測します。具体的にはメモリからデータを読み出し始めてから、書き込みが終わるまでの時間を計測します(自作IPをスタートさせたタイミングで入力データの転送が開始され、受信側のDMA IPが終了するタイミングでIPの実行も終了するため)。</div><div> <a href="https://github.com/shtsno24/FMAUnit4PYNQ/blob/master/FMAUnit_PYNQ/FMA.ipynb" target="_blank">ノートブックはこちらから。</a></div><div><br /></div><h1 style="text-align: left;">2.実行結果</h1><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjxEskKnWQd9sdUg1PsO5uMkdhSXbsZn9FRV2bOWd8StRAYVWHIIwuFaHTzUM4c2xr5SRMJ-aWbYbzqeyePdh8dTNyuMmbPA_dCVOrsSB0iLzeKYB2vaEh4gaw5xYWJTRgxQBh94LbwNS3UB63HGDMh6HJBreA8xhJgW0vfiOjANG6D4NbMqQbEqIJZ=s771" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="572" data-original-width="771" height="296" src="https://blogger.googleusercontent.com/img/a/AVvXsEjxEskKnWQd9sdUg1PsO5uMkdhSXbsZn9FRV2bOWd8StRAYVWHIIwuFaHTzUM4c2xr5SRMJ-aWbYbzqeyePdh8dTNyuMmbPA_dCVOrsSB0iLzeKYB2vaEh4gaw5xYWJTRgxQBh94LbwNS3UB63HGDMh6HJBreA8xhJgW0vfiOjANG6D4NbMqQbEqIJZ=w400-h296" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">実行結果。140MFLOPS程度の性能であった。</td></tr></tbody></table><br /><div><br /></div><div> サンプルコードではCPUの計算結果との比較を行っているのですが、特段表示が出なければ一致していると思ってください。実行速度に関しては、20万回FMAの計算を実行した場合で大体140MFLOPS程度が出ているようです(実はループ回数をいじると計算回数が変化し、計算速度が変化する)。</div><div> CPUで実行する場合と比べると...まぁ遅いといった感想になるでしょうか。クロック周波数が200MHzしか出ておらず、またFMAの計算に16*5nsかかっていることを踏まえればこの程度かなとは思っています。</div><div><br /></div><h1 style="text-align: left;">3.今後</h1><div><br /></div><div> 自作のFMA演算IPを実機実装することができました。<a href="https://www.shtsno24.tokyo/2022/03/pynqvitis-hlsfmaip4.html" target="_blank">次回はAXI-Streamのデータ幅拡張や異なるデータ型への対応についての話です。</a></div><div><br /></div>
<br />
<br />
<br />
<div style="text-align: center;">
©2022 shts All Right Reserved.</div><br />Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-75386303893303392332022-03-16T00:45:00.001+09:002022-03-16T00:55:48.769+09:00PYNQとVitis HLSで作るFMA演算IP(2):高位合成と回路合成<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEh7XCdUP6bgxT4fG7qXd_6lDFY-416RI_zvwB18a2tXl4Z0TtuKBCK-ypYaBurLJ6PEFCgIcUGQnBteNbr67ITAH8Gw3m9m0SnjpUTlxhaZZquZHrCsyIxyQToQ9SckP7GxmZBZCBeb7EEgkYYDdSIBGVtJGaIQAADr8yMfFEV0Z6fLh15GoqKZHcDY=s3143" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2357" data-original-width="3143" height="300" src="https://blogger.googleusercontent.com/img/a/AVvXsEh7XCdUP6bgxT4fG7qXd_6lDFY-416RI_zvwB18a2tXl4Z0TtuKBCK-ypYaBurLJ6PEFCgIcUGQnBteNbr67ITAH8Gw3m9m0SnjpUTlxhaZZquZHrCsyIxyQToQ9SckP7GxmZBZCBeb7EEgkYYDdSIBGVtJGaIQAADr8yMfFEV0Z6fLh15GoqKZHcDY=w400-h300" width="400" /></a></div><div><br /></div><br /> <a href="https://www.shtsno24.tokyo/2022/03/pynqvitis-hlsfmaip1hls.html" target="_blank">前回高位合成用のC++コードを作成しました。</a>今回はそのコードを使って高位合成を行い、その流れで回路まで作成します。<br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><br /><h1 style="text-align: left;">1.高位合成</h1><div> 今回はVitis HLSを用いてPYNQ-Z2向けに合成を行います。その際の設定は以下の通り。</div><div><ul style="text-align: left;"><li>ターゲット周波数:200MHz</li><li>Uncertainty:12.5%</li><li>ターゲットデバイス:pynq-z2(xc7z020clg400-1)</li><li>言語:C++0x</li></ul></div><div> 今回は2つのソースファイル(FMA.cpp, FMA.hpp)、1つのテストベンチ(FMA_TB.cpp)を登録します。このうちFMA.cppとFMA_TB.cppのCFLAGSに-std=c++0xオプションを付与します。</div><div> 合成結果はこんな感じになりました。</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgf96_iVUy-eIEU3MXKBb5lqy6FEpMiGjI24kMoWKKhavDrOis4F-klWnV8B1Owi6OxWcchAT1AJqsIevpXYvKg4LLImNZzNDDZD4x5PIm4kasl6lweEnQfOI1t3I6dq1spHhruSYIqX9xPyAOX6RpXQn2DOtgcTDVkKWACVEWPqyFO9_7pZpRQUZBO=s750" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="280" data-original-width="750" height="149" src="https://blogger.googleusercontent.com/img/a/AVvXsEgf96_iVUy-eIEU3MXKBb5lqy6FEpMiGjI24kMoWKKhavDrOis4F-klWnV8B1Owi6OxWcchAT1AJqsIevpXYvKg4LLImNZzNDDZD4x5PIm4kasl6lweEnQfOI1t3I6dq1spHhruSYIqX9xPyAOX6RpXQn2DOtgcTDVkKWACVEWPqyFO9_7pZpRQUZBO=w400-h149" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">高位合成の結果</td></tr></tbody></table><div><br /></div><div> Iteration Latencyは16となりましたが、Intervalが1になっていることからいい感じにパイプライン化できたようです。使用率は</div><div><ul style="text-align: left;"><li>DSP : 4%(10/220)</li><li>LUT:3%(1992/53200)</li><li>FF:1%(1718/106400)</li><li>BRAM:0%(0/140)</li></ul></div><div>となっています。余裕ありありですね。合成されたデータフローはこんな感じでした。</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiiOeVIB_GMtN_DtCtISGb0k8MGgCviG9C5RGLaZ6_uMnZZ_EsSLvuv_jTqxiq47Vlw3PLPEmhmfJPUT555v8qTNvGT-oart9Og53tjPYZIJ3xTPNIJJ8uITfJc3PV0D5t6PtXosJzq6hlm7y6mZz81hHCPwPx_TgeRqYxwQ9MzHK0zgsehdBXczCZc=s1047" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="617" data-original-width="1047" height="236" src="https://blogger.googleusercontent.com/img/a/AVvXsEiiOeVIB_GMtN_DtCtISGb0k8MGgCviG9C5RGLaZ6_uMnZZ_EsSLvuv_jTqxiq47Vlw3PLPEmhmfJPUT555v8qTNvGT-oart9Og53tjPYZIJ3xTPNIJJ8uITfJc3PV0D5t6PtXosJzq6hlm7y6mZz81hHCPwPx_TgeRqYxwQ9MzHK0zgsehdBXczCZc=w400-h236" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">データフローの一部。2か所ほど"長い棒"がみえるが、<br />それぞれfmulとfaddの計算ステップとなっていた。<br /></td></tr></tbody></table><div><br /></div><div> 一応仕様通りに2並列で計算できているようです。また大半のステップがfmulとfaddで占められていることもわかりました。</div><div> この後CoSimを走らせて結果を確認後、IPを出力します(そのまま出力してもいいのだが、Configuration...のボタンからVendor、Library、Description、Display Nameあたりをいじってからいったん出力->Solution Settings内のConfiguration Settingsのconfig_exportにあるipnameをいじってから出力すると、VivadoでIPを読み込んだ際にオリジナルの名前が付き、ベンダー名で検索がかけられる)。</div><div><br /></div><h1 style="text-align: left;">2.回路合成</h1><div><br /></div><div> 高位合成で作成したIPを使って回路を作成します。ZYNQのIPを最初に置いて、Run Connection Automationを走らせるとDDRとFIXED_IOと外部端子がつながるはずです。</div><div> その後、AXI_HPポートの0から3を有効化します。データ幅はすべて64bitにしましょう。</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhGNZ_fe932B8xMfpL-4V3g4g4NMF-G_Iy6SNezlAhpbwYHbzgE0BIimU7mKJCy-HPJt3xIQ7Q7WUDHwvYBPKd0DczUeqDO8mfLX-qRU5AEh48OHNBY08i2aPLcAbQfaswzlWSw_wWuAdBjYMgVZtmtZFG7FT46pMJVswW-KXZwBIHVYo2t_k8Iisrt=s1217" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="786" data-original-width="1217" height="259" src="https://blogger.googleusercontent.com/img/a/AVvXsEhGNZ_fe932B8xMfpL-4V3g4g4NMF-G_Iy6SNezlAhpbwYHbzgE0BIimU7mKJCy-HPJt3xIQ7Q7WUDHwvYBPKd0DczUeqDO8mfLX-qRU5AEh48OHNBY08i2aPLcAbQfaswzlWSw_wWuAdBjYMgVZtmtZFG7FT46pMJVswW-KXZwBIHVYo2t_k8Iisrt=w400-h259" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">AXI_HPポートの設定。データ幅はすべて64bitとした。</td></tr></tbody></table><br /><div> AXI_HPポートの設定後、IPへ供給するクロックの設定をします。今回は単一のクロックソースかつ周波数が200MHz程度なので、ZYNQのIPから供給します。Clock Configuration->PL Fabric Clocksの順にたどり、FCLK_CLK0を200MHzに設定します。</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgPrQw9QPgx8HUhJo4bg_2qBFVnMObAK3ZyxkJHLV_ovA3r96GWiahAsbI_crRp7-Wwzt3bOC5ep9xWuDY4H_RH4AhOKE8a_xZiTG9On2sPNf0yfgRIbK57_VqMzv9qtapv9moxeiB6bdr6D0mEawy0GO59qOUIIhG8whSIVCv3NglKjQUqk_UDPUcJ=s1176" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="766" data-original-width="1176" height="260" src="https://blogger.googleusercontent.com/img/a/AVvXsEgPrQw9QPgx8HUhJo4bg_2qBFVnMObAK3ZyxkJHLV_ovA3r96GWiahAsbI_crRp7-Wwzt3bOC5ep9xWuDY4H_RH4AhOKE8a_xZiTG9On2sPNf0yfgRIbK57_VqMzv9qtapv9moxeiB6bdr6D0mEawy0GO59qOUIIhG8whSIVCv3NglKjQUqk_UDPUcJ=w400-h260" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">クロック設定。今回はHLSに合わせて200MHz。</td></tr></tbody></table><br /><div> ZYNQ IPの設定が終わったら、AXI Direct Memory AccessとAXI Interconnectを4つずつ出します。</div><div> AXI Interconnectの方はMasterとSlaveの数をそれぞれ1に設定します。</div><div>DMAの方は入力側(W, X, B)と出力側(Y)で少し異なります。入力側のDMA IPについて、Enable Scatter Gather Engineを無効化し、Width of Buffer Legth Registerを26bits、Address Widthを64Bitsにしておきます。データ入力のIPなので、Read Channelのみ有効にしておきます。Memory Map Data WidthとStream Data Widthは64にしておきます。</div><div><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiOncj29k_dPdC8BkJulf8wUO0B-muTzef43z83a2Ad2LnWTlLu1STLhGaWIh8HFcopTeTJ-NfCVC096jBt0ALR_zTQfLeFVsXyfxOpMlVaD_mbVtx1k2AdvjPeJHymMVQMXgzMsE4YSoT88II7klwPo1-eP2y9RGWIxe8Yo2sV9ySdKrszRbuZstIQ=s1453" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="910" data-original-width="1453" height="250" src="https://blogger.googleusercontent.com/img/a/AVvXsEiOncj29k_dPdC8BkJulf8wUO0B-muTzef43z83a2Ad2LnWTlLu1STLhGaWIh8HFcopTeTJ-NfCVC096jBt0ALR_zTQfLeFVsXyfxOpMlVaD_mbVtx1k2AdvjPeJHymMVQMXgzMsE4YSoT88II7klwPo1-eP2y9RGWIxe8Yo2sV9ySdKrszRbuZstIQ=w400-h250" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">読み込み側のDMA IPの設定</td></tr></tbody></table></div><div><br /></div><div> 出力側のDMA IPについては、入力側で行ったEnable Scatter Gather Enginenの無効化、Width of Buffer Legth Register->26bits、Address Width->64Bitsの操作を同じく行います。その後、Read Channelを無効化し、Write Channelの有効かを行います。Memory Map Data WidthとStream Data WidthはAUTOのままでOKです。</div><div><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEh6fV_XnMIedToZYj-w_KrGG0uPV7ErdeePbzZ6AVrrH3HTD1Z5Dqkj2gwCKwpZagzP1Yx42xOW4P6T5en3G-E7NbJ6hVhVdEcfb7-H0lVvPmLrhZtj9lRickwtIhesIR3HQCmlqM_cmdLhfZB-xj3FifSaCJ0JivlvuqTw04DkwdICeZOz76f0nVB8=s1456" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="890" data-original-width="1456" height="245" src="https://blogger.googleusercontent.com/img/a/AVvXsEh6fV_XnMIedToZYj-w_KrGG0uPV7ErdeePbzZ6AVrrH3HTD1Z5Dqkj2gwCKwpZagzP1Yx42xOW4P6T5en3G-E7NbJ6hVhVdEcfb7-H0lVvPmLrhZtj9lRickwtIhesIR3HQCmlqM_cmdLhfZB-xj3FifSaCJ0JivlvuqTw04DkwdICeZOz76f0nVB8=w400-h245" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">書き込み側のDMA IPの設定</td></tr></tbody></table></div><div><br /></div><div> 最後に各IPを接続します。DMAのIPをCPU側から制御するため、個々のIPに割り当てられている名前が必要になります。サンプルコードをそのまま使いたい場合、</div><div><ul style="text-align: left;"><li>S_AXI_HP0 -> axi_dma_0(+interconnect) -> w_axi_0</li><li>S_AXI_HP1 -> axi_dma_1(+interconnect) -> x_axi_1</li><li>S_AXI_HP2 -> axi_dma_2(+interconnect) -> b_axi_2</li><li>y_axi_3 -> axi_dma_3(+interconnect) -> S_AXI_HP3</li></ul></div><div>と接続しましょう。</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEizL8t27tch4QM1y1bbjUjZdJYPjId5M4C34ngdQJxq7Fup9Fyv3CAQWue6Ovw7H1ci2t54HCfXDDcu_B_MSSERo5aqkKKH6UoMlvguBdBbic2Wa9Ls8ww1vWRrj1ChjaqgVlBxZ76oJ__G-SUx6Tm_2wB7HiqxeqWunEMQqmbrUoOmyPxYs3wyiW7t=s1851" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="871" data-original-width="1851" height="189" src="https://blogger.googleusercontent.com/img/a/AVvXsEizL8t27tch4QM1y1bbjUjZdJYPjId5M4C34ngdQJxq7Fup9Fyv3CAQWue6Ovw7H1ci2t54HCfXDDcu_B_MSSERo5aqkKKH6UoMlvguBdBbic2Wa9Ls8ww1vWRrj1ChjaqgVlBxZ76oJ__G-SUx6Tm_2wB7HiqxeqWunEMQqmbrUoOmyPxYs3wyiW7t=w400-h189" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">IPの配線図。<br />Wが0、Xが1、Bが2、Yが3と覚えると分かりやすい。<br /></td></tr></tbody></table><div><br /></div><div> この接続を終えると、Run Connection Automationの表示が出るので、すべてにチェックを入れて実行すれば最終的な回路の完成です。この後、アドレスエディタでDMAと自作IPに対してアドレスを割り当てておきましょう。</div><div><br /></div><div> Generate Output Productsを実行し、Create HDL WrapperをLet Vivado manage...の方に入れておきます。Generate Bitsteramをクリックすれば回路の合成が始まります(2回に1回ぐらいで失敗するが、Output Productsをリセットしたのち、Generateしなおして再びBitstreamの生成を行えばいけるはず)。</div><div> Bitstreamの生成が終わったら、.bitのファイルと.hwhのファイルを書きだします。画面左上のFile->Export->Export Hardwareを選択し、Platform typeをFixed、Outputを Include bitstreamに設定します。その後、XSAのファイル名を聞かれるので、適当な名前にします(サンプルコードの通りにしたい場合は、design_1_wrapperをdesign_1に変更)。出力先はどこでもよいです。</div><div> .bitと.hwhはこのXSAファイルに入っているので、7zip等を使い取り出します。最終的にこの.bitと.hwhのファイルを.ipynbから読みだしてプログラムを実行することになります。</div><div><br /></div><h1 style="text-align: left;">3.次回</h1><div>.bitファイルと.hwhファイルが生成できたので、<a href="https://www.shtsno24.tokyo/2022/03/pynqvitis-hlsfmaip3.html" target="_blank">次回はPYNQ側のコードと速度計測を行っていきます。</a></div><div><br /></div>
<br />
<br />
<div style="text-align: center;">
©2022 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
<br />Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-21998632563727685942022-03-15T11:30:00.003+09:002022-03-16T09:14:33.061+09:00PYNQとVitis HLSで作るFMA演算IP(1):簡単な仕様策定とHLSコードの作成<div><br /></div><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEi2H-4SIMr17sq6Om8g9WnXj68xHN-0JwI5LEoG3QQgump2IiYxC8q2-Ot3ezDLyJ4Ful1bHaDBW2GA0JV16y7McLfK9TC_eqocUvvYoTqy2snT_6V68UjCjEe1fHawpuSY81m2wmL1i_9tpBDhts9YkqBwB1B1pAYq_RYH1h_Y4a9IbzutT2SqFRp3=s3143" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2357" data-original-width="3143" height="300" src="https://blogger.googleusercontent.com/img/a/AVvXsEi2H-4SIMr17sq6Om8g9WnXj68xHN-0JwI5LEoG3QQgump2IiYxC8q2-Ot3ezDLyJ4Ful1bHaDBW2GA0JV16y7McLfK9TC_eqocUvvYoTqy2snT_6V68UjCjEe1fHawpuSY81m2wmL1i_9tpBDhts9YkqBwB1B1pAYq_RYH1h_Y4a9IbzutT2SqFRp3=w400-h300" width="400" /></a></div><br /> 修論の提出まで終わり、無事修士課程を修了できた中の人です。修論ではとある専用計算回路を作成したのですが、時間の都合上PS-PL間の通信部に関してあまり手を入れることができませんでした。そこで今回はその通信部について、PYNQ-Z2へのFMA(積和)演算IPの実装を題材として、いろいろ試してみようと思います。<div> <a href="https://github.com/shtsno24/FMAUnit4PYNQ" target="_blank">今回のコードについてはこちらからどうぞ。</a><br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">0.開発環境</h1><div><br /></div><div><ul style="text-align: left;"><li>使用ボード:PYNQ-Z2(PYNQ v2.6)</li><li><div>Vivado:2020.1</div></li><li><div>Vitis HLS:2020.1</div></li><li>高位合成言語:C++0x</li><li>OS:Ubuntu20.04(on WSL2)</li></ul></div><div> </div><div><h1 style="text-align: left;">1.FMA演算IPの簡単な仕様</h1><div><br /></div><div> 今回は、積和演算を同時に複数実行する演算IPを作成します。演算器自体はそこまで重要ではないのですが、今回重要となるのはPS部とIPを接続する通信部です。</div><div><br /></div><div> 今回使用するPYNQ-Z2において、PS部とIPの通信方法はいくつかあります。どの通信方法を使うかについて少し考えます。</div><div> まずFMAの演算器の個数よりも多くのデータを流すことを考えると、演算器を複数回使いまわす必要があります。その場合にはパイプライン化した方がより高速に実行できるようになります。パイプライン化を行う際に注意すべき点として、パイプラインに流すデータの取得が滞ってしまうとストールすることが挙げられます。</div><div> となると、PS-IP間の通信として連続してデータを送ることができるAXI-Streamを使うとよさげなことがわかります(Xilinx提供のAXI Direct Memory AccessがPL側とAXI-Streamで接続するのも理由の一つ)。</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgkdgddOqGQwKfNORGwQXG_hHIZSvoVi2G5Pcvkqwr24C_wZTIRFd65v3G1_ntLtm3clz5-hLm8iT3twX8Uku3heUEpisjr9-_y9K4uJVxLmollG5RKAE3aP5oSyTY4o-hRtp2tI4bv5aiOwTfW_JgLSJIa0GBwppNYjQh6kMGZUBeLBXSzJn_BuKxv=s963" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="321" data-original-width="963" height="134" src="https://blogger.googleusercontent.com/img/a/AVvXsEgkdgddOqGQwKfNORGwQXG_hHIZSvoVi2G5Pcvkqwr24C_wZTIRFd65v3G1_ntLtm3clz5-hLm8iT3twX8Uku3heUEpisjr9-_y9K4uJVxLmollG5RKAE3aP5oSyTY4o-hRtp2tI4bv5aiOwTfW_JgLSJIa0GBwppNYjQh6kMGZUBeLBXSzJn_BuKxv=w400-h134" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">全体のブロック図(W〇Xは要素積を表す)</td></tr></tbody></table><div><br /></div><div> 転送規格は決まったので、より詳しい部分を決めていきます。AXI-Streamのデータ幅はとりあえず64bitにします(後で広げる)。また実際に計算するデータの型を単精度浮動小数点(FP32)に仮決定しておきます。64bit幅のバスであればFP32のデータを2つ同時に流すことができるので、同時に2のFMA命令を実行できる回路を作成することにします。</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEg0GDq4f1E_dGS5TyrfzAzf9lsUxQtWaM84N4a3nLg1lmQLCwHoX2YzHd33IJPSYIpLbZKIn8PaFrn4goQCuH2FprOKg_eM7pLwFMowLUso3VbcEOe9XbRLkKUrP9wAg8jvZdPma5VSlmd1VZXs_2W4X4p5YQiI3WA279YZ0NYI_CP6SR3yNDCiilMp=s1041" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="721" data-original-width="1041" height="278" src="https://blogger.googleusercontent.com/img/a/AVvXsEg0GDq4f1E_dGS5TyrfzAzf9lsUxQtWaM84N4a3nLg1lmQLCwHoX2YzHd33IJPSYIpLbZKIn8PaFrn4goQCuH2FprOKg_eM7pLwFMowLUso3VbcEOe9XbRLkKUrP9wAg8jvZdPma5VSlmd1VZXs_2W4X4p5YQiI3WA279YZ0NYI_CP6SR3yNDCiilMp=w400-h278" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">自作IPのブロック図</td></tr></tbody></table><div><br /></div><h1 style="text-align: left;">2.HLS用のコード</h1><div><br /></div><div> さてここからはHLS用のコードについてです(<a href="https://github.com/shtsno24/FMAUnit4PYNQ/tree/master/Code" target="_blank">コードについてはこちら</a>)。IP内部のブロック図を基にコードを作成すると、必要になるのが</div><div><ul style="text-align: left;"><li>slicer:64bitのデータを32bit x 2個のデータに分割する</li><li>array_(w, x, b, y):32bit x 2個のデータを保持する</li><li>fma_unit:y=wx+bを2並列同時に行う</li><li>packer:32bit x 2個のデータを64bitのデータに分割する</li></ul></div><div>となります。<a href="https://github.com/shtsno24/FMAUnit4PYNQ/blob/master/Code/FMA.cpp" target="_blank">array_(w, x, b, y)</a>に関しては、C言語の配列(C++の生配列)とarray_partitionプラグマを使用します(std::arrayはHLSで合成できないので)。</div><div> 以下のコード例では配列を要素ごとに分割して実装しています(data_type=float, field_length=2)。 </div><div><br /><pre><code>data_type w_vec[field_length];
#pragma HLS array_partition variable=w_vec complete dim=0
</code></pre><br /> <a href="https://github.com/shtsno24/FMAUnit4PYNQ/blob/master/Code/FMA.hpp" target="_blank">fma_unit</a>はfor-loopとloop_unrollプラグマで2並列分(length=field_length=2)の演算器を実装します。
<br /><pre><code>template<typename data_t, uint64_t length>
void fma(data_t w[], data_t x[], data_t b[], data_t y[]){
for (uint64_t i = 0; i < length; i++){
#pragma HLS UNROLL
y[i] = w[i] * x[i] + b[i];
}
}
</code></pre><br /> <a href="https://github.com/shtsno24/FMAUnit4PYNQ/blob/master/Code/FMA.hpp" target="_blank">slicerとpacker</a>については、ビットマスクとシフトを使っていい感じにスライス・パックしていくだけです。しかしながら、floatからAXI-Streamで使用するデータ型(ap_axiu)へ単純に代入した場合型キャストが発生し整数部分しか読み取られない問題や、floatのフォーマットでPSから送信されたビット列をintとして解釈し、floatにキャストした際にデータが化ける問題があります。</div><div> これはap_axiu(ap_axis)のデータ部がap_uint(ap_int)で記述されていることに起因しており、c言語でいうところのfloatとunsigned int(int)間のキャストと同じことが発生しています。</div><div> この対策として、変数のポインタをキャストすることで、ビット列の解釈をプログラム上で変更するコードを入れています(floatの内部表現を確認するときにやるやつ)。
</div><div><pre><code>inline void slicer(axi_bus_type bit_data, data_type array[]){
#pragma HLS INLINE
ap_uint<data_bit_width> buffer, bit_mask = -1;
ap_uint<data_bus_width> bus_buffer;
bus_buffer = bit_data.data;
for (uint64_t i = 0; i < field_length; i++){
#pragma HLS UNROLL
buffer = (bus_buffer >> (data_bit_width * i)) & bit_mask;
array[i] = *((data_type*) &buffer);
}
}
inline void packer(data_type data[], packed_type bus_buffer[]){
#pragma HLS INLINE
ap_uint<data_bit_width> buffer;
bus_buffer[0] = 0;
for (uint64_t i = 0; i < field_length; i++){
#pragma HLS UNROLL
buffer = *((ap_uint<data_bit_width>*) &data[i]);
bus_buffer[0] |= ((packed_type)buffer) << (data_bit_width * i);
}
}
</code></pre><br /> 最後これらの関数をまとめ、HLS向けにラップした関数を準備します(<a href="https://github.com/shtsno24/FMAUnit4PYNQ/blob/master/Code/FMA.cpp" target="_blank">コードはこちら</a>).このラップ関数の実体は.hppに記述するのではなく.cppに記述します(.hppに書くと高位合成のターゲット関数にならない).</div><div> 今回はこれに加えてテストベンチを準備します(<a href="https://github.com/shtsno24/FMAUnit4PYNQ/blob/master/Code/FMA_TB.cpp" target="_blank">コードはこちら</a>).基本的には入力データを仕込み,通常のC言語経由とRTL経由で計算を行い比較を行う流れになっています.</div><div><br /></div><h1 style="text-align: left;">3.次回</h1><div><br /></div><div>今回はHLS用のコードまで作成しました。この後は<a href="https://www.shtsno24.tokyo/2022/03/pynqvitis-hlsfmaip2.html" target="_blank">実際の合成をおこないます。</a></div><div>合成して<a href="https://www.shtsno24.tokyo/2022/03/pynqvitis-hlsfmaip3.html" target="_blank">動作確認</a>まで行った後は、</div><div><ul style="text-align: left;"><li><a href="https://www.shtsno24.tokyo/2022/03/pynqvitis-hlsfmaip4.html" target="_blank">バス幅を増やしつつ合わせて並列数も増やす</a></li><li><a href="https://www.shtsno24.tokyo/2022/03/pynqvitis-hlsfmaip4.html" target="_blank">別のデータ型(e.g.固定小数点)への対応</a></li></ul></div><div>あたりをやっていこうと考えています。</div><div><br />
<br />
<div style="text-align: center;">
©2022 shts All Right Reserved.</div>
<pre class="prettyprint lang=c++"></pre>
</div></div></div>Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-29687715527624791572021-11-19T11:56:00.001+09:002021-11-19T15:29:45.023+09:00PYNQ-Z2向けのアクリル天板のレーザーカットを頼んでみた話<div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYiYNBkTxxerjW3y3fFEq8N_9b6oudKWXUvHVUew3eiDXEXdTLvAfIL1D70HmLPGO-rlfpKCi-2kQaozWWYvoKKo5wIgpcRAP1Ktq7h4LgIlP_VFsFqjkfoyHlBtYoDeWiTJHJ6I5livA/s2713/IMG_E4057.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1526" data-original-width="2713" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYiYNBkTxxerjW3y3fFEq8N_9b6oudKWXUvHVUew3eiDXEXdTLvAfIL1D70HmLPGO-rlfpKCi-2kQaozWWYvoKKo5wIgpcRAP1Ktq7h4LgIlP_VFsFqjkfoyHlBtYoDeWiTJHJ6I5livA/w400-h225/IMG_E4057.JPG" width="400" /></a></div></div><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<br />修論が忙しいのに何も手を付けていない中の人です。修論で自前のFPGAボード(PYNQ-Z2)を使ってるのですが、基本裸運用なのでショートやらなんやらが怖い状態です。今回はその対策としてアクリルの天板を作成してみた話です。<div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn4GWcS_M5ptHi5f-UzbjLY3ZHbdHvzoax77HDQm9jC_vYT1By93iCHNhtZjYwS06pcR_5eAZN7nQe6nDN6PoPJfVfnXbxPXSAtm67joCZuQbwzuk2GOvfxyVzUUTKhuUKRELGmFGl8E0/s2930/IMG_E4056.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1648" data-original-width="2930" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn4GWcS_M5ptHi5f-UzbjLY3ZHbdHvzoax77HDQm9jC_vYT1By93iCHNhtZjYwS06pcR_5eAZN7nQe6nDN6PoPJfVfnXbxPXSAtm67joCZuQbwzuk2GOvfxyVzUUTKhuUKRELGmFGl8E0/w400-h225/IMG_E4056.JPG" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">基板には元から足がついているので5mm程度浮いているが,<br />基本むき出しなので不安が残る</td></tr></tbody></table><div><br /></div><div><br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">1.設計する</h1><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggIeHnenyWmfbXVl6l6ha9KT9MQefhTVxFEV8KKNNKQCXTvlgxprmqjPTe6R2287rs5trLQ81s70A7fdTL0_z7LbL2iU6KK8xm9b35MPIurfgsa3HWKg_E0hePebutPDHa9znwKKZlPHo/s750/PYNQZ2_Cover_Outline_Dimension.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="750" data-original-width="739" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggIeHnenyWmfbXVl6l6ha9KT9MQefhTVxFEV8KKNNKQCXTvlgxprmqjPTe6R2287rs5trLQ81s70A7fdTL0_z7LbL2iU6KK8xm9b35MPIurfgsa3HWKg_E0hePebutPDHa9znwKKZlPHo/w394-h400/PYNQZ2_Cover_Outline_Dimension.png" width="394" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">部品の配置図.<br />配置するエリアのサイズを入れることで,領域内に入りますよアピール.</td></tr></tbody></table><div><br /></div><div>天板の設計をするにあたり寸法図を探したのですが、ネットの海にはなかったようでした。そこでその辺にノギスが生えていたので各部を測定し寸法を割り出しました。寸法を割り出したのちFusion360で実際の設計を行い、dxfで出力しました。</div><div><br /></div><div><br /></div><div><br /></div><h1 style="text-align: left;">2.発注する</h1><div><br /></div><div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh47mlUidkZzDp5hsOzKuhymS4o37bmlqqMlaXcqxytt4eq7zCgi_AmnKX7J-EKCNt_FaeWcnDJ3hmLj_CFV9TG42snNVx6AsJ-uct3MS3IXxDnpHtWSIC2xTCadOiQZjDvupUPtTSVZGI/s1126/PYNQZ2_Cover_Rendering.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="698" data-original-width="1126" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh47mlUidkZzDp5hsOzKuhymS4o37bmlqqMlaXcqxytt4eq7zCgi_AmnKX7J-EKCNt_FaeWcnDJ3hmLj_CFV9TG42snNVx6AsJ-uct3MS3IXxDnpHtWSIC2xTCadOiQZjDvupUPtTSVZGI/w400-h248/PYNQZ2_Cover_Rendering.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">完成予想図</td></tr></tbody></table><div><br /></div>設計ができたので次は発注です。今回は手間をあまりかけたくなかったので、レーザーカットのサービスを使うこととし、いろいろ探した結果いつも基板を頼んでいる<a href="https://www.elecrow.com/acrylic-cutting.html" target="_blank">Elecrowのサービス</a>を使うことにしました。</div><div>基板の発注と異なる点として、領域内であればいくつでも部品を置くことができます。無理に1つの部品にする必要はありませんでした。</div><div>先ほど作成したdxfのファイルとともに、カット時の部品の配置図と完成予想図をpdfで添付しました。完成予想図は正直に言っていらないのですが、たまたまあったので入れました。</div><div>発送業者に関しては、最近追加された佐川急便を使ってみました。</div><div><br /></div><h1 style="text-align: left;">3.到着と組み立て</h1><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyOI7ltTtoGqM8-4W8J5XAkQcMfRa1Wj7StNKKa2VH9sAsSirdRnPdHxVl053DFfhhle6LIQvd5yjtdbYL9SmLxHWJ62OZdypKe6RNOJY3nEhanV5qnV340BxG0U4gOVU8Bk3zYBUWa0k/s3450/IMG_E4055.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1941" data-original-width="3450" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyOI7ltTtoGqM8-4W8J5XAkQcMfRa1Wj7StNKKa2VH9sAsSirdRnPdHxVl053DFfhhle6LIQvd5yjtdbYL9SmLxHWJ62OZdypKe6RNOJY3nEhanV5qnV340BxG0U4gOVU8Bk3zYBUWa0k/w400-h225/IMG_E4055.JPG" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">届いた天板とFPGA基板.合計5セット届く.</td></tr></tbody></table><div><br /></div><div>発注が11/10で、到着が11/18だったので1週間ちょっとぐらいでした。おそらく基板と同じ感覚で待てばよさそうです。</div>
<div>実際に組み立てるとこんな感じになりました。PYNQ-Z2に搭載されるチップであればそこまで発熱しないのでファンは不要なのですが、スペースが開いていたので付けました。</div><div>スペーサーは秋月、ねじ・ナット・ワッシャーは近所のホームセンターで購入しました。</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAkd75EkPp5DDNtbMKesa4l0bYpDbvbFOxHdwnc2A67eiVa2Hrc1nIjq0Rnca7T5CUk3Kmyi59S2FoUYyN3t_AvL2llJlHeI-qHu-JJvyOTPnixBDaLya5zOrvSdBzZmCxrmnpBYs888Y/s2713/IMG_E4057.JPG" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1526" data-original-width="2713" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAkd75EkPp5DDNtbMKesa4l0bYpDbvbFOxHdwnc2A67eiVa2Hrc1nIjq0Rnca7T5CUk3Kmyi59S2FoUYyN3t_AvL2llJlHeI-qHu-JJvyOTPnixBDaLya5zOrvSdBzZmCxrmnpBYs888Y/w400-h225/IMG_E4057.JPG" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">組み立てた様子.この時はファンが外側についている.<br />ファンが外に出っ張っていると壊す恐れがあり,この後内側に移設した.</td></tr></tbody></table><div><br /></div><h1 style="text-align: left;">4.まとめ</h1><div><br /></div>初めてレーザーカットのサービスを使ってみましたが、特に詰まるところはありませんでした。簡単な形状であればプリント基板を作るよりも楽にできました。印字みたいなこともできるようなので、また機会があれば試してみたいです。<br />
<br />
<br />
<div style="text-align: center;">
©2021 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
<br /></div>Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-59181057758837465912021-11-12T22:08:00.005+09:002021-11-12T22:11:23.153+09:00ctypesを使ってPython3からC++の生配列(not std::vector)をいじる<script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<br />修論がだんだん忙しくなってきた中の人です.研究でPythonからC++のコードをたたく必要が出てきたのでいろいろお試ししていたのですが,その際にいろいろ詰まったので書き残しておきます.<a href="https://github.com/shtsno24/Python_Cpp_API_Test" target="_blank">今回のコードはこちらに上げてあります.</a><br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">1.PythonからC++をさわる</h1><div><br /></div><div>Python側からC++のコードを実行する方法はPython.hやSWIG,Boost.Python,pybind11など様々なものがあります(<a href="https://www.xsim.info/articles/BoostPython/How-to-make-Python-module-with-BoostPython.html" target="_blank">参考1</a>).今回の研究で使用している環境(HLSツールや実行環境)の問題で,以下の制約がありました.</div><div><br /></div><div><ul style="text-align: left;"><li>相互呼び出しの機能は不要(PythonからC++を実行できればOK)</li><li>STLコンテナが使えない(≒std::vectorなどを使う必要がない)</li><li>g++やCPythonに標準で入っているライブラリのみで行けると非常に楽</li></ul></div><div><br /></div><div>いろいろ調べた結果,とりあえずctypesを使ってみることにしました.</div><div><br /></div><h1 style="text-align: left;">2.C++で共有ライブラリを作成する</h1>
<div><br /></div><div>今回は以下のC++コードをPythonから呼び出します.</div><br />
<pre><code>// MAC_VEC.hpp
#include <cstdint>
namespace MAC_VEC{
template<typename data_t>
void mac_vec(uint32_t size, data_t a[], data_t x[], data_t b[], data_t y[]){
for(uint32_t i = 0; i < size; i++){
y[i] = a[i] * x[i] + b[i];
}
}
}</code></pre>
<div><br /></div><div>ctypesを使う場合テンプレートをそのまま呼び出すことはできないので,型を確定させるラッパーを作っておきます.</div><div>
<br />
<pre><code>// MAC_VEC_WRAPPER.cpp
#include <cstdint>
#include "MAC_VEC.hpp"
extern "C" {
void MAC_VEC_FP32(uint32_t size, float a[], float x[], float b[], float y[]){
MAC_VEC::mac_vec<float>(size, a, x, b, y);
}
void MAC_VEC_INT16(uint32_t size, int16_t a[], int16_t x[], int16_t b[], int16_t y[]){
MAC_VEC::mac_vec<int16_t>(size, a, x, b, y);
}
void MAC_VEC_UINT32(uint32_t size, uint32_t a[], uint32_t x[], uint32_t b[], uint32_t y[]){
MAC_VEC::mac_vec<uint32_t>(size, a, x, b, y);
}
}</code></pre><br />
</div><div>とりあえずfloat(fp32),int16, uint32の3パターン準備しました.この時extern "C"をつけないと,コンパイラ側でシンボル名を書き換える操作を行うため,Python側から読めなくなることがあります(<a href="https://qiita.com/nomunomu0504/items/722a2771fef7d8038ceb" target="_blank">参考2</a>).</div><div>この二つが準備できたら,g++で共有ライブラリ(.so)を生成します.</div><div>
<br />
<pre><code>// generate_so.sh
g++ MAC_VEC_WRAPPER.cpp -shared -o MAC_VEC.so
</code></pre><br />
</div><div>コンパイルが通ると,MAC_VEC.soが生成されるはずです.</div><div><br /></div><h1 style="text-align: left;">3.Pythonから動かす</h1><div><br /></div><div>
先ほど作成したライブラリをPythonから動かしてみましょう.今回使用するctypesは,Python2.5から標準で入っているライブラリです.</div><div>この記事ではMAC_VEC_FP32のみを扱います.残りの二つのに関しては,<a href="https://github.com/shtsno24/Python_Cpp_API_Test/blob/master/C_API_TEST.py" target="_blank">こちらの実装を確認してください.</a></div><div><br />
<pre><code>// C_API_TEST.py
import ctypes
# load .so file
libc = ctypes.cdll.LoadLibrary("./MAC_VEC.so")
# define params and src/dst data
len_vec = 8
coef = 1.1
vec_x = [i * coef for i in range(len_vec)]
vec_a = [2 * coef for i in range(len_vec)]
vec_b = [(i - 8) * coef for i in range(len_vec)]
vec_y = [0 for i in range(len_vec)]
# define data type and convert method
len_vec_type = ctypes.c_uint32
data_type = ctypes.c_float
vec_type = data_type * len_vec
# convert list-type data
_len_vec = len_vec_type(len_vec)
_vec_x = vec_type(*vec_x)
_vec_a = vec_type(*vec_a)
_vec_b = vec_type(*vec_b)
_vec_y = vec_type(*vec_y)
# execution
libc.MAC_VEC_FP32(_len_vec, _vec_a, _vec_x, _vec_b, _vec_y)
# convert results to list-type
result = list(_vec_y)
print(result)
</code></pre></div><div><br /></div><div>配列の型を宣言するあたりの作法で詰まりました.配列のデータ型×配列の要素数で表現し,アンパックしたlistを投げ込むことで変換できるようです.</div><div>実行すると,こんな感じの結果が得られました.</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhggYC7PFgAV0a4zVweUBLeFBrhmabAGhF7L0oF4DoH6y6uu82BlfvOwG-4vP1mHawSgTanb609GYTtrZQUgkH_gGim3gl8pDfdv6ySg5IwkJVnPMKLa3ts8CD9Jy5zZuc65gRAQr4qQE4/s1101/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2021-11-12+202013.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="56" data-original-width="1101" height="33" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhggYC7PFgAV0a4zVweUBLeFBrhmabAGhF7L0oF4DoH6y6uu82BlfvOwG-4vP1mHawSgTanb609GYTtrZQUgkH_gGim3gl8pDfdv6ySg5IwkJVnPMKLa3ts8CD9Jy5zZuc65gRAQr4qQE4/w640-h33/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2021-11-12+202013.png" width="640" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">実行結果.INT16とUINT32の結果も表示している.</td></tr></tbody></table><br /><div>とりあえず正しい結果が得られているようです.</div><div><br /></div><h1 style="text-align: left;">4. まとめ</h1><div><br /></div><div>今回はPythonからC++の生配列をいじってみました.ライブラリの追加も最小限で済み,割と簡単に動かすことができました.少し凝ったデータのやり取りをしようとすると大変かもしれないですが,C/C++標準のデータ型であれば十分に使えると思います.</div><br />
<br />
<div style="text-align: center;">
©2021 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com1tag:blogger.com,1999:blog-1936700217346692515.post-19155955675894698482021-10-13T17:15:00.002+09:002021-10-13T17:15:47.898+09:00GeekServoで遊んでみた<script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<br />
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/d40AVzBSIkI" title="YouTube video player" width="560"></iframe>
<br />
<br />
数か月間ブログの更新をさぼっていた中の人です。今回はLEGOと互換性のあるDCモータ・サーボモータであるGeekServoで遊んでみた話です。
<br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">
0.GeekServoとは
</h1><div><br /></div><div>GeekServoはKittenBot社から発売されているRCサーボモータ・DCモータのシリーズで、日本では<a href="https://www.switch-science.com/catalog/list/?keyword=GeekServo" target="_blank">SwitchScience</a>あたりで購入できます。</div><div><br /></div><h1 style="text-align: left;">1.外見</h1><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPWjATWkEB1W3eMlrBl3qRSEvfqZecSLx8SxATZ2fWiYEmPf68a0Tpmtwo0v4L91aRf-olC-8EFiyc6u9LmPQt__i-ygsZXv8LiHu1gy7KEppBlFVKDWVlpccwvIPHAIJJ6WTUXruXwX4/s1961/IMG_3908.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1103" data-original-width="1961" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPWjATWkEB1W3eMlrBl3qRSEvfqZecSLx8SxATZ2fWiYEmPf68a0Tpmtwo0v4L91aRf-olC-8EFiyc6u9LmPQt__i-ygsZXv8LiHu1gy7KEppBlFVKDWVlpccwvIPHAIJJ6WTUXruXwX4/w400-h225/IMG_3908.HEIC" width="400" /></a></div><br /><div>今回試したのは、<a href="https://www.switch-science.com/catalog/6812/" target="_blank">GeekServoの9G Motor-Red</a>です。GeekServoのシリーズの中ではこのモデルだけがDCモータで、あとはRCサーボになっています。</div><div>出力軸は十字のシャフトになっており、ギアなどを直接接続することができます。また、側面などに丸穴やポッチがあるのでペグやシャフトを接続できます。</div><div><br /></div><h1 style="text-align: left;">2.実際に組んでみる</h1><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQq1eBXGdBaFj7PB_QXA3T8eNe8bAluF1guAVxUFv9M8EVtdqCI-9vMLORrFA0XkV3NIbMancdCZLGleeYoXzIyXd1ZuFIAqYG_dU1z4Jvq2V-hlhj0KNVWAA9xT_j7T_AcvMjJRivvUM/s4608/DSCN1925.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2592" data-original-width="4608" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQq1eBXGdBaFj7PB_QXA3T8eNe8bAluF1guAVxUFv9M8EVtdqCI-9vMLORrFA0XkV3NIbMancdCZLGleeYoXzIyXd1ZuFIAqYG_dU1z4Jvq2V-hlhj0KNVWAA9xT_j7T_AcvMjJRivvUM/w400-h225/DSCN1925.JPG" width="400" /></a></div><br /><div>手元にあった部品を使ってとりあえず組んでみました。</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO7CZr9kYeglEetSqLpUf8LvD99t0ZfQ1WRAJz8YL_fsn6DV-LscNFI5_R3VF0PNWmpQvdACETJYeh0_FECMb5nVTh5UIQw7J9Ge2cA5df31VAigk7VDdKUgraYHQixtdHxG83sG5Jl7E/s4032/IMG_3867.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO7CZr9kYeglEetSqLpUf8LvD99t0ZfQ1WRAJz8YL_fsn6DV-LscNFI5_R3VF0PNWmpQvdACETJYeh0_FECMb5nVTh5UIQw7J9Ge2cA5df31VAigk7VDdKUgraYHQixtdHxG83sG5Jl7E/s320/IMG_3867.HEIC" width="320" /></a></div></div><div><br /></div><div>中身はこんな感じです。横軸と縦軸の両方出力軸に設定できるあたりはいいのですが、ギアの段数が多いために終端のガタが大きいのと、伝達できるトルクが少ないのが欠点でしょうか。</div><div>ここまで大げさな構造になったのは、軸の位置が縦と横の両方で半ポッチずつずれているためで、縦方向には半ポッチ幅のパーツを挟んで調節し、横方向は12枚歯のベベルギアの位置をハーフブッシュでずらしてかみ合う位置に移動させました。</div><div>きれいに0.5ポッチずれているので、半ポッチずらすテクニックがあれば普通に使えそうです。</div><div><br /></div><h1 style="text-align: left;">3.まとめ</h1><div><br /></div><div>今回初めてGeekServoを触ってみたのですが、割と使い勝手がよくびっくりしました。半ポッチずらす必要があるなど多少癖はあるものの、それさえ解消できれば非常に良いものかなと思います。</div><div><br /></div><div><iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/bSJTmEM6n84" title="YouTube video player" width="560"></iframe></div>
<br />
<div style="text-align: center;">
©2021 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-65836191667564334642021-05-26T21:38:00.005+09:002021-05-26T21:41:53.565+09:00UnitV2が手に入った<div><br /></div><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1gyWOXoB2tURZaeTafIPZWkQNrbm9CWvhOYqXuUW2B3NdBNAAUd4V8lOIftfbqo7GMMOHTaK-r_fiSvDb2ttDKhGCXoAIpGo4jsEeFv5IUwNqA7MjqAV4bt_VxQP3PCec17DpsE_SNIY/s4032/IMG_3395.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1gyWOXoB2tURZaeTafIPZWkQNrbm9CWvhOYqXuUW2B3NdBNAAUd4V8lOIftfbqo7GMMOHTaK-r_fiSvDb2ttDKhGCXoAIpGo4jsEeFv5IUwNqA7MjqAV4bt_VxQP3PCec17DpsE_SNIY/w400-h300/IMG_3395.HEIC" width="400" /></a></div><div><br /></div>
暇な時間が欲しい中の人です.今回はM5Stackから発売されたUnitV2を手に入れたのでテストしていきます.
<br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script><h1 style="text-align: left;"><div class="separator" style="clear: both; text-align: center;"><br /></div>
0.UnitV2とは
</h1>
<div><br /></div><div>UnitV2はM5Stackから発売されたプロトタイピングツールです.</div><div>M5Stackのラインナップの中でも最も計算性能が高いものになっています.</div><div>UnitV"2"の名前が示すようにUnitVの後継モデルとなっていますが,CPUに互換性はないうえに,2の方はLinuxが動作しています.</div><div><br /></div><h1 style="text-align: left;">1.外観と内容物</h1><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhR5IyjtY-Z9iV3hM_ozOu8WfTp4a9WQAPrnJBsPC-AojlT-Kq7IsKdQs_NHOuJDHdmstar2Ik36tL9BUSbxNjHGtMlpLhCGVv29-36XgRbDA_bSMC5_6bzUw-8OK1ODN2luwgdl4vs8bE/s4032/IMG_3394.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhR5IyjtY-Z9iV3hM_ozOu8WfTp4a9WQAPrnJBsPC-AojlT-Kq7IsKdQs_NHOuJDHdmstar2Ik36tL9BUSbxNjHGtMlpLhCGVv29-36XgRbDA_bSMC5_6bzUw-8OK1ODN2luwgdl4vs8bE/w400-h300/IMG_3394.HEIC" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div>UnitV2のサイズはUnitVよりもStickVに近いです.ただUnitV2はバッテリーを含まないのでその分薄くなっています.<div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; margin-left: 1em; margin-right: 1em; text-align: center;"><span style="margin-left: 1em; margin-right: 1em;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhK7p8W3085eBmn3ywJPv759tghu4E-61_EfF14jqQnH3JbNK3BS7mJRRE_2zuSvBE462Yi-p05_8yBn9qlnMP5_JVD7bhNslv93nCwbc1Ax-PiS8jHvNijg5UajdqTJ0VClYCiZM7dsk/s4032/IMG_3390.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWWN_D6ICKl6DRPBpv_URanmGusKb-tUReCelpPVf6KNrVI8lyAEPwnUPm_Jgz_7zfD2ql09b63voA4-P8qsDRkvG0EmouOpQCH8mzzF9ZsI_hRX-UlIV5wa1Tw57v0fG4QGl_kKwxUo4/w400-h300/IMG_3391.HEIC" width="400" /></a></span></div></div><div><br /></div>内容物はこんな感じです.16GBのSDカードがついてきます.USBはTypeA-TypeC(おそらく2.0)です.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrbydDRODZaL8gVJp1ZY9dEOsdldydDM0XJl-unIx8mgy4hoKrZjQQRd2k1VG0AvKaKNScVvn0XHkS4YUGX9k-ArgmPllyaiCETDJvu_zDsPeCvNBHlJPjv-vI-4fmDNjafHnFNQ8AlKM/s4032/IMG_3401.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="4032" data-original-width="3024" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrbydDRODZaL8gVJp1ZY9dEOsdldydDM0XJl-unIx8mgy4hoKrZjQQRd2k1VG0AvKaKNScVvn0XHkS4YUGX9k-ArgmPllyaiCETDJvu_zDsPeCvNBHlJPjv-vI-4fmDNjafHnFNQ8AlKM/w300-h400/IMG_3401.HEIC" width="300" /></a></div><div><br /></div><div>治具(1).GoProのものに似たヒンジになっています.</div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpEaO7GhB5BM9cSGTCYZXTl3JX_GElFRV3w9mzi_KAfxI6_ZkO3qXRzU36nkCwyn8B5IQYsHQnJnlsAyzRvQNXcaa9D-0thTNP-6FdoF-3jZ4AEeX8IsITkiD5unsreeoNmupUrKMqhR0/s4032/IMG_3403.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpEaO7GhB5BM9cSGTCYZXTl3JX_GElFRV3w9mzi_KAfxI6_ZkO3qXRzU36nkCwyn8B5IQYsHQnJnlsAyzRvQNXcaa9D-0thTNP-6FdoF-3jZ4AEeX8IsITkiD5unsreeoNmupUrKMqhR0/w400-h300/IMG_3403.HEIC" width="400" /></a></div><br /><div>治具(2).LEGOの部品が付くやつです(赤い部品は付属品ではないです).<br /><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJzQZGjQDZRTPzGr8Gb1SMuokHWcPmhxNeOWsf4Imo7JippzCa-hQPtQEt-G5sUyC3odx90Z4FNCYYm8d-T24xYind0ox-Du-CWyjvV02COTD35E73HzCU_PiERqwzIeW0vyKrARmIflk/s4032/IMG_3406.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJzQZGjQDZRTPzGr8Gb1SMuokHWcPmhxNeOWsf4Imo7JippzCa-hQPtQEt-G5sUyC3odx90Z4FNCYYm8d-T24xYind0ox-Du-CWyjvV02COTD35E73HzCU_PiERqwzIeW0vyKrARmIflk/w400-h300/IMG_3406.HEIC" width="400" /></a></div><div><br /></div>手持ちの画像認識系デバイスを並べました(UnitVはレンズ交換済み).UnitVの小ささが際立っていますね.</div><div><br /></div><h1 style="text-align: left;">2.遊ぶ前の儀式</h1><div><br /></div><div>UnitV2とPCをUSBでつなげるとファンが回転し始め,だんだん暖かくなってきます.この時にデバイスマネージャでUnitV2を探すと不明なデバイスとして認識されます.そのためドライバを充てる必要があります.ドライバは<a href="https://docs.m5stack.com/en/quick_start/unitv2/base_functions" target="_blank">チュートリアルのページ</a>にあるリンクで配布されているので突っ込んでおきます.</div><div><br /></div><div>参考:<a href="https://docs.m5stack.com/en/quick_start/unitv2/base_functions" target="_blank">UnitV2 recognition service - M5Stack</a></div><div><br /></div><div>チュートリアルページの通りにドライバを認識させたのち,ブラウザ(Chromeで動作確認済み)を開き,URLのところに <b><span style="color: #e06666;">UnitV2.py</span></b> or <b><span style="color: #e06666;">10.254.239.1</span></b> と入力します.すると最初から入っているでもプログラムを確認できます.</div><div><div class="separator" style="clear: both; text-align: left;"><br /></div>
<h1 style="clear: both; text-align: left;">3.デモの様子</h1></div><div class="separator" style="clear: both; text-align: center;"><br /></div>
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube-nocookie.com/embed/Mc7zqESRRXw" title="YouTube video player" width="560"></iframe>
<br /><div><br /></div><div>こんな感じで動きます.Yoloの実行の様子を見ている感じだと,UnitVやStickVで使われていたK210のアクセラレータ使用時ほどではないにしろ,そこそこの速さで動いている感じです.<br /><div><br /></div><h1 style="text-align: left;">4.SSH</h1><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4LyPO_AB-96nop4ac2vEexGj38wD4qkWYsfATX0S4SKbDyZVKFuBJiwEj0nBeugppYGTr5GME_lNRJ-50yW9zigakNCBSWfixzer8cVr1MECktUOjltZTdrTXhQGdkeowXzgL05b-k1E/s1428/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2021-05-26+190400.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="702" data-original-width="1428" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4LyPO_AB-96nop4ac2vEexGj38wD4qkWYsfATX0S4SKbDyZVKFuBJiwEj0nBeugppYGTr5GME_lNRJ-50yW9zigakNCBSWfixzer8cVr1MECktUOjltZTdrTXhQGdkeowXzgL05b-k1E/w400-h198/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2021-05-26+190400.png" width="400" /></a></div><br /><div>UnitV2は初期状態でSSH接続による操作をすることができます.</div><div><br /></div><div>参考:<a href="https://docs.m5stack.com/en/quick_start/unitv2/jupyter_notebook" target="_blank">UnitV2 Jupyter Notebook - SSH Connect</a></div><div><br /></div><div>適当なターミナルソフトで <span><b style="color: #e06666;">10.254.239.1:22 </b>にアクセスし,username : m5stack,初期パスワード : 12345678で入れるはずです(本体裏面のシールに書いてある).</span></div><div>組み込みLinuxなので,コマンドポチポチしていくと色々見ることができます.</div><div>ただし,スーパーユーザーになれなかったので電源をコマンドラインから切ることができませんでした(中の人がやり方を知らないだけかもしれません).</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihqNKN9DB8i5PMT4ZBbzVV2lP0boNxl-5ltpgf9ionGLRDtupBK2jSPHwdhVgDDa6ehhcX7FASXUqpdXVtMkQD4QZufGPDocuTy8zeNzfBFaZEVIs22gra3uKrFyBuNAYW6B0-L9kPx3c/s991/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2021-05-26+194542.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="715" data-original-width="991" height="289" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihqNKN9DB8i5PMT4ZBbzVV2lP0boNxl-5ltpgf9ionGLRDtupBK2jSPHwdhVgDDa6ehhcX7FASXUqpdXVtMkQD4QZufGPDocuTy8zeNzfBFaZEVIs22gra3uKrFyBuNAYW6B0-L9kPx3c/w400-h289/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2021-05-26+194542.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">cpuinfoを読みに行った様子.確かにデュアルコア.</td></tr></tbody></table><br /><h1 style="text-align: left;">5.その他</h1></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZsjJJzSUF-S8RtmIo5yx9Z-KTUWV1RuC80Mryu3Hw8lAHLG4vlXEf9lwYKXBtQIbaAylswBRpmivW1MJMqnEsBNR4LhbcSsSwr8wjFpFrlnRzGcdTw27Bfgakwg2lfJOYMXexxg4GrB0/s1024/IMG_3407.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="767" data-original-width="1024" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZsjJJzSUF-S8RtmIo5yx9Z-KTUWV1RuC80Mryu3Hw8lAHLG4vlXEf9lwYKXBtQIbaAylswBRpmivW1MJMqnEsBNR4LhbcSsSwr8wjFpFrlnRzGcdTw27Bfgakwg2lfJOYMXexxg4GrB0/w400-h300/IMG_3407.JPG" width="400" /></a></div><div><br /></div><div>Armv7のデュアルコア(1.2GHz)は初期のRPiを凌駕するほどのCPU性能であり,当然のごとく熱がすごいです.この対策として冷却ファンがついているのですが,振動と音が出ます.もしかしたら気になる人がいるかもしれないです.</div><div><br /><h1 style="text-align: left;">6.まとめ</h1><div><br /></div><div>UnitV2を初めて動かしてみました.ドライバのインストールと電源をコマンドラインから切れないこと以外は特に気になる点はありませんでした.</div><div>今後はncnnやOpenCVを使っていろいろやっていこうと思っています.</div><div><br /></div><div><br /></div><br />
<pre><code>cargo run</code></pre>
<br />
<br />
<div style="text-align: center;">
©2021 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
<br /><br /></div>Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-48712983225038734162021-04-10T16:26:00.010+09:002021-04-10T16:33:42.068+09:00PYNQ V2.6でDMA転送をする話(手打ちでDMAコントローラを制御する)<div><br /></div><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw01rI6lVx3HJyteL3BvP_pHdq5oIwS4FBhtcgT408KmtD-RNinS9t3Q15DOE8i1H7EH1Ni_2uH7iAitjvrzD3Fk_rJA02VBFcqBPosG0yLrEVz-N7u27i8YTO7KI9RYHedOYJxm80lVc/s4032/IMG_3288.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw01rI6lVx3HJyteL3BvP_pHdq5oIwS4FBhtcgT408KmtD-RNinS9t3Q15DOE8i1H7EH1Ni_2uH7iAitjvrzD3Fk_rJA02VBFcqBPosG0yLrEVz-N7u27i8YTO7KI9RYHedOYJxm80lVc/w400-h300/IMG_3288.HEIC" width="400" /></a></div><div><br /></div>
前回,前々回ではPYNQのライブラリでDMA転送を行うための回路の作成とプログラミングを行いました.今回は,pynq.lib.dmaの関数ではなく,AXI-Liteのレジスタを直接操作して同じようなことができないかを探る話です. <div>
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">
1.概要
</h1><div><br /></div><div>DMAコントローラはAXI-Liteを用いて制御しており,PYNQのDMAライブラリ内でもAXI-Liteのレジスタを直接操作してDMA転送を行っています.今回はDMAライブラリが何をしてるかを理解するため,この操作を温かみのある手打ちで実装します.</div><div>ビットストリームは前回使用したものを転用するため,DMAのモードはシンプルモードのままでいきます.</div><div><br /></div><div><a href="https://github.com/shtsno24/PYNQ_V2_6_Example/blob/master/DMA_AXI_STREAM_FIFO/DMA_AXI_STREAM_FIFO_MANUAL.ipynb" target="_blank">今回のnotebookはこちらにあります.</a></div><div><br /></div><div>参考</div><div>Python productivity for Zynq (Pynq),"<a href="https://pynq.readthedocs.io/en/v2.6.1/_modules/pynq/lib/dma.html" target="_blank">pynq.lib.dma — Python productivity for Zynq (Pynq)</a>"</div><div><br /></div><h1 style="text-align: left;">2.方針</h1><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0dwHItgEQrRD-JI4N9RX5Q8X4Vy9_dUfDE-RzabCOQpftJgAGS_oT8SgisyStNO_XhlgRBvN1apQ1GAf-pO0iDzftShyck4QPf2A9LWEtN8WLDpABNBWykr09QpXtJd8TgAclL2YJNRo/s531/DMA.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="210" data-original-width="531" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0dwHItgEQrRD-JI4N9RX5Q8X4Vy9_dUfDE-RzabCOQpftJgAGS_oT8SgisyStNO_XhlgRBvN1apQ1GAf-pO0iDzftShyck4QPf2A9LWEtN8WLDpABNBWykr09QpXtJd8TgAclL2YJNRo/w400-h158/DMA.png" width="400" /></a></div><div><br /></div><div>PS-PL間のDMA転送は,PSからPLへのデータの流れ(Memory-Mapped to Stream:MM2S)とPLからPSへのデータの流れ(Stream to Memory-Mapped:S2MM)の二つが存在し,これらを制御する必要があります.</div><div>MM2S,S2MMの制御手順はほぼ同じではあるものの独立して制御するため,同じ機能のレジスタがMM2S用,S2MM用の2つ準備されています.</div><div><br /></div><div>今回はデータ転送直後にデータ読み出しを行うので,S2MMもMM2Sも同じようなタイミングで操作します.</div><div><br /></div><h1 style="text-align: left;">3.方法</h1><div><br /></div><div>実際にAXI4_Liteを用いて,DMAコントローラを操作していきます.アクセスするレジスタとアドレスの関係は以下の通りです(カッコ内はソースコード内での変数名).</div><div><br /></div><div>MM2S</div><div>DMA制御レジスタ(MM2S_DMACR):0x00</div><div>DMA状態レジスタ(MM2S_DMASR):0x04</div><div>ソースアドレスレジスタ(MM2S_SA):0x18</div><div>転送長さレジスタ(MM2S_LENGTH):0x28</div><div><br /></div><div><div>S2MM</div><div>DMA制御レジスタ(MM2S_DMACR):0x30</div><div>DMA状態レジスタ(MM2S_DMASR):0x34</div><div>ソースアドレスレジスタ(MM2S_SA):0x48</div><div>転送長さレジスタ(MM2S_LENGTH):0x58</div><div><br /></div></div><div>スキャッターギャザーモード(SGモード)でのアドレスはAXI DMA IPの製品ガイドを見てください.</div><div><br /></div><div>参考</div><div>Xilinx.Inc, "<a href="https://www.xilinx.com/support/documentation/ip_documentation/axi_dma/v7_1/j_pg021_axi_dma.pdf" target="_blank">LogiCORE IP AXI DMA v7.1 製品ガイド (PG021)</a>"</div><div>Lauri's blog,"<a href="https://lauri.xn--vsandi-pxa.com/hdl/zynq/xilinx-dma.html" target="_blank">AXI Direct Memory Access</a>"</div><div><br /></div><div><h2 style="text-align: left;">3-1.リセット</h2><div><br /></div><div>1. S2MMのDMA制御レジスタ(0x30)に0x04を書き込む(リセットビットを1にする) </div><div>2. MM2SのDMA制御レジスタ(0x00)に0x04を書き込む(リセットビットを1にする)</div><div><br /></div><div>(S2MMとMM2Sの状態を確認) </div><div><br /></div><div>3. S2MMのDMA制御レジスタに0x00を書き込む(全停止) </div><div>4. MM2SのDMA制御レジスタに0x00を書き込む(全停止) </div><div><br /></div><div>(S2MMとMM2Sの状態を確認) </div><div><br /></div><div><div>最初にS2MM/MM2Sのリセットと停止を行います.通信に失敗してDMAのIPが動作したままだと転送が行えなくなります.</div><div>S2MMとMM2Sの状態はxxxx_DMASRを読み出して確認します.</div></div><div><br /></div><h2 style="text-align: left;">3-2.転送</h2><div><br /></div><div>5. S2MMで書き込むメモリ領域の先頭アドレスをデスティネーションアドレスレジスタ(0x48)に書き込む </div><div>6. MM2Sで読み込むメモリ領域の先頭アドレスをソースアドレスレジスタ(0x18)に書き込む </div><div><br /></div><div>(S2MMとMM2Sの状態を確認) </div><div><br /></div><div>7. S2MMのDMA制御レジスタ(0x30)に0xF001を書き込む(DMAチャンネルの実行&IOC_IrqENとErr_IrqEnの設定) </div><div>8. MM2SのDMA制御レジスタ(0x00)に0xF001を書き込む(DMAチャンネルの実行&IOC_IrqENとErr_IrqEnの設定) </div><div><br /></div><div>(S2MMとMM2Sの状態を確認) </div><div><br /></div><div>9. S2MMの転送長を転送長さレジスタ(0x58)に書き込む(バイト単位) </div><div>10. MM2Sの転送長を転送長さレジスタ(0x28)に書き込む(バイト単位)</div><div><br /></div><div>11. MM2Sの同期を待つ</div><div>12. S2MMの同期を待つ(ここでフリーズするなら、全メモリの範囲がアドレスエディタで割り当てられているかを確認すること) </div><div>(S2MMとMM2Sの状態を確認) </div><div><br /></div><div>転送長を書き込んだ段階で実際にDMAの転送が行われます.</div><div>S2MMやMM2Sの同期は、DMAのステータスがErr_IrqかIdleではない間、whileで待つようにしました。</div></div><div><br /></div><h1 style="text-align: left;">4.まとめ</h1><div><br /></div><div>手打ちでDMAコントローラを制御してみました.マイコンのレジスタの設定とほぼ同じような感じで操作できるようになっており,個人的には比較的わかりやすかったです.</div><div>PYNQ V2.6からはSGモード用の関数も準備されており,直に叩くメリットはほぼないのですが,関数内で何をしているかが分かっていただければ幸いです.</div><div><br /></div>
<br />
<div style="text-align: center;">
©2021 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div>Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-17931718002043299802021-04-09T16:25:00.003+09:002021-04-09T16:27:14.697+09:00PYNQ V2.6でDMA転送をする話(ビットストリーム生成)<div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6vGVR91r85Nh9MQQNl9tGb5NANFJhPK4aTYmCIk3Pm-9A9vdKPgSmPBwr2xKWg57ttX_iS7jTDXVmrsveIrh_rhTnUNwczU_QCJ_LqqsVmArHtlZ3faedqvS5WdK9ZUcgZi_bNRyziu0/s1853/DIAGRAM_DONE.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1054" data-original-width="1853" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6vGVR91r85Nh9MQQNl9tGb5NANFJhPK4aTYmCIk3Pm-9A9vdKPgSmPBwr2xKWg57ttX_iS7jTDXVmrsveIrh_rhTnUNwczU_QCJ_LqqsVmArHtlZ3faedqvS5WdK9ZUcgZi_bNRyziu0/w400-h228/DIAGRAM_DONE.png" width="400" /></a></div><div><br /></div>
絶賛就活中,中の人です.気晴らしがてら進めていた研究の方でPYNQのDMAを使うことがあったのですが,その際に得た知見をまとめようと思います.<div><a href="https://github.com/shtsno24/PYNQ_V2_6_Example/tree/master/DMA_AXI_STREAM_FIFO" target="_blank">ビットストリームはこちらに上げてあります</a>. <br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">
1.環境</h1><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHjqMp2n8R20nTFihthfAchtgsKZy7hc6doFBfW-cZUQ1BcZc0mT1nSdr2ErsfiHFXZyqEbI1tDPAbGJCfWskYbVrCEet5sBzAer4F6CpuR-30FjRfyWKdoyn0iMO31bfbESirVEaLADg/s4032/IMG_3288.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHjqMp2n8R20nTFihthfAchtgsKZy7hc6doFBfW-cZUQ1BcZc0mT1nSdr2ErsfiHFXZyqEbI1tDPAbGJCfWskYbVrCEet5sBzAer4F6CpuR-30FjRfyWKdoyn0iMO31bfbESirVEaLADg/w400-h300/IMG_3288.HEIC" width="400" /></a></div><div><div><br /></div><div>ボード:PYNQ-Z2(TUL製,xc7z020clg400-1搭載)</div><div>Vivado : Vivado 2020.1</div><div>PYNQ : V2.6</div><div>OS Ubuntu 20.04LTS</div></div><div><br /></div><div>特に変哲のない感じですが,PYNQ V2.6はVivado 2020.1でビルドされているので,それに合わせてバージョンを決めた感じです.</div><div><br /></div><h1 style="text-align: left;">2.どんな回路を作るか</h1><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCcq961iqf5Ord5I-hwfmHocOrdJEzD3YsIt8D1FAGA0_SrECrlZ_vnOJxZnFYf06yh_7C_i3RF2zxUWftSirdmUO-aRjNvh01gIzCnA2BMpJ0Eej0YezpsHkGC_Rx_A9mwUxzLKw00tE/s1853/DIAGRAM_DONE.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1054" data-original-width="1853" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCcq961iqf5Ord5I-hwfmHocOrdJEzD3YsIt8D1FAGA0_SrECrlZ_vnOJxZnFYf06yh_7C_i3RF2zxUWftSirdmUO-aRjNvh01gIzCnA2BMpJ0Eej0YezpsHkGC_Rx_A9mwUxzLKw00tE/w400-h228/DIAGRAM_DONE.png" width="400" /></a></div><div><br /></div><div>CPUにぶら下がっているDDR3メモリとPL部をつなぎ,メモリ->FIFO(PL部)->メモリというような簡単な回路で動作確認を行います.</div><div><br /></div><h1 style="text-align: left;">3.PS部とPL部の橋渡し.</h1><div><br /></div><div><div>PYNQ-Z2で使用されているZYNQ 7000シリーズでは,FPGA(PL)とCPU(PS)に接続されたDDR3メモリをAXIバスを介して接続することができます.この機能はZYNQ内に存在するポートを使うことで使用できます.</div><div>このポートいくつか存在しており,32b GP AXI Master Ports(M_AXI_GPx),32b GP AXI Slave Ports(S_AXI_GPx),AXI High Performance 32b/64b Slave Ports(S_AXI_HPx),64b AXI ACP Slave Portのように通信の種類に応じて分けられています.</div></div><div><br /></div><div><div>参考</div><div>なひたふJTAG日記,"<a href="http://nahitafu.cocolog-nifty.com/nahitafu/2013/11/zynqfpgaplarmps.html" target="_blank">ZYNQでFPGA(PL)からARM(PS)のDDR3メモリへDMA転送</a>"</div></div><div><br /></div><h1 style="text-align: left;">4.AXIバスの通信規格</h1><div><div>AXIバスの通信規格にはいくつかの種類があります(AXI4だとAXI4(-Full),AXI-Lite,AXI-Stream).</div><div>今回使用するDMAのIPの制約で,FIFOとDMAコントローラ間はAXI-Stream,PS(S_AXI_HP)とDMAコントローラ間はAXI-Fullを使用します.またいくつかのIPでAXI-Liteによる制御が必要なので,そちらも使用します.</div><div><br /></div><div>参考</div><div>武内 修,"<a href="https://dora.bk.tsukuba.ac.jp/~takeuchi/?%E9%9B%BB%E6%B0%97%E5%9B%9E%E8%B7%AF%2FHDL%2FVivado%E3%81%A7AXI%E3%83%90%E3%82%B9%E3%82%92%E5%88%A9%E7%94%A8#v002e43c" target="_blank">HDL/VivadoでAXIバスを利用</a>"</div><div><br /></div></div><h1 style="text-align: left;">5.ブロックダイアグラムを作る</h1><div><div>ここからブロックダイアグラムを作っていきます.</div><div><br /></div><h2 style="text-align: left;">5-1.PSの設定</h2><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKvfw4pi9aXae2bxaupjeeCg_dF5sKH0SG0Fi9XkPVy466U-vI2qh0JyQvN4g39P4fmN7-GJGQUVITvhzcyDFk31oNEwJqkDAMGgY06dcFcczMeopPqjFjU0KJ-435gP_FFKQMkp-6Kbo/s1180/ZYNQ7_RUN_BLOCK.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="526" data-original-width="1180" height="178" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKvfw4pi9aXae2bxaupjeeCg_dF5sKH0SG0Fi9XkPVy466U-vI2qh0JyQvN4g39P4fmN7-GJGQUVITvhzcyDFk31oNEwJqkDAMGgY06dcFcczMeopPqjFjU0KJ-435gP_FFKQMkp-6Kbo/w400-h178/ZYNQ7_RUN_BLOCK.png" width="400" /></a></div><div><br /></div><div>PSとして,Zynq7 Processing System(5.5)を使います.</div><div>DDRメモリやFIXIOへの接続ポートを先に生成しておきます。</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfRGpmbl21lQuAbeNABuO2WRIdnRiO5XNkvCK1aAysDcVrsUOG6SyaZVA59yb4TisMv0P79QK2Wu9F-XH1369wZaf_Ea0UL4gK__2dPMvKLG_oIay_TpXQNbL-vTRz4uxPWxLt8Y9XTmc/s986/Zynq7_Processing_System_after.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="883" data-original-width="986" height="359" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfRGpmbl21lQuAbeNABuO2WRIdnRiO5XNkvCK1aAysDcVrsUOG6SyaZVA59yb4TisMv0P79QK2Wu9F-XH1369wZaf_Ea0UL4gK__2dPMvKLG_oIay_TpXQNbL-vTRz4uxPWxLt8Y9XTmc/w400-h359/Zynq7_Processing_System_after.png" width="400" /></a></div><div><br /></div><div>ここではメモリとPLを接続するため,ポート(M AXI GP0とS AXI HP0)の設定を行います.Vivado 2020.1ではM AXI GP0の方は最初から有効化されているようで,有効化されていないS_AXI_HP0は手動で有効化します.この際に,S_AXI_HP0のデータ幅は64bitにしておきます.</div><div><br /></div><h2 style="text-align: left;">5-2.DMAコントローラの設定</h2><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV91CyWaVWW2DYpiJ8DJYtlFGNYtRXc6mRLUXTBZgILhhf13MzIZrVoSMgh1zjMXIIXLstXH-Ny7wO0FYvjT2DhJTFtUoK5X65KRI86lA-LtjcKk8Clyg5xfj5GAoSpnLGI20Xi_pmR_c/s1174/AXI_DMA_IP_AFTER.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="864" data-original-width="1174" height="295" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV91CyWaVWW2DYpiJ8DJYtlFGNYtRXc6mRLUXTBZgILhhf13MzIZrVoSMgh1zjMXIIXLstXH-Ny7wO0FYvjT2DhJTFtUoK5X65KRI86lA-LtjcKk8Clyg5xfj5GAoSpnLGI20Xi_pmR_c/w400-h295/AXI_DMA_IP_AFTER.png" width="400" /></a></div><div><br /></div><div>今回使うIPはXilinx提供のAXI Direct Memory Access(7.1)です.</div><div>PYNQのv2.6からScatter Gather Engineをサポートするようになったのですが,今回はシンプルモードで試すのでチェックを外しておきましょう.</div><div>また,バッファ長を設定するレジスタ(Width of Buffer Length Register)は最大値の26まで引き上げておきましょう.</div><div>ここではAddress Widthを32bitとしておきます.</div><div>DMAのIPを二つ配置し,それぞれRead-Only, Write-Onlyにすることも可能ですが,今回はR/Wの双方を使えるようにしておきます.</div><div>今回の回路ではint16のデータを流すので,Read Channel側のMemory Map Data Widthを32bit,Stream Data Widthを16bitに設定しておきます.</div><div><br /></div><h2 style="text-align: left;">5-3.FIFOの設定</h2><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ6CJ3496eyQsVFUsPN94yd7PBCCM43pEr2zWHXSyxTTcVKZxYQwzPboNE1iPngRYi6N-T_r1QyHfvjw-IOlviwjQKrHe6DdXg2p3bNn9n-Ni8ulTJoejT59EqfSIF3DPNI2Y1Bu8e2F4/s1175/AXI4_STREAM_DATA_FIFO_DEFAULT.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="864" data-original-width="1175" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ6CJ3496eyQsVFUsPN94yd7PBCCM43pEr2zWHXSyxTTcVKZxYQwzPboNE1iPngRYi6N-T_r1QyHfvjw-IOlviwjQKrHe6DdXg2p3bNn9n-Ni8ulTJoejT59EqfSIF3DPNI2Y1Bu8e2F4/s320/AXI4_STREAM_DATA_FIFO_DEFAULT.png" width="320" /></a></div><div><br /></div><div>FIFOとして,Xilinx提供のAXI4-Stream Data FIFO(2.0)を使用します.特段設定をかえる必要はないと思います.</div><div><br /></div><h2 style="text-align: left;">5-4.IPの配置と配線</h2><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPbCfaswcsyDKoOcdxKGNn9sUn-uC_zn8PUJSlCq2c7jJMwFAtZe4fmgXnNSxOpJDCrn2t6eF67H3YIHQRdbc1RJX1DFE9zBC6y8OxbR39c9nOPDDO4kuthu6KBIo-a_UQnjTXWIb31RU/s1853/DIAGRAM_DONE.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1054" data-original-width="1853" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPbCfaswcsyDKoOcdxKGNn9sUn-uC_zn8PUJSlCq2c7jJMwFAtZe4fmgXnNSxOpJDCrn2t6eF67H3YIHQRdbc1RJX1DFE9zBC6y8OxbR39c9nOPDDO4kuthu6KBIo-a_UQnjTXWIb31RU/w400-h228/DIAGRAM_DONE.png" width="400" /></a></div><div><br /></div><div>PSのブロックをDiagramに追加し,DDRとFIXED_IOの自動配線を終えたのち,DMAコントローラとFIFOを追加します.</div><div>そして,DMAコントローラとFIFOのAXI Streamのバスをつなぎます.</div><div>DMAコントローラとPSのS_AXI_HP0との接続にはAXI SmartConnectをかませました(Vivado2020.1の自動配線だと,別のIPが出てきました).</div><div>その後、自動接続を使い、他の配線を行いました。</div><div><br /></div><h1 style="text-align: left;">6. 合成とファイルの生成</h1><div><br /></div><div>先程のブロック図をValidate Designにかけると、アドレスが振られていない警告が出てくるので、アドレスエディタでアサインしておきましょう。もう一度チェックを走らせると、CriticalWarningは消えているはずです。</div><div><br /></div><div>Generate Output Products,Generate HDL Wrapperをし,ビットストリームを生成しました.</div><div>PYNQ上で実行する際には,.bit及び.hwhが必要になります(V2.6では.tclは不要みたいです).</div><div>以下の二つのフォルダから.bit及び.hwhを探します.</div><div><br /></div><div>プロジェクト名.runs/impl_1/デザイン名_wrapper.bit</div><div>プロジェクト名.src/source_1/bd/デザイン名/hw_handoff/デザイン名.hwh</div><div><br /></div><div>これらのファイルをPYNQ上のフォルダに投げ込めば,Vivado上での操作は完了です.</div><div>(プロジェクト名.src/source_1/bd/デザイン名/hw_handoff/デザイン名.tcl は無くても動くみたいです。)</div></div><div><br /></div><h1 style="text-align: left;">7.まとめ</h1><div><br /></div><div>ビットストリームの生成まで完成しました.<a href="https://www.shtsno24.tokyo/2021/04/pynq-v26dmajupyternotebook.html" target="_blank">次はPYNQ上での操作に移っていきます</a>.</div><div><br /></div><div><br /></div>
<br />
<div style="text-align: center;">
©2021 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div>Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-85511229514752415312021-04-09T16:25:00.002+09:002021-04-09T16:26:28.633+09:00PYNQ V2.6でDMA転送をする話(JupyterNotebook上での実行)<div><br /></div><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3ALs2FyMjiYLT5eSAePsQz2LyvLoxKKhWt1jP6fqwdWu5w_KIVqcU_3o0er9fqz-wMPRTFc3JGsXQcmt6qMVZSueegrbkEnf9EtHn9hgftyU0cjhz4Zz0BYG9zfkOEXDin2jVjUSkEtQ/s4032/IMG_3288.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3ALs2FyMjiYLT5eSAePsQz2LyvLoxKKhWt1jP6fqwdWu5w_KIVqcU_3o0er9fqz-wMPRTFc3JGsXQcmt6qMVZSueegrbkEnf9EtHn9hgftyU0cjhz4Zz0BYG9zfkOEXDin2jVjUSkEtQ/w400-h300/IMG_3288.HEIC" width="400" /></a></div><br />
前回に引き続きDMA転送の話です.今回は<a href="https://www.shtsno24.tokyo/2021/04/pynq-v26dma.html" target="_blank">前回作成したビットストリーム</a>を実行していきます.<a href="https://github.com/shtsno24/PYNQ_V2_6_Example/blob/master/DMA_AXI_STREAM_FIFO/DMA_AXI_STREAM_FIFO.ipynb" target="_blank">今回のnotebookはこちらに上げています</a>.<br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">
1.PYNQで動かす</h1><div><br /></div><div><div>PYNQ上のJupyter Notebookにアクセスする話は割愛します.</div><div>とりあえず適当なからフォルダを作り,その中に先ほどの.bitと.hwhを入れ,.ipynbをそのフォルダ内で新規で作成しておきます..bitと.hwhはファイル名をそろえておきます(今後はdesign_1.bit, design_1.hwhとする).</div></div><div><br /></div><h2 style="text-align: left;">1-1.オーバーレイのロード</h2><div><br /></div>
<pre><code>from pynq import Overlay
from pynq import PL
OL = Overlay("design_1.bit")
print(OL.ip_dict.keys())
dma = OL.axi_dma_0</code></pre>
<br />ビットストリームの読み込みはこれで完了です..bitのファイル名を使用して.hwhを読み込むようなので,名前はそろえておきましょう.
OL.ip_dictには使用したIPのうち,PS側から操作できるものが辞書として登録されています.
この辞書内からdmaのIPを探し出し,dmaとしておきましょう.<div><br /></div><h2 style="text-align: left;">1-2.xlnkとAllocate</h2><div><br />
<pre><code>import numpy as np
from pynq import allocate
data_src = allocate((100,), dtype=np.int16)
for i in range(100):
data_src[i] = i + 1
data_dst = allocate((512,), dtype=np.int16)
print("size of data_src :", data_src.nbytes, "Byte")
print("size of data_dst :", data_dst.nbytes, "Byte")</code></pre>
<div><br /></div><div>V2.6のPYNQでは,旧来より使われてきたXlnkに代わり,allocateを使うようになっています.今回はAXI-Streamのデータ幅を16bitにしたので,dtypeも16bitのモノに設定しました.入出力のバッファ領域をこれで確保しました.</div><div><br />
</div><h2 style="text-align: left;">1-3.実行</h2><div><br /></div><div>
<pre><code>print(data_dst)
dma.sendchannel.transfer(data_src)
dma.sendchannel.wait()
print("send done")
dma.recvchannel.transfer(data_dst)
dma.recvchannel.wait()
print("receive done")
print(data_dst)</code></pre></div><div><br /></div><div>
dmaのメンバ関数にsendchannel,recvchannelがあり,それぞれにtransferとwaitがあります.この辺は以前のPYNQと変わらずに使えます.</div><div><br /><h1 style="text-align: left;">
2.まとめ
</h1></div><div><br /></div><div><div>とりあえずこのような形でPYNQ+DMAの動作を確認出来ました.</div><div>そのうちVivado HLSで作成したIPを埋め込み,動作させたいと思います.</div><div><br /></div><div>参考</div><div>okchan08,<a href="https://okchan08.hateblo.jp/entry/2019/03/16/223000" target="_blank">ZYNQでAXI DMAを試してみる</a></div></div><div><br />
<br />
<div style="text-align: center;">
©2021 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div></div>Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-15095691327226123092021-04-03T21:02:00.000+09:002021-04-03T21:02:32.736+09:00スイッチサイエンスのジャンク品買ってみた<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaEOr02AlYY_BN5HxIExgq-iXXxcTHBkOF9nF8o6TITkL90n4wYH3ttfGyUiI01qo-EoFl5pLETG61mtEEiE1k4qK-0mzyQc4Q5jOQEsp261gfvxYk42zny_l9CKbYmRmA6LTahzosges/s4032/IMG_3237.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaEOr02AlYY_BN5HxIExgq-iXXxcTHBkOF9nF8o6TITkL90n4wYH3ttfGyUiI01qo-EoFl5pLETG61mtEEiE1k4qK-0mzyQc4Q5jOQEsp261gfvxYk42zny_l9CKbYmRmA6LTahzosges/w400-h300/IMG_3237.HEIC" width="400" /></a></div><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<br />
絶賛就活終わらない中の人です.先日Twitterを眺めていたところ,このような記事が流れてきました.
<br />
<br />
<iframe class="hatenablogcard" frameborder="0" scrolling="no" src="https://hatenablog-parts.com/embed?url=https://mag.switch-science.com/2021/03/31/ジャンク品放出します/" style="display: block; height: 155px; margin: 12px 0; max-width: 680px; width: 100%;" title="%title%"></iframe>
<br />
<br />
たまたまその時間は待機できそうだったので争奪戦に参加しました.結果1セット手に入れることができたので,少し見ていこうかと思います.
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">1.内容物</h1>
<div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYVTDlA6qGssmbyBarSMvpejtSYA1WfZSLSu_O3o9Sgone0YaQEKtNZCbmNEKfmq9jRfN4VNwo5jhStxRQGtXOG4EoYr0QhA70xeDpLwi8JQjIkxl5W2xQnb0hczFYn58Kzb4SXENm1eA/s4032/IMG_3234.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYVTDlA6qGssmbyBarSMvpejtSYA1WfZSLSu_O3o9Sgone0YaQEKtNZCbmNEKfmq9jRfN4VNwo5jhStxRQGtXOG4EoYr0QhA70xeDpLwi8JQjIkxl5W2xQnb0hczFYn58Kzb4SXENm1eA/w400-h300/IMG_3234.HEIC" width="400" /></a></div><div><br /></div>中身はこんな感じでした.内容物としては,<div><br /></div><div>M5StickC x 1</div><div>M5Gray x 1</div><div>M5Faces x 1</div><div><br /></div><div>となっていました(<a href="https://www.switch-science.com/catalog/7081/">https://www.switch-science.com/catalog/7081/</a>の例2のパターン).</div><div><br /></div><h1 style="text-align: left;">2.少し動かしてみた</h1><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXH6DlKsbokKSCprzPEINicskJypyEfa5jzONkI3WYwcT26kMiCoAc1ynQXl6eOQvDGojuu0G6eV3T2UYT2M-fyc7EIjA1oLFMbjbkdaCJoEmd4NU5DY8aVpJPK4Xd03mRvz5qfEa2NXw/s2460/IMG_3238.HEIC" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1845" data-original-width="2460" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXH6DlKsbokKSCprzPEINicskJypyEfa5jzONkI3WYwcT26kMiCoAc1ynQXl6eOQvDGojuu0G6eV3T2UYT2M-fyc7EIjA1oLFMbjbkdaCJoEmd4NU5DY8aVpJPK4Xd03mRvz5qfEa2NXw/w400-h300/IMG_3238.HEIC" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">M5Gray.UIFlowのファームが元から書き込まれていた.</td></tr></tbody></table><div><br /></div><div>最初にUSBケーブルをつなぎ,電源だけを供給させて動作するか試してみました.</div><div>StickCとGrayについては,元からUIFlowのファームが書き込まれており,電源を入れただけで動作しました.</div><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRdoKSzeRr-gfyJhEs9-hRqzmC-iCFtKP0aIXX34n59wPXwl0Ssd_0xYjLgTzC3gA6RyphuZN2-GdNZET5pWqrL4lleRT7urBRVTtMkFSSWHQEOrS4Qpm-Py2nWNGUm7MmRWRggJqBt5o/s2812/IMG_3235.HEIC" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="2109" data-original-width="2812" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRdoKSzeRr-gfyJhEs9-hRqzmC-iCFtKP0aIXX34n59wPXwl0Ssd_0xYjLgTzC3gA6RyphuZN2-GdNZET5pWqrL4lleRT7urBRVTtMkFSSWHQEOrS4Qpm-Py2nWNGUm7MmRWRggJqBt5o/w400-h300/IMG_3235.HEIC" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">FacesにArduinoのサンプルコードを入れたところ.<br />加速度センサはMPU6886らしい.</td></tr></tbody></table><div><br /></div><div>Facesに関しては電源を入れても何も表示されませんでした.PCに接続したところCOMポートが割り当てられたので,試しにArduinoでサンプルコードを入れたところ無事動作することがわかりました.3種類のキーボードも動作することを確かめました.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh654P2wiLe00IxnSVLGE7mRKdq-AEPOeCzwdlWilIv6k4qQWRvHvJ2Hi9RNATihOMcYA3W-o7lIef-D9afvo21U5oqcab-PmsjLayoGhRfwpwYSfxdiapRFO1Jz8sRRX7ob9CpVJbrl_U/s4032/IMG_3240.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="3024" data-original-width="4032" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh654P2wiLe00IxnSVLGE7mRKdq-AEPOeCzwdlWilIv6k4qQWRvHvJ2Hi9RNATihOMcYA3W-o7lIef-D9afvo21U5oqcab-PmsjLayoGhRfwpwYSfxdiapRFO1Jz8sRRX7ob9CpVJbrl_U/s320/IMG_3240.HEIC" width="320" /></a></div><div><br /></div><div>唯一,Facesのベース内部のフレキが根元から断線していたため,グレードルが使えませんでした.今のところは特に使う場面は無いので,当面は放置になりそうです.</div><div><br /></div><h1 style="text-align: left;">3.まとめ</h1><div><br /></div><div>ジャンクということもあり全く動かないことを覚悟していたのですが,あっさり動いてしまいました.返品されたもののうち軽い修正で使えそうなものを選んだとなっていたのですが,出荷前にある程度の修理や動作確認も行ったように見えました.</div><div>保証は当然なく,壊れても自己責任なので初心者には絶対にお勧めできませんが,個人的には満足な買い物でした.</div><div><br /></div><div>
<br />
<div style="text-align: center;">
©2021 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div>Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-73500160262555517642021-02-28T23:29:00.000+09:002021-02-28T23:29:34.145+09:00RPi Pico向けRustサンプルコードを動かす(Win10 + PowerShell + WSL)<div><br /></div><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpuSKPPMP4pUcA6VCCRnL4TQgnoFDTaNwSOtuJfRbT62e5Ast5HKP851lJtCPXoxz3nRg5oVNuF_4r_HmlTCj5n_lxm5IhCnUNsVlTF8w8KIMIESBvvCQEi5uMwhzPyUE1aAdgU7_UlW8/s2749/IMG_3130.HEIC" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2062" data-original-width="2749" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpuSKPPMP4pUcA6VCCRnL4TQgnoFDTaNwSOtuJfRbT62e5Ast5HKP851lJtCPXoxz3nRg5oVNuF_4r_HmlTCj5n_lxm5IhCnUNsVlTF8w8KIMIESBvvCQEi5uMwhzPyUE1aAdgU7_UlW8/w400-h300/IMG_3130.HEIC" width="400" /></a></div><br /><div><br /></div>
就活解禁数時間前にブログを書き出す中の人です.少し前にRPi PicoをWSL + C/C++ SDKで実装する話を書いたのですが,どうやらRustで動くサンプルコードがあるようだったので,実際に動かしてみました.<div><br /></div><div>今回はEmbedded Rustの話は置いといて,とにかくサンプルコードをRPi Pico上で動かすことにフォーカスします.そのためコードやクレートの解説はほかの資料に譲ることにします.</div><div><br /></div><div>サンプルコード:<a href="https://github.com/rp-rs/sample-project">https://github.com/rp-rs/sample-project</a></div><div><br /></div><div>
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">1.RPi PicoとEmbedded Rust</h1><div><br /></div><div>そもそもRustで組込みプログラミングができるのかという問題があるのですが,Arm Cortex-M系のマイコンであれば動かすことができるようです.RPi PicoのマイコンであるRP2040はCortex-M0+のデュアルコアなのでRustが動かせるというわけです.</div><div><br /></div><div>参考:</div><div>The Embedded Rust Book, <a href="https://rust-embedded.github.io/book/">https://rust-embedded.github.io/book/</a></div>
<div><br /></div><h1 style="text-align: left;">2.何をやるか</h1><div><br /></div><div>今回はデバッガ等も使わずに,ただひたすらにバイナリを吐き出しLチカを</div>することにフォーカスします.</div><div><br /></div><h1 style="text-align: left;">3.環境</h1><div><br /></div><div>今回は,コードのビルドとELF->UF2の変換で使う環境を変えました.</div><div><br /></div><div>ビルド:Rust(1.52.0-nightly) + PowerShell</div><div>ELF->UF2の変換:WSL2(Ubuntu 20.04)</div><div><br /></div><div>最初はWSL2一本でやろうと思ったのですが,cargo buildを実行した際に</div><div><br /></div><div>
<pre><code>error: RPC failed; curl 56 GnuTLS recv error (-24): Decryption has failed.</code></pre></div><div><br /></div><div>
のエラーが出てしまい,ビルドが通らなくなる現象が解決しなかったので今回はPowerShellを使いました(GitHubとの通信で出るようで,git fetchやgit cloneが使えなくなる).
</div><div>ビルド後の処理でC/C++SDKに含まれるツールが必要になるので,WSL2の方の環境構築もお勧めします.詳細は,<a href="https://www.shtsno24.tokyo/2021/02/raspberry-pi-picocc-wsl2.html" target="_blank">こちらを参考にしてください.</a></div><div><br /></div><div>ビルド環境の方は,<a href="https://www.rust-lang.org/ja/tools/install" target="_blank">公式の手順通り</a>にRustを突っ込んだのちにarm-none-eabi-gdbを突っ込みます.この辺りはEmbedded Rustでの手順と同じですが,今回はデバッガを使わないので,OpenOCDなどは入れません.</div><div>arm-none-eabi-gdbをインストールする際に,必ず環境変数にパスを追加するようにしましょう.インストールの最後に出てくる画面にAdd path to environment variableのオプションが出てくるのでチェックを入れましょう(初期状態だとチェックがないはず).</div><div><br /></div><h1 style="text-align: left;">4.サンプルコードのクローン</h1><div><br /></div><div><div><a href="https://github.com/rp-rs/sample-project">https://github.com/rp-rs/sample-project</a></div><div><br /></div><div>を適当な場所にクローンしましょう.ビルド作業はこのsample-project内で行います.</div></div><div><br /></div><h1 style="text-align: left;">5.ビルド</h1><div><br /></div><div>早速ビルドに移るのですが,そのままではCortex-M0+のELFファイルを吐き出してくれません.そこでおまじない</div><div><br /></div><div>
<pre><code>rustup target add thumbv6m-none-eabi</code></pre><div><br /></div>
を実行しておきます.これを実行したうえで</div><div><br /></div><div>
<pre><code>cargo run</code></pre><div><br /></div>
すれば./target/thumbv6m-none-eabi/debug内にrp-testというELFファイルが吐き出されているはずです(実態はELFファイルだが,拡張子がない状態で吐き出される).
</div><div><br /></div><h1 style="text-align: left;">6.ELF2UF2</h1><div><br /></div><div>.elfも生成出来たのでRPi Picoへ実装したいのですが,Picoへ実装する際に.uf2に変換する必要があります.これを行うツールがRPi PicoのC/C++ SDKに入っています.このツールは事前にビルドする必要があります.今回はこのビルドをWSL2上で行うことにします.</div><div><br /></div><div>
<pre><code>cd (pico-sdkのあるフォルダ)
cd pico-sdk/tools/elf2uf2
mkdir build
cd build
cmake ..
make
sudo cp elf2uf2 /usr/local/bin/</code></pre><div><br /></div>ビルド終了後,WSL2でelf2uf2と打ち込み,</div><div><br /></div><div>
<pre><code>Usage: elf2uf2 (-v) <input ELF file> <output UF2 file></code></pre><div><br /></div>と出てくればelf2uf2のビルド成功です.ここで先ほどのrp-testをrp-test.elfとリネームしておきましょう.elf2uf2の<input ELF file>は拡張子が.elfのファイルだけを受け入れるので注意しましょう.</div><div>最後に</div><div><br /></div><div>
<pre><code>elf2uf2 rp-test.elf rp-test.uf2</code></pre><div><br /></div>を実行すれば,rp-test.uf2が出来ているはずです.</div><div><br /></div><h1 style="text-align: left;">7.実機で動かす</h1><div><br /></div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="266" src="https://www.youtube.com/embed/zoQ8wAzYSbI" width="416" youtube-src-id="zoQ8wAzYSbI"></iframe></div><br /><div><br /></div><div>.uf2を実機に入れるところの操作はC/C++ SDKと全く同じなので割愛.</div><div>こんな感じでLチカ完了です.</div><div><br /></div><h1 style="text-align: left;">8.感想</h1><div><br /></div><div>Embedded Rustとほぼ同じなので,開発環境についてはある程度ほかのマイコンでの知見が生かせそうです.またデバッガを使う場合は,OpenOCDやらなんやらのインストールが必要みたいです.</div><div><div><br /></div></div><h1 style="text-align: left;">9.参考</h1><div>"rp-rs/sample-project", <a href="https://github.com/rp-rs/sample-project">https://github.com/rp-rs/sample-project</a></div><div>"The Embedded Rust Book 日本語版",<a href="https://tomoyuki-nakabayashi.github.io/book/intro/index.html">https://tomoyuki-nakabayashi.github.io/book/intro/index.html</a></div><div>"Crate cortex_m_quickstart", <a href="https://rust-embedded.github.io/cortex-m-quickstart/cortex_m_quickstart/">https://rust-embedded.github.io/cortex-m-quickstart/cortex_m_quickstart/</a></div><div>"PicoボードにPico_SDKでC言語をビルドする", <a href="https://beta-notes.way-nifty.com/blog/2021/02/post-2fff25.html">https://beta-notes.way-nifty.com/blog/2021/02/post-2fff25.html</a></div><div><br /></div><div><br />
<br />
<div style="text-align: center;">
©2021 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div>Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-16037809391870778672021-02-26T22:48:00.001+09:002021-02-26T22:50:15.074+09:00Raspberry Pi PicoのC/C++ 環境をWSL2上に構築する<script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><br /><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQO5kGu5fikAiKIVR-auAd7zqAv1WdcJVv6JNqULIdQ2bMvn3TkHTyPLLnesmNwOzWloDZLFj8MnuIVx1KApkeDok54vAKe4P4vPNZj4lY5bsCdzeGjXHTIpddOMRekg7tJJT5CE08KdY/s2749/IMG_3130.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2062" data-original-width="2749" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQO5kGu5fikAiKIVR-auAd7zqAv1WdcJVv6JNqULIdQ2bMvn3TkHTyPLLnesmNwOzWloDZLFj8MnuIVx1KApkeDok54vAKe4P4vPNZj4lY5bsCdzeGjXHTIpddOMRekg7tJJT5CE08KdY/w400-h300/IMG_3130.HEIC" width="400" /></a></div>
<div><br /></div>絶賛就活中の中の人です.この度Raspberry Pi Pico(RPi Pico)が運良く入手できたので,開発環境を整えてみたいと思います.<div><br /></div><div>この記事は<a href="https://qiita.com/kmak" target="_blank">@kmak</a>さんの<a href="https://qiita.com/kmak/items/a14b9e9673875ff45176" target="_blank">Raspberry Pi Pico を WSL からあつかう</a>をWSL2(Ubuntu 20.04)向けにアレンジしたものになります.</div><div>
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">1.RPi Picoの開発環境</h1><div><br /></div><div>RPi PicoはRaspberry Pi財団が開発したRP2040を使用した開発ボード的なものです.</div>RP2040はCortex-M0+を2つ搭載したいわゆるデュアルコアマイコンで,いろいろな特徴があります(詳しくは<a href="https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf" target="_blank">データシート</a>で).<div><div>公式サイト上ではMicroPython SDK,C/C++ SDKが公開されており,このほかにもRustなどを用いることができるようです.</div><div>今回はベーシックにC/C++を使っていきます.</div><div><br /></div><div>参考:</div><div>Raspberry Pi財団, "Getting started with Raspberry Pi Pico", <a href="https://datasheets.raspberrypi.org/pico/getting-started-with-pico.pdf" target="_blank">https://datasheets.raspberrypi.org/pico/getting-started-with-pico.pdf</a></div><div><a href="https://qiita.com/kmak" target="_blank">@kmak</a>, "Raspberry Pi Pico を WSL からあつかう",</div><div><a href="https://qiita.com/kmak/items/a14b9e9673875ff45176" target="_blank">https://qiita.com/kmak/items/a14b9e9673875ff45176</a></div><div><br /></div><h1 style="text-align: left;">2.WSL2の下ごしらえ</h1><div><br /></div><div>今回はWSL2上にC/C++ SDKを突っ込むわけですが,SDKを入れる前に必要なものを入れます.必要なものは以下の4つ.</div><div><br /></div><div><ul style="text-align: left;"><li style="box-sizing: inherit; margin: 0px; padding: 0px;">gcc-arm-none-eabi</li><li style="box-sizing: inherit; margin: 0px; padding: 0px;">cmake (>=3.13)</li><li style="box-sizing: inherit; margin: 0px; padding: 0px;">git</li><li style="box-sizing: inherit; margin: 0px; padding: 0px;">build-essential</li></ul></div><div><br /></div><div>ubuntu 20.04であれば,これらをaptでインストールすればいいようです.ubuntu18.04ではcmakeをaptで入れると古いバージョンがインストールされるので,自前でビルドしましょう.</div><div><br /></div><h1 style="text-align: left;">3.SDKのインストール</h1><div><br /></div><div>ドキュメント通りにインストールする.</div><div><br /></div><div>
<pre><code>
# SDKとサンプルを入れるpicoフォルダを作成する
$ cd ~/
$ mkdir pico
$ cd pico
# SDKをクローン
$ git clone -b master https://github.com/raspberrypi/pico-sdk.git
$ cd pico-sdk
$ git submodule update --init
$ cd ..
</code></pre>
</div><div><div><br />上記でSDK自体は入ったのですが,環境変数PICO_SDK_PATHにSDKの場所を追加する必要があります.</div><div><br />
<pre><code>$ export PICO_SDK_PATH=/(pico-sdkを入れたフォルダの絶対パス)/pico-sdk
</code></pre>
</div><div><br /></div><div>
これでSDKの準備は完了です.
</div><div><br /></div><h1 style="text-align: left;">4.サンプルコードを入れてコンパイル</h1><div><br /></div><div>SDKの動作確認もかねてサンプルコードをクローンしてコンパイルします.
</div><div><br />
<pre><code>
$ git clone -b master https://github.com/raspberrypi/pico-examples.git
$ cd pico-examples
$ mkdir build
$ cd build
$ cmake -G "Unix Makefiles" ..
$ make
</code></pre>
<br /></div><div>これにはそこそこ時間(i5-7200Uで2hぐらい)がかかるので気長に待ちましょう.</div><div>(全部のサンプルコードをビルドしているためで,どれか一つだけであればここまで時間はかからない)</div><div>ビルドの成果物は./pico-examples/build内に生成されており,Lチカのコードであれば./pico-examples/build/blink/に入っています.この時,ボードに入れるファイルは.uf2になります.</div><div><br /></div><h1 style="text-align: left;">5.ボードに入れる</h1><div><br /></div><div>RPi PicoはBOOTSELを押したままの状態でPCとつなげるとストレージとして認識されます.ここに先ほど作成したuf2ファイルを入れると自動的にストレージとしての認識が解除され,コードの実行を開始します.</div><div>bashか何かで自動的にボードに投げ込んでもいいのですが,ここでは脳死でGUIのエクスプローラを使って入れました(もう少し考えたいところ).</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="362" src="https://www.youtube.com/embed/W_Q4bIUfo5Y" width="549" youtube-src-id="W_Q4bIUfo5Y"></iframe></div><div><br /></div><div>
<br />
<div style="text-align: center;">©2021 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div></div></div></div></div><br />Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-64760370608079871962021-01-14T23:20:00.002+09:002021-02-26T22:50:43.234+09:00PySimpleGUIとMatplotlibで高速グラフ描画<div><br /></div><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5jLaNuSJN2XzixWBKah13k7IEucGAkljRjwPajnp9ysPWqALbvzDXVn44qD382wJB9N7hJfqjbEvu0GgEZk7dANIumWyafoaapg2mAvzB124nz3bZ6tA48IuaefnKEowcUOorVVHbcDI/s640/Embedding-Fast_Render_Matplotlib-In-PySimpleGUI-2021-01-14-22-05-20.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="640" height="375" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5jLaNuSJN2XzixWBKah13k7IEucGAkljRjwPajnp9ysPWqALbvzDXVn44qD382wJB9N7hJfqjbEvu0GgEZk7dANIumWyafoaapg2mAvzB124nz3bZ6tA48IuaefnKEowcUOorVVHbcDI/w400-h375/Embedding-Fast_Render_Matplotlib-In-PySimpleGUI-2021-01-14-22-05-20.gif" width="400" /></a></div><br /><div><br /></div><br />
就活がいよいよ始まってきた中の人です.今回はPySimpleGUIに<a href="https://www.shtsno24.tokyo/2020/07/matplotlib.html" target="_blank">以前作成したMatplotlibの高速描画クラス</a>を埋め込む話です. <div><br /></div><div>今回の話のコードは<a href="https://github.com/shtsno24/pysimplegui_realtime_graph" target="_blank">こちらから</a><br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><div style="text-align: left;"><br /></div><h1 style="text-align: left;">1.PySimpleGUIについて</h1><div><br /></div>
MatplotlibとGUIを組み合わせる場合,Tkinterとの組み合わせがよくあるパターンだと思います(Matplotlibの描画の問題で,多分これ一択).ただTkinterでGUIを組む場合,部品のレイアウトで苦労することがあるかと思います.そこで登場するのがPySimpleGUIです. <div><br />
売り文句は"Python GUI For Humans - Transforms tkinter, Qt, Remi, WxPython into portable people-friendly Pythonic interfaces." </div><div>どうやらPythonで使えるGUIライブラリをラップして,"人間"でも使えるようにしたライブラリと考えればよさそうです(はてさて読めるのだろうか).</div><div><br /></div><div>参考:</div><div>PySimpleGUI公式,<a href="https://pysimplegui.readthedocs.io/en/latest/#the-call-reference-section-moved-to-here">https://pysimplegui.readthedocs.io/en/latest/#the-call-reference-section-moved-to-here</a></div><div>
<br /><h1 style="text-align: left;">2.Matplotlibを埋め込む</h1><div><br /></div><div>Tkinterもラップしてくれているので,Matplotlibも埋め込めそうって考えてたら公式cookbookに参考例がありました.どうやら動画として動かせ...ませんでした.どうやらサンプルコードが古いバージョンのようで,新しいものでは動作しないようです.</div><div><br /></div><div>で,情報を探し回っていたら<a href="https://qiita.com/bear_montblanc" target="_blank">@bear_montblanc</a>さんの<a href="https://qiita.com/bear_montblanc/items/cce4e8c58dfa236200f6" target="_blank">記事</a>を見つけ,試してみたら動作しました.とりあえず普通の使い方であれば,Matplotlibのグラフを埋め込んで動作させることが可能なようです.</div><div><br /></div><div>参考:</div><div>PySimpleGUI公式,<a href="https://pysimplegui.readthedocs.io/en/latest/cookbook/#animated-matplotlib-graph">https://pysimplegui.readthedocs.io/en/latest/cookbook/#animated-matplotlib-graph</a></div><div>Be4rR,"PySimpleGUIにMatplotlibを埋め込みたい",<a href="https://qiita.com/bear_montblanc/items/cce4e8c58dfa236200f6">https://qiita.com/bear_montblanc/items/cce4e8c58dfa236200f6</a></div><div><br /></div><h1 style="text-align: left;">3.自作クラスを埋め込む</h1><div><br /></div><div>普通の使い方であればMatplotlibのグラフを埋め込めたので,今度は<a href="https://www.shtsno24.tokyo/2020/07/matplotlib.html" target="_blank">先日作成した自作クラス</a>を埋め込みます.</div><div><br /></div><div>といっても,2.で実装したコードを一部書き換える程度であっさり動作しました.</div><div><br />
</div><div><br />
<pre><code>
if __name__ == "__main__":
try:
make_dpi_aware()
# Generate Layout
layout = [[sg.Text('Fast_Render_Matplotlib Plot')],
[sg.Canvas(key='-CANVAS-')],
[sg.Button("Add"), sg.Button("Clear")]]
# Generate Window (finalize=True is Required)
window = sg.Window('Embedding Fast_Render_Matplotlib In PySimpleGUI',
layout,
finalize=True,
element_justification='center',
font='Monospace 18')
# Generate Fig to Embedding Graph
fig = plt.figure(figsize=(5, 4))
line_ax = fig.add_subplot(2, 1, 1)
pos_ax = fig.add_subplot(2, 1, 2)
points_num = 500
scatter_view = plotter.Scatter(fig, pos_ax, len_points=points_num, show_icon=True, PySimpleGUI=True)
line_view = plotter.Line(fig, line_ax, plot_area=(points_num, 1000), len_points=points_num, PySimpleGUI=True)
# Associate Fig and Canvas.
fig_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig)
while True:
event, values = window.read()
if event in (None, "Cancel"):
break
elif event == "Add":
# Generate Random Data
rand_array_x = np.random.randint(-1000, 1000, 1250).tolist()
rand_array_y = np.random.randint(-1000, 1000, 1250).tolist()
y = np.random.randint(-1000, 1000, points_num)
# Plot Data
line_view.plot(y)
scatter_view.plot([rand_array_x, rand_array_y])
elif event == "Clear":
line_view.cla()
scatter_view.cla()
fig_agg.draw()
except Exception as e:
print(e, end="\n\n")
import traceback
traceback.print_exc()
input("Press any key to continue...")
else:
print("Done")
finally:
window.close()
</code></pre>
</div><div><br />
</div><div><br />
基本的には,ぼやけ防止の関数を走らせ,GUIのレイアウトを決定,ウィンドウを生成したのち,グラフの初期設定を行います.その後,グラフとレイアウトで設定したキャンバスを関連付けてあげることで準備は完了です.プロット類はボタンの入力をトリガとして走らせることで実行します.
</div><div><br /></div><div>参考:</div><div><a href="https://www.shtsno24.tokyo/2020/07/matplotlib.html">https://www.shtsno24.tokyo/2020/07/matplotlib.html</a></div><div><br /></div><h1 style="text-align: left;">3.実行速度</h1><div class="separator" style="clear: both; text-align: left;"><br /></div><br /><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-T7xu3zeynv7G54OxVQcxIwNLXhINVLPZAVeE3SzuH0p0qYL1_uGPac11L051MyzYe_-G99SLMDj1H5KByS2-4UBxbv37eLdXZnCOsyCJNKw-a-EYFTS06p3pgEqSHNCwGk_G_DDNQYE/s730/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2021-01-14+230639.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="378" data-original-width="730" height="208" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-T7xu3zeynv7G54OxVQcxIwNLXhINVLPZAVeE3SzuH0p0qYL1_uGPac11L051MyzYe_-G99SLMDj1H5KByS2-4UBxbv37eLdXZnCOsyCJNKw-a-EYFTS06p3pgEqSHNCwGk_G_DDNQYE/w400-h208/%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588+2021-01-14+230639.png" width="400" /></a></div><br /></div><div><br /></div><div>とりあえず50[fps]前半から60[fps]前半あたりが出ているようです.そこそこのフレームレートですね.</div><div><br /></div><h1 style="text-align: left;">4.参考</h1><div><br /></div><div>コメント欄で教えてもらった,公式のデモコード集</div><div><a href="https://github.com/PySimpleGUI/PySimpleGUI/tree/master/DemoPrograms">https://github.com/PySimpleGUI/PySimpleGUI/tree/master/DemoPrograms</a></div><div><br /></div>
<br />
<div style="text-align: center;">
©2021 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div></div>Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com2tag:blogger.com,1999:blog-1936700217346692515.post-91078050659080057942020-12-31T23:21:00.003+09:002021-01-01T09:36:31.527+09:00M5StickVでDonkeyCarのモデルは走らせられるのか(1)<div><br /></div><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ4tqUiyDo98hGIOLZqRRHr1IQrmqnfaHeaPPQR7vJiVrpjs996sBN8drf995zypBStPCoDNaVCZPTMwdsMEt3pPU9LQHIgmebcU_AO_I6XZ5VdVUfi6zpkzzuzho1rE5yn4H-U6uamdk/s3045/IMG_3005.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1713" data-original-width="3045" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ4tqUiyDo98hGIOLZqRRHr1IQrmqnfaHeaPPQR7vJiVrpjs996sBN8drf995zypBStPCoDNaVCZPTMwdsMEt3pPU9LQHIgmebcU_AO_I6XZ5VdVUfi6zpkzzuzho1rE5yn4H-U6uamdk/w400-h225/IMG_3005.HEIC" width="400" /></a></div><div><br /></div>
年末進行感が全くないまま大みそかになっていた中の人です.今年はいろいろなことが変わった一年でしたが,いかがお過ごしでしょうか.<br />
今回はM5StickVでDonkeyCarのモデルを走らせる話(1)です.個人的に気になっていたので,少しやってみようと思いました. <div><br /></div><div>今回の実装は,<a href="https://github.com/shtsno24/DonkeyCar_on_M5StickV">https://github.com/shtsno24/DonkeyCar_on_M5StickV</a>に上げてあります.</div><div><br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">
1.DonkeyCarのモデル</h1><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYsH-hnrevnAnNY7fOCvzzmHc-tdjxj16qhboNmkPw7URoYZ1gLulFM_FMcF7BJK-TwCYnk783CyGPdX9Iyl3hn3Uz_JnJNH4lOG3iAqFQN2YhGquzjvESne-4Coo65QkutFAPjgTzx5c/s898/donkey-car-graphic_orig.jpg" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="800" data-original-width="898" height="356" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYsH-hnrevnAnNY7fOCvzzmHc-tdjxj16qhboNmkPw7URoYZ1gLulFM_FMcF7BJK-TwCYnk783CyGPdX9Iyl3hn3Uz_JnJNH4lOG3iAqFQN2YhGquzjvESne-4Coo65QkutFAPjgTzx5c/w400-h356/donkey-car-graphic_orig.jpg" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><a href="https://www.donkeycar.com/">https://www.donkeycar.com/</a>より,DonkeyCarの一例</td></tr></tbody></table><div><br /></div><div>DonkeyCarはラジコンにRPiやカメラを組み合わせ,自動運転させようというプロジェクトです(車本体をさすこともあるとか).自動運転の心臓部はKerasによるDeepLearningのモデルで実装されており,使うデータの種類などでいくつかのパターンがあるようです.</div><div><a href="https://www.shtsno24.tokyo/2016/09/raspberry-pi-autonomous-car.html" target="_blank">2016年ごろにやっていたやつの結果</a>を踏まえると,個人的にはcategoricalあたりがうまく動きそうです.今回はこれをM5StickV向けに変換します.</div><div><br /></div><div style="text-align: left;">参考:</div><div style="text-align: left;">Donkey Car, "Keras - Donkey Car", <a href="http://docs.donkeycar.com/parts/keras/" target="_blank">http://docs.donkeycar.com/parts/keras/<br /></a>腹筋開発,"Donkeycar3.1.0上の機械学習モデルを調べてみた", <a href="https://fight-tsk.blogspot.com/2019/09/donkeycar310.html" target="_blank">https://fight-tsk.blogspot.com/2019/09/donkeycar310.html</a></div><div><br /></div><h1 style="text-align: left;">2.モデルの作成</h1><div><br /></div><div><a href="https://github.com/autorope/donkeycar/blob/a5c1424717ef50db00d0b2ab6c2a637971a94483/donkeycar/parts/keras.py#L422" target="_blank">本家の実装</a>は汎用性が高い実装になっていますが,今回はcategoricalのみが動けばよいので,少し手を入れてミニマムな構成に直しました.<br /><br />
<pre><code>
def Categorical(input_shape=(120, 160, 3), drop=0.2, l4_stride=1):
"""
:param img_in: input layer of network
:param drop: dropout rate
:param l4_stride: 4-th layer stride, default 1, in Categorical, l4_stride=2
"""
inputs = Input(shape=input_shape, name='img_in')
x = conv2d_relu(inputs, 24, 5, 2, 1)
x = Dropout(drop)(x)
x = conv2d_relu(x, 32, 5, 2, 2)
x = Dropout(drop)(x)
x = conv2d_relu(x, 64, 5, 2, 3)
x = Dropout(drop)(x)
x = conv2d_relu(x, 64, 3, l4_stride, 4)
x = Dropout(drop)(x)
x = conv2d_relu(x, 64, 3, 1, 5)
x = Dropout(drop)(x)
x = Flatten(name='flattened')(x)
x = Dense(100, name='dense_1')(x)
x = ReLU()(x)
x = Dropout(drop)(x)
x = Dense(50, name='dense_2')(x)
x = ReLU()(x)
x = Dropout(drop)(x)
outputs = []
_x = Dense(15, name='throttle')(x)
_x = Softmax()(_x)
outputs.append(_x)
_x = Dense(20, name='steer')(x)
_x = Softmax()(_x)
outputs.append(_x)
model = Model(inputs=inputs, outputs=outputs)
return model
def conv2d_relu(x, filters, kernel, strides, layer_num):
"""
Helper function to create a standard valid-padded convolutional layer
with square kernel and strides and unified naming convention
:param filters: channel dimension of the layer
:param kernel: creates (kernel, kernel) kernel matrix dimension
:param strides: creates (strides, strides) stride
:param layer_num: used in labelling the layer
"""
x = Conv2D(filters=filters,
kernel_size=(kernel, kernel),
strides=(strides, strides),
name='conv2d_' + str(layer_num))(x)
x = ReLU()(x)
return x
</code></pre>
<br /><br />
とりあえずこんな感じです(Conv2DのActivationとか使えばいいのですが,気にしない). Dropoutに関してはtfliteに変換する際に消えるので問題ないです.これをnncaseで変換し,PC上で実行時間のシミュレーションをしてみました(モデルの訓練はしていません).</div><div><br /></div><div>参考:autorope, donkeycar/keras.py at dev · autorope/donkeycar, <a href="https://github.com/autorope/donkeycar/blob/dev/donkeycar/parts/keras.py" target="_blank">https://github.com/autorope/donkeycar/blob/dev/donkeycar/parts/keras.py</a></div><div><br /></div><h1 style="text-align: left;">3.PC上でシミュレーション</h1><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAgUynyO6aLWcYGp4se8a_bdBblHwwl2enuroK5Wo8obPrjDwhVmcMV8UvLxnKU1e7-A8VPXW4e4dKn_42Dt2WmFDWfV01Catog6ZxR8ghaG1MSIvA0XmKgjnfz2AhDQ1LVit0I0LHhyphenhyphenA/s160/0.jpg" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="120" data-original-width="160" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAgUynyO6aLWcYGp4se8a_bdBblHwwl2enuroK5Wo8obPrjDwhVmcMV8UvLxnKU1e7-A8VPXW4e4dKn_42Dt2WmFDWfV01Catog6ZxR8ghaG1MSIvA0XmKgjnfz2AhDQ1LVit0I0LHhyphenhyphenA/w400-h300/0.jpg" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">入力画像</td></tr></tbody></table><div><br /></div><div>120x160x3のカラー画像(ランダムなピクセル値を使用)を使用し,実行時間を計測しました.<br /><br />
<pre><code>
QuantizedConv2D: 16.6666ms
QuantizedConv2D: 35.7317ms
Dequantize: 0.0421ms
Conv2D: 21.1655ms
Quantize: 0.3078ms
KPUUpload: 0.0231ms
KPUConv2D: 15.5949ms
Pad: 0.0365ms
KPUUpload: 0.0038ms
KPUConv2D: 14.1453ms
Pad: 0.026ms
Transpose: 0.06ms
Dequantize: 0.0026ms
MatMul: 1.9926ms
Pad: 0.0108ms
Quantize: 0.0232ms
KPUUpload: 0.0039ms
KPUConv2D: 0.1828ms
Pad: 0.0011ms
Dequantize: 0.0006ms
MatMul: 0.0018ms
MatMul: 0.0012ms
Total: 106.024ms
</code></pre>
<br /><br />PC上では100msで,全体としてはConv2Dの演算に時間がかかっていそうです.最初のQuantizedConv2DはKPU上で演算されていない様子なので,もう少し上手くやる方法がありそうです.意外とMatMulが高速みたいですが,実機だとどうなるかが気になります.</div><div><br /></div><h1 style="text-align: left;">4.実機実装</h1><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnk8EWPsE0Wp2GjSAfWsVjZ4yTAejLVW0zrW5S_ZO1xFGdy5Gzo0IslH23gtjRtP7lv8gU9sm0WzRCDs0dujkc0gi7swOwNWAzqyr1-JGFs9il0V9dc3jAzRSV4A9zJjlRZd9CwysbbQY/s3045/IMG_3005.HEIC" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1713" data-original-width="3045" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnk8EWPsE0Wp2GjSAfWsVjZ4yTAejLVW0zrW5S_ZO1xFGdy5Gzo0IslH23gtjRtP7lv8gU9sm0WzRCDs0dujkc0gi7swOwNWAzqyr1-JGFs9il0V9dc3jAzRSV4A9zJjlRZd9CwysbbQY/w400-h225/IMG_3005.HEIC" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">実機で動かす様子</td></tr></tbody></table><div><br /></div><div>以前に実装していたコードを使ってパパっと実装.</div><div>(2021.1.1更新:時間のところが実際はFPSだったので時間表示に修正しました.)<br /><br />
<pre><code>
KPU : fetch data from Camera
KPU : run kpu
KPU : fetch data from kpu
Time : 2.758 [s]
</code></pre>
<br /><br />
PCの結果の27倍実行に時間がかかっていることがわかりました.PCの結果やNNCaseのQAから察するに,おそらくフィルタサイズが5x5のConv2Dが部分的にしかアクセラレートされていないことが主な原因だと考えられます(1x1 or 3x3が完全な形でアクセラレートされる).</div><div><br /></div><div><h1 style="text-align: left;">5.もう少し実行速度を上げる</h1><div><br /></div><div>AIが動くことが売りのM5StickVでDonkeyCarのモデルを実行してみました.結果として約400[ms]程度の実行時間がかかることがわかりました.実行できただけである程度は成功なのですが,実用上もう少し実行速度を上げる必要がありそうです.手法としては,</div><div><br /></div><div>・5x5フィルタを複数の3x3フィルタに置き換える</div><div>・全結合の出力サイズを落とす</div><div>・SeparableConv2Dに置き換える</div><br />あたりが効果がありそうです.</div><div><br /></div><h1 style="text-align: left;">6.最後に</h1><div><br /></div><div>今年も様々な方にこのブログを見ていただきました.来年は就活&修論に追われる予定なので,おそらく更新頻度は下がるかと思いますが何卒よろしくお願いします(UnitV2とかが出るので,それに関連した記事を書く予定です).</div><div><br /></div><div>P.S. このブログを閲覧している方は,機会があったら中の人にこのブログを見たことを伝えていただけると幸いです.中の人が喜びます.</div><div>
<br />
<div style="text-align: center;">
©2020 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div></div>Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-65972445894243580502020-11-16T20:30:00.006+09:002020-11-16T20:30:52.903+09:00M5StickVのIMUで詰まった話<br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSJK8FUOmG8LJ4_aRmN5gIX9jNqWGh0kUFDH59XHp8YcoJstvWqXKjXPV0n396J5a-udUWZGJ7msI3-D9y2FMOjEWE8lLjKNkt4kZYn7TaiJ527179397oN6inHsO-E4DI0jhyphenhyphenAJBUkpk/s240/M5StickV_IMU_100_sample_0.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="135" data-original-width="240" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSJK8FUOmG8LJ4_aRmN5gIX9jNqWGh0kUFDH59XHp8YcoJstvWqXKjXPV0n396J5a-udUWZGJ7msI3-D9y2FMOjEWE8lLjKNkt4kZYn7TaiJ527179397oN6inHsO-E4DI0jhyphenhyphenAJBUkpk/w400-h225/M5StickV_IMU_100_sample_0.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">M5StickVのIMUのドリフト補正したときのグラフ.<br />画像を作ってSDに書き出せるのは非常に便利.<br /></td></tr></tbody></table><br /><div><br /></div>
研究をやり始めると,就活がおろそかになるシングルスレッド人間,中の人です.今回はM5StickVのIMUの話です.
<br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">1.M5StickVのIMUと回路について</h1><div><br /></div><div>
M5StickVは生産された時期に応じて搭載しているIMUと,メインのマイコンであるK210との接続ピン・方法が異なっています.今回は2020/03以降に生産されたモデルで,MPU6886を搭載しているものを使用していきます.</div><div><br /></div><div>参考:</div><div>SwitchScience, M5StickV--販売終了 - スイッチサイエンス, <a href="https://www.switch-science.com/catalog/5700/">https://www.switch-science.com/catalog/5700/</a></div><div><br /></div><h1 style="text-align: left;">2.MPU6886と会話する(I2C)</h1><div><br /></div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVlafYI6-ioDMk42uQvHixVfWZ_TH6cdaQLdZ_3CYisN85uNuiLNZVl4eELt7axeWazrmYtYJJx2hsWws7GEMH2lxJFW8Z5PhRTpo1Z-QQqspmC97EamaZROEKIWArKAV7LmYQ0e_HNxM/s737/M5StickV_IMU_I2C.png" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="231" data-original-width="737" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVlafYI6-ioDMk42uQvHixVfWZ_TH6cdaQLdZ_3CYisN85uNuiLNZVl4eELt7axeWazrmYtYJJx2hsWws7GEMH2lxJFW8Z5PhRTpo1Z-QQqspmC97EamaZROEKIWArKAV7LmYQ0e_HNxM/w400-h125/M5StickV_IMU_I2C.png" width="400" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">データの読出しに成功した.</td></tr></tbody></table><br /><div><br /></div><div><br /></div><div>MPU6886との通信は,SPIとI2Cの2つがあります.</div><div><br /></div><div><blockquote class="twitter-tweet"><p dir="ltr" lang="ja">新しいタイプのM5StickVのMPU6866は、GPIO25をHIGHにするとI2C、LowだとSPI接続です。こちらをご参考まで。<a href="https://t.co/LySTbKzuSO">https://t.co/LySTbKzuSO</a></p>— nnn (@nnn112358) <a href="https://twitter.com/nnn112358/status/1324323990723162112?ref_src=twsrc%5Etfw">November 5, 2020</a></blockquote> <script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script></div><div><br /></div><div>どちらを使うかを決めるためには,G25をHigh or Lowにする必要があります(nnnさん教えてくださりありがとうございます).</div><div><br /></div><div>手始めに,I2Cを使ってMPU6886との会話を試みます...</div><div><br /></div><div><blockquote class="twitter-tweet"><p dir="ltr" lang="ja">情報ありがとうございます.<br /><br />ただ,GPIO25をいじっても読めないので,多分もっと別の問題な気がしています...</p>— shts (@shtsno24) <a href="https://twitter.com/shtsno24/status/1324327167073816577?ref_src=twsrc%5Etfw">November 5, 2020</a></blockquote> <script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"></script></div><div><br /></div><div>ほかの人だと読めたのに,なぜか読めない...</div><div>I2Cのコード自体は動いていたのでIMU側の問題と考え,<a href="https://github.com/m5stack/M5-Schematic/blob/master/datasheet/MPU-6886-000193%2Bv1.1_GHIC.PDF.pdf">データシート</a>を眺めていましたが特に答えが得られなかったので,IMUにつながっているG24を操作しました.結果IMU側のアドレスをスキャンできました.</div><div>G24はIMUのアドレスを決定するピン(AD0)に接続されているのですが,G24を操作してHigh or Lowにしないと,回路的に浮いた状態になるようです(プルダウン/アップされていないみたい,SPIで読むときに,idle状態で不定にしないと値を吐き出すから?).</div><div>とりあえずnnnさんのサンプルコードを参考に,レジスタを設定したところ普通に動作しました.</div><div><br /></div><div>参考:</div><div>m5stack, M5-Schematic/MPU-6886-000193+v1.1_GHIC.PDF.pdf at master · m5stack/M5-Schematic</div><div><a href="https://github.com/m5stack/M5-Schematic/blob/master/datasheet/MPU-6886-000193%2Bv1.1_GHIC.PDF.pdf">https://github.com/m5stack/M5-Schematic/blob/master/datasheet/MPU-6886-000193%2Bv1.1_GHIC.PDF.pdf</a></div><div><br /></div><div>anoken, purin_wo_motto_mimamoru_gijutsu/006_2_imu_new_MPU6886.py at master · , <a href="https://github.com/anoken/purin_wo_motto_mimamoru_gijutsu/blob/master/03_maixpy_example/006_2_imu_new_MPU6886.py">https://github.com/anoken/purin_wo_motto_mimamoru_gijutsu/blob/master/03_maixpy_example/006_2_imu_new_MPU6886.py</a></div><div><br /></div><h1 style="text-align: left;">3.SPIで会話する</h1><div><br /></div><div>SPIは開発中...</div><div>なぜか読めないんだよね.</div><div><br /></div><div><br /></div><div><br /></div><div><br /></div><div><br />
<div style="text-align: center;">
©2020 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div>Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-19688563970479336982020-10-20T20:49:00.000+09:002020-10-20T20:49:39.566+09:00Interface10月号のNNCaseネタをやってみる(途中経過)<div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCvSiN3lS7XPlLgE0x3yIGXMHnrLgXTCBbpk3tBEahnMobRA14QntTdmewAHiJDaH4ciy9n_Db_MC35_tMY8pEvs1MMakgtgG7d3MAZJEg0KynSZ6AIHMs3oZ5kxaHTS1EQbfEqP6_LyE/s2632/IMG_2695.HEIC" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1480" data-original-width="2632" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCvSiN3lS7XPlLgE0x3yIGXMHnrLgXTCBbpk3tBEahnMobRA14QntTdmewAHiJDaH4ciy9n_Db_MC35_tMY8pEvs1MMakgtgG7d3MAZJEg0KynSZ6AIHMs3oZ5kxaHTS1EQbfEqP6_LyE/w400-h225/IMG_2695.HEIC" width="400" /></a></div></div><div><br /></div><br />
インターン地獄に巻き込まれた中の人です(これ年明けも続くのつらいな).今回は雑誌記事の検証的なネタです.<div>Interface10月号のP.55-58に"AIマイコンK210の汎用AIチップとしての可能性を探る"という記事がありまして,BodyPixを変換し実装までやるという内容でした.記事内の結果では,ファームウェアがkmodelv4に対応していないため動かなかったという結論でした.</div><div>記事を読んだ感じでは動かせる気がしたので,とりあえずやってみます(ソースコードの公開は,もう少し先になりそうです).<br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">1.モデルの変換</h1><div><br /></div><div>記事内では,<a href="https://twitter.com/PINTO03091" target="_blank">PINTOさん</a>のPINTO_model_zooにある.tfliteを使用していたので,同じようにモデルを準備します(量子化などは行わずfloatのままtfliteにする).入力サイズは320x240,出力はいじりません.</div>
<div>tfliteが生成出来たら,NNCaseを使い,kmodelへの変換を行います.NNCaseでの変換では,量子化のためのデータセット(データの分布を見たいから?)を指定する必要があるのですが,BodyPixのデータセットが見当たらなかったので,各ピクセルの値がランダムな320x240の画像を10枚生成し,データセットの代わりにしました(Imgフォルダに突っ込みました).もしかしたらCocoDatasetを使っているかもしれないですね.</div><div><br />
<pre><code>.\ncc.exe compile .\035_BodyPix_tflite\bodypix_025_320x240_weight_quant.tflite .\035_BodyPix_tflite\bodypix_025_320x240_weight_quant.kmodel -i tflite -o kmodel --dataset .\Img\ --dataset-format image --inference-type uint8 --input-mean 0 --input-std 1 --dump-ir --input-type uint8 --max-allocator-solve-secs 120 --calibrate-method l2 --dump-weights-range --weights-quantize-threshold 1024 --output-quantize-threshold 4096</code></pre>
<br />
</div><div>参考</div><div>中村仁昭,"AIマイコンK210の汎用AIチップとしての可能性を探る",Interface10月号,CQ出版,PP.55-58</div><div>PINTO,PINTO_model_zoo/035_BodyPix,<a href="https://github.com/PINTO0309/PINTO_model_zoo/tree/master/035_BodyPix" target="_blank">https://github.com/PINTO0309/PINTO_model_zoo/tree/master/035_BodyPix</a></div><div>Kaz Sato,Google Developers Japan: BodyPix の概要: ブラウザと TensorFlow.js によるリアルタイム人セグメンテーション,<a href="https://developers-jp.googleblog.com/2019/04/bodypix-tensorflowjs.html">https://developers-jp.googleblog.com/2019/04/bodypix-tensorflowjs.html</a></div><div><br /></div><h1 style="text-align: left;">2.ファームウェアの準備</h1><div>kmodelv4を使う場合,ファームウェアのバージョン違いではじかれることがあります(SipeedやM5Stackが配布しているファームが古い時がある).今はアップデートされて行けるかも).そこで,手元のLinux環境でM5StickV向けにファームウェアをビルドしました.(MaixHubのサービスで,カスタムファームウェアのビルドをやっているみたいだけど,いろいろあって手元の環境でやった).</div><div>ファームウェアのビルドは<a href="https://twitter.com/mongonta555" target="_blank">紅樹 タカオ</a>さんの<a href="https://raspberrypi.mongonta.com/howto-build-firmware-of-m5stickv/" target="_blank">記事</a>を参考にUbuntu20.04マシンで行いました.オプションで,support v4 kmodelというオプションがあるので,そこを有効化しておく必要があります(配布されているファームウェアだと,これが有効になってないかも).</div><div><br /></div><div>参考</div><div>紅樹 タカオ,"M5StickVのファームウェアビルド手順",<a href="https://raspberrypi.mongonta.com/howto-build-firmware-of-m5stickv/">https://raspberrypi.mongonta.com/howto-build-firmware-of-m5stickv/</a></div><h1 style="text-align: left;">3.MaixPyIDE</h1><div><br /></div><div>BodyPixは4つの出力があるモデルなので,KPUを使う際にkpu.set_outputs()を4つ書いておきます.kpu.forward()を実行し推論をしたのち,kpu.get_output()で目的の出力を得ます.取り出したデータをいい感じに整形すれば完成です.</div><div><br /></div><h1 style="text-align: left;">4.出力データを正しく表示したい</h1><div><br /></div><div>出力データが出たところで,4つの出力を確認していきます.まずは形状とデータサイズから.</div><div><br />
<pre><code>{"fmap": "data"=0x80330b70, "size"=20400, "index": 41, "w": 17, "h": 20, "ch": 15, "typecode": f}
{"fmap": "data"=0x803382f8, "size"=40800, "index": 41, "w": 34, "h": 20, "ch": 15, "typecode": f}
{"fmap": "data"=0x80342258, "size"=28800, "index": 41, "w": 24, "h": 20, "ch": 15, "typecode": f}
{"fmap": "data"=0x8032f8b0, "size"=1200, "index": 41, "w": 1, "h": 20, "ch": 15, "typecode": f}</code></pre>
</div><div><br /></div><div>"size"のところと"w","h","ch"の計算がを合わせることで,データ型がわかります.</div><div><br /></div><div>20400 / (17 x 20 x 15) = 4</div>40800 / (34 x 20 x 15) = 4<br />28800 / (24 x 20 x 15) = 4<br />1200 / (1 x 20 x 15) = 4<br /><br />全部一致したので,4Byte,かつ出力データからFP32と分かります.形状はw*h*chのように見えますが,実際は,ch * w * hの順番らしいです(NNCaseの方の出力がこっち:MaixPyでのKPUのプロパティが違う).</div><div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEHRSPEkiPB78FFpnqhoyEXrn5fTrzL9r5Ir56ti2TVAmymE-CeQ4l_w-Mbm6mgEW0S3r_wnxKuNTXYp1xQvYq7OQtdDm02WAh-22ZlhoGFgNPWN_yKyj1exrkFau6PS3dNz5FFcUZcgM/s621/IMG_2702.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="347" data-original-width="621" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEHRSPEkiPB78FFpnqhoyEXrn5fTrzL9r5Ir56ti2TVAmymE-CeQ4l_w-Mbm6mgEW0S3r_wnxKuNTXYp1xQvYq7OQtdDm02WAh-22ZlhoGFgNPWN_yKyj1exrkFau6PS3dNz5FFcUZcgM/w400-h225/IMG_2702.PNG" width="400" /></a></div></div><div class="separator" style="clear: both; text-align: center;">NNCaseの出力.ch,w,hの順番になっている.</div><br /><div>ここまではほぼ確定なのですが,ここからがよくわからないところで,この4つの出力モデルの解釈で,ch=24は体の部位ごとのセグメンテーション,ch=1は体とそれ以外のセグメンテーションと読めるのですが,ほかの2つがよくわかりませんでした.とりあえずch=1の奴を使ってみます.</div><div><br />
<iframe width="560" height="315" src="https://www.youtube.com/embed/YQOUNYuV2b4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><div><br /></div><div><br /></div><div>赤い部分が濃いほど,人がそこにいる確率が高いことを表しているのですが,あまりうまくいっていなさそうです.</div><div><br /></div><h1 style="text-align: left;">5.今後やりたいこと</h1><div><br /></div><div>データの解釈があっているかの確認や精度向上,高速化あたりをやっていきたいです.もしかしたらch,w,hの解釈もあっていないかもしれないですね...</div><div><br /><br /><br />
<div style="text-align: center;">
©2020 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
</div><br />Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-49190219797359962842020-09-11T12:52:00.001+09:002020-09-11T13:25:28.407+09:00Matplotlibで散布図や折れ線グラフの30fps描画を実現したい<div><br /></div><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAnlPfJpq-2soAevlc_k_hjuwPkBdmBoQJyR4p9BCoY2ijJUh7witXTp6twkvD1TH8BiVmWEv5T54kjQ0tzYqwarr3hWk_apHIBn8FJ4LsPiYzFpH2fofE6MsZQV114gzECz3SWqcZaJs/s640/Fast-Render_1250.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="516" data-original-width="640" height="404" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAnlPfJpq-2soAevlc_k_hjuwPkBdmBoQJyR4p9BCoY2ijJUh7witXTp6twkvD1TH8BiVmWEv5T54kjQ0tzYqwarr3hWk_apHIBn8FJ4LsPiYzFpH2fofE6MsZQV114gzECz3SWqcZaJs/w500-h404/Fast-Render_1250.gif" width="500" /></a></div><div><br /></div><br />
相変わらず引きこもり生活な中の人です。今回はMatplotlibで散布図や折れ線グラフを高速描画する話です。 <br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1>1.Matplotlibの描画の話</h1><div><br /></div><div>Pythonでグラフ描画を行う際によく使うのがMatplotlibです.Matlab-likeなインターフェースで扱いやすいのですが,リアルタイム描画を行おうとすると非常に遅いことがあります.</div><div>これに関してはいろいろな高速化のやり方があるのですが,この中でも手動更新のコードを自分で書くことで高速化を果たすやり方だと,データ数によっては<a href="http://oregengo.hatenablog.com/entry/2017/04/20/111932" target="_blank">100fps以上を狙うことができる</a>らしいです.</div><div><br /></div><div>参考:hukkumameo,<a href="http://oregengo.hatenablog.com/entry/2017/04/20/111932" target="_blank">【Python】matplotlibの手動で描画更新</a>,俺言語。</div><h1 style="text-align: left;">2.手動更新について</h1><div><br /></div><div>描画の更新方法はいくつかあるのですが,今回は</div><div><ol style="text-align: left;"><li>描画領域を白く塗る</li><li>データを描画する</li><li>描画領域のアップデート</li><li>画面の描画更新</li></ol></div><div>でやってみました.(1.の参考に書いてあるcase4)</div><div><br /></div><h1 style="text-align: left;">3.折れ線グラフ</h1><div><br /></div><div>折れ線グラフは<a href="http://oregengo.hatenablog.com/entry/2017/04/20/111932" target="_blank">hukkumameo</a>氏がやった通りなのですが,少しいじってクラス化しました.まずは初期化から.</div><div><br />
<pre><code>class Line:
def __init__(self, fig, ax, plot_area=(1000, 1000), len_points=100):
self.fig = fig
self.plot_area = plot_area
# axis setup
self.line_ax = ax
self.line_ax.set_xlim(0, plot_area[0])
self.line_ax.set_ylim(-plot_area[1], plot_area[1])
self.ydata = [0.0 for x in range(len_points)]
self.line, = self.line_ax.plot(self.ydata)
# show figure
self.fig.canvas.draw()
self.fig.show()
</code></pre>
</div><div><br /></div><div>高速化のために自動での軸レンジの計算を手動に変更し,初期化部分で設定しています.描画するデータに関しては,専用のリスト(FIFO)を作成し,データ更新が走るたびに一番古いデータを破棄し,新しいデータを足していくようにしました.</div><div>次は更新周りです.</div><div><br /></div><div>
<pre><code> def update_data(self, points):
# draw background with white
self.line_ax.draw_artist(self.line_ax.patch)
# plot points
self.ydata.append(points)
self.ydata.pop(0)
self.line.set_ydata(self.ydata)
self.line_ax.draw_artist(self.line)
# update this graph
self.fig.canvas.blit(self.line_ax.bbox)
def plot(self, ydata):
self.update_data(ydata)
self.fig.canvas.flush_events()
</code></pre>
</div><div><br /></div><div>自分で書いておいてなんですが,update_dataとplotの分割はあんまり意味は無さそうです...</div><div><br /></div><h1 style="text-align: left;">4.散布図</h1><div><br /></div><div>折れ線ができたら散布図もやりたいということで,実際にやってみました.描画の基本方針は折れ線グラフとは変わらないのですが,やり方が少し変わってきます.このあたりの話に関しては,<a href="https://waregawa-log.hatenablog.com/entry/2019/02/09/192939" target="_blank">差分更新によるmatplotlibのアニメーションの高速化の記事</a>によく書かれています.</div><div><br />
<pre><code>class Scatter:
def __init__(self, fig, ax, plot_area=(1000, 1000), len_points=100, show_icon=False, icon_radius=100):
self.fig = fig
self.plot_area = plot_area
self.icon_radius = icon_radius if show_icon is True else None
# axis setup
self.pos_ax = ax
self.pos_ax.set_xlim(-plot_area[0], plot_area[0])
self.pos_ax.set_ylim(-plot_area[1], plot_area[1])
self.pos_points = self.pos_ax.scatter([], [])
self.xy = [[0.0, 0.0] for x in range(len_points)]
if show_icon is True:
self.agent_icon = mpatches.RegularPolygon(xy=(0, 0), numVertices=4, radius=self.icon_radius, orientation=0.0, ec="r", fill=False)
self.pos_ax.add_patch(self.agent_icon)
# show figure
self.fig.canvas.draw()
self.fig.show()
</code></pre>
</div><div><br /></div><div>折れ線グラフと同じく,軸のレンジを決めFIFOの準備をしています.これに加え,最新のデータを示すためのポリゴン描画のコードが入っています.<a href="https://waregawa-log.hatenablog.com/entry/2019/02/09/192939" target="_blank">差分更新の記事</a>ではmpatches.Circleの例が挙げられていますが,今回はポリゴンの方を使用し,描画に関してもdraw_artistを使用します.mpatchesに関しては<a href="https://matplotlib.org/api/patches_api.html?highlight=matplotlib%20patches#module-matplotlib.patches" target="_blank">公式</a>が詳しいです.</div><div><br />
<pre><code> def update_data(self, points, orientation=0.0):
# draw background with white
self.pos_ax.draw_artist(self.pos_ax.patch)
# plot points
self.xy.append(points)
self.xy.pop(0)
self.pos_points.set_offsets(self.xy)
self.pos_ax.draw_artist(self.pos_points)
# plot the icon
if self.icon_radius is not None:
self.agent_icon.xy = points
self.agent_icon.orientation = orientation
self.pos_ax.draw_artist(self.agent_icon)
# update this graph
self.fig.canvas.blit(self.pos_ax.bbox)
def plot(self, points, orientation=0.0):
self.update_data(points, orientation)
self.fig.canvas.flush_events()
</code></pre>
</div><div><br />基本的には折れ線グラフと一緒です.こっちもupdate_dataとplotはひとまとめにした方がよかったかもしれません.</div><div><br /></div><div>参考:estshorter,<a href="https://waregawa-log.hatenablog.com/entry/2019/02/09/192939" target="_blank">差分更新によるmatplotlibのアニメーションの高速化</a>,われがわログ</div><div> matplotlib公式,<a href="https://matplotlib.org/api/patches_api.html?highlight=matplotlib%20patches#module-matplotlib.patches" target="_blank">matplotlib.patches — Matplotlib 3.3.1 documentation</a>,Matplotlib 3.3.1 documentation</div><div><br /></div><h1 style="text-align: left;">5.動かす</h1><div><br /></div><div>とりあえず,[-1000, 1000]の範囲でランダムな点の組(X,Y)を生成し,グラフに打っていくことにしました.これを5000回繰り返して,平均フレームレートを計算します.<a href="https://github.com/shtsno24/Fast_Render_Matplotlib" target="_blank">実行コードはこちらから.</a></div><div><br />
<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/13cAmpw7dU8" width="560"></iframe>
</div><div><br /></div><div>平均フレームレートは22.9[fps]で,目標の30[fps]には届きませんでした....</div><div>試しに一度に表示する点数を,折れ線グラフと散布図の両方で5000 -> 2500にしてみます.</div><div><br />
<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/_MOqzkFrpWw" width="560"></iframe>
</div><div><br /></div><div>平均フレームレートは31.0[fps]で,目標は達成したようです.一度の表示する点数を2500 -> 1250とさらに減らしてみます.</div><div><br />
<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="315" src="https://www.youtube.com/embed/95ec9DThQgs" width="560"></iframe>
</div><div><br /></div><div>平均フレームレートは52.2[fps]とそこそこ速くなりました.どうやら表示するデータ数に応じてフレームレートが変動するようです.</div><div><br /></div><h1 style="text-align: left;">6.結局どうなのよ</h1><div><br /></div><div>これは目標の30fps描画というべきかについてはいろいろ考える必要があると思いますは,とりあえず部分的には目標達成ということにしましょう.もやもやするけど.散布図のみだったり,グラフの更新を並列で走らせるとか,更新を隠蔽するとかすればもっとフレームレートは上がるはずなので,まだまだといったところでしょうか.</div><div><br /></div><h1 style="text-align: left;">7.参考</h1><div><br /></div><div>hukkumameo,<a href="http://oregengo.hatenablog.com/entry/2017/04/20/111932" target="_blank">【Python】matplotlibの手動で描画更新</a>,俺言語。</div><div><div>estshorter,<a href="https://waregawa-log.hatenablog.com/entry/2019/02/09/192939" target="_blank">差分更新によるmatplotlibのアニメーションの高速化</a>,われがわログ</div><div>matplotlib公式,<a href="https://matplotlib.org/api/patches_api.html?highlight=matplotlib%20patches#module-matplotlib.patches" target="_blank">matplotlib.patches — Matplotlib 3.3.1 documentation</a>,Matplotlib 3.3.1 documentation</div><div><br /></div></div><div><br /></div><div><br /></div>
<br />
<div style="text-align: center;">
©2020 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0tag:blogger.com,1999:blog-1936700217346692515.post-48300822630699762752020-09-10T10:04:00.007+09:002020-09-10T10:07:49.751+09:00このブログを参照するときに気を付けてほしいこと<script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<amp-auto-ads data-ad-client="ca-pub-3408307153332449" type="adsense">
</amp-auto-ads>
<br />
インターン準備が大変すぎて,おめめぐるぐる中の人です.さて,今回はブログの利用に関しての話です.弊ブログも来月で7年目に突入し,だんだんとほかのブログなどから参照されること増えてきました.
今のところ目立ったトラブルもないのですが,もしかしたら今後何か起きるかもしれないので,その前に手を打っていくのがこの記事の趣旨です.
<br />
<br />
<ins class="adsbygoogle" data-ad-client="ca-pub-3408307153332449" data-ad-format="fluid" data-ad-layout="in-article" data-ad-slot="1233107731" style="display: block; text-align: center;"></ins><script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<br />
<br /><h1 style="text-align: left;">1.このブログの趣旨</h1><div><br /></div><div>このブログは,中の人が試してみてうまくいった・うまくいかなかった事例をまとめたものです.</div><div><br /></div><h1 style="text-align: left;">2.情報の内容と免責</h1><div><br /></div><div>当然,開発環境・アップデートなどにより,このブログ内で紹介した方法も動かなくなることがあります.うまくいかない場合にはほかの方法を試してください.また,ブログ内で紹介した方法で何か起こっても(物損など)責任は負えないのでご了承ください.</div><div><br /></div><h1 style="text-align: left;">3.ほかの媒体での利用</h1><div><br /></div><div>基本的に他の媒体(ブログ・Twitter・同人誌など)での使用に関して,商用・非商用問わず,基本的にNGはないのですが,元にしたブログ記事のリンクを貼ってほしいです.許可は取らなくてもいいです.</div><div>諸事情により元記事が消えることもあるのでご了承ください.</div><div><br /></div><div><br /></div><h1 style="text-align: left;">4.その他</h1><div><br /></div><div>この記事は状況に合わせてアップデートします.そのため途中で内容が変わるかもしれません.</div><div><br /></div><div><br /></div>
<br />
<br />
<div style="text-align: center;">
©2020 shts All Right Reserved.</div>
<pre class="prettyprint lang=python"></pre>
Shtshttp://www.blogger.com/profile/11174351147968901165noreply@blogger.com0