EMUDAT/EMUIR
VDSP++やICEbearに比べて,UrJTAGがやたらと遅い件.id:suikan師からのヒントについて検討*1.
比較対象の決定
ベンチマークは,ICEbearのbfloaderに決める.叩き方の最適解はVDSP++のほうにあるのかもしれないけれど,JTAG podがハードウェア的に近い方が比較をし易い.
それと,簡便なベンチマークで,ICEbearのほうがVDSP++よりも書込み速度が速いという結果も出ている*2.
しかし,bfloader はソースコード非開示.ただ,そのアクセスライブラリである bfemu は bfemu-gdbproxy-0.03.tar.gz に含まれている.
読んでみた.
bfemu-gdbproxy-0.03/jtag/bfemu/emulation.c
EMUDAT/EMUIRのDRは32もしくは40ビット(IRは各5ビット).BSRを介して得ることができない内部レジスタのアクセスもできる.
void set_register(int regno, BFIN_REGISTER value) { scanchain_select(SCAN_EMUDAT); scanchain_shiftin(value, UPDATE); scanchain_select(SCAN_EMUIR); scanchain_shiftin(cons_regmv(regno, REG_EMUDAT), EXEC);//"<reg>=EMUDAT" scanchain_shiftin(INS_NOP, UPDATE); }
set_register に要するビット数は 106.BlackfinのBSRレジスタ長は,短めのBF531/2/3でも196だから,概ね半分.
メモリアクセスは,もうちょっと複雑で事前に行うことが増える.set_datamemory() が参考になる.フラッシュプログラマなら,レジスタの退避などは不要なので,もう少し簡単にできる可能性はある.
事前に行うことは多いが,しかしメモリコピーに入ってしまえば,圧倒的な低オーバヘッドを享受できる.
scanchain_shift_twoins(ins_r0_emudat, st, UPDATE); #ifdef DEBUG TIMEVAL t0, t1; gettime(&t0); #endif scanchain_select(SCAN_EMUDAT); switch (sizecode) { case LDST_8: while (count--) { // Every time we do 'full' shift and enter Run-Test/Idle, // the instruction loop is executed scanchain_shiftin(*buf++, EXEC); } break;
UrJTAGのようなBSR式だと任意のnバイトのへの書込みに要するビット長は,(BSRの長さ)×3n程度*3.
EMUDATの場合は (EMUDATの長さ)×n + (初期設定で要するEMUDAT/EMUIRの長さの総和).
nが十分に大きい時の両者の比は概ね20倍.そりゃ圧倒的に EMUDATのほうが速い.
以上の見積もりは,単にバイトアクセスしたときの差.フラッシュプログラマの動作を考えると,書込みのステータスチェックが欠かせない.1バイト書込み当たりでJTAGに流し込むビット長の比は,上記20倍のさらに数倍になる.
…はずなのだけれど.
少なく見積もってさえ20倍以上の速度差がつくはずの UrJTAG と ICEbear.しかし実際の計測結果は UrJTAG が 5倍程度の遅さと,予想外に善戦している.
これは,EMUDATを使ったメモリ書きの特性を考えれば,それっぽい説明はつけられる.
EMUDATを使うと,単純なメモリコピーでの速さは確保できるのだけれど,この方法では直接フラッシュメモリに書くことは考えられない.書込みステータスのチェックを行えば,必要な処理が増えてBSRを直接いじるのと大差が無くなる.
だから,VDSP++もICEbearも,JTAG経由で(RAMに)投げ込まれたデータ列をフラッシュに書き込むためのファームも転送する必要がある.ファームの転送時間は微々たるものだろうけれど,問題は実行時間.
RAM転送→フラッシュ焼きという時間は,BSRアクセスでは存在しない.そして,フラッシュ焼きという時間は,他のメモリアクセスに比べて3桁程度遅く,書込み用バッファが存在しないフラッシュの場合は,書込みするバイト数nに比例する.
ほんとか?
そんなこんなで,5倍程度の差に収まるのは何の不思議もない.
…ほんとか???