RISC-VのNVDLAがコラボしたり、NVDLAの調査も再度実施しなければならないと思ってきた。
しかしNVDLAの内部構成やインテグレーションの方法など、あまり情報が整理されていない。 というわけで、NVDLAのリポジトリのテストパタンを解析して、どうやって動いているのか見ていこう。
NVDLAには、主に以下のテストパタンが付属しており、Verilator, Vivado Simulator, VCSで動作させることができる。
verif/traces/traceplayer/sanity0
- sanity0
- sanity1
- sanity1_cvsram
- sanity2
- sanity2_cvsram
- sanity3
- sanity3_cvsram
- sdp_relu_int16
- cc_alexnet_conv5_relu5_int16_dtest_cvsram
- conv_8x8_fc_int16
- googlenet_conv2_3x3_int16
- pdp_max_pooling_int16
まずはsanityテストからチェックしようかな。
csr制御のシーケンサ
NVDLAのテストベンチは、read_reg
, write_reg
などのCSRを制御するシーケンスで構成されている。
これを実際に制御するのはNVDLAモジュールの傍にインスタンスされているcsr_master_seqというモジュールなのだが、このモジュールがそれぞれの命令をシーケンサで管理している。
コマンド名 | 番号 |
---|---|
MSEQ_IDLE | 8'h00 |
MSEQ_REG_RD | 8'h01 |
MSEQ_REG_RD_WAIT_RESP | 8'h02 |
MSEQ_REG_RD_POLL_WAIT | 8'h03 |
MSEQ_REG_RD_MISMATCH | 8'h04 |
MSEQ_REG_RD_TIMEOUT | 8'h05 |
MSEQ_REG_WR | 8'h08 |
MSEQ_REG_WR_WAIT_RESP | 8'h09 |
MSEQ_REG_WR_TIMEOUT | 8'h0a |
MSEQ_MEM_RD | 8'h10 |
MSEQ_MEM_WR | 8'h18 |
MSEQ_MEM_LD | 8'h20 |
MSEQ_MEM_DMP | 8'h28 |
MSEQ_WAIT | 8'h30 |
MSEQ_WAIT_TIMEOUT | 8'h31 |
MSEQ_BOOT_1 | 8'hfd |
MSEQ_BOOT_2 | 8'hfe |
MSEQ_DONE | 8'hff |
sanity0
レジスタアクセスに関するテスト。
3回のレジスタアクセスを起こす。
CFG_DST_SURF_0
の初期値読み込み。CFG_DST_SURF_0
に値を書き込み。CFG_DST_SURF_0
に書き込んだ値が読み込めるか。
sanity1
BDMAに関するテスト。
tb.slave_mem_wrap.dbb_mem.memory
にsurf_memの内容をコピーする。このメモリは32ビット幅で、surf_data.txtの中身をそのまま格納している。
0x80000000に格納されているデータを0x81000000にコピーしている。
CFG_LINE
を7に設定している。CFG_LINE_REPEAT
が0x7に設定されている。このパラメータは1surfaceにつき何ラインを移動するかを指定している。
最後にCFG_LAUNCH0
に書き込みして実行開始。
64bit×32回のバーストが発生している。NVDLA側からリードリクエストを発生させ、読み込んだものをそのまま書き込み。
sanity2
BDMAに関するテストでsanity1と同じだが、最後に割り込みが発生するのを待つ。最後にwaitコマンドを実行し、割り込みが発生するまで待機する。
sanity3
sample_surf.datのデータと、weight.datのデータを使って畳み込み演算を実行している。
sample_surfのデータは0x80000000-0x80001000(4KB)、0x80100000から18KBに格納されている。といっても、かなり大量にレジスタを設定しているので、もう少し調査しないといけない。
NVDLAの扱えるデータ構造
sanity3は実際に畳み込みをするテストなのだが、どのようにデータを格納して扱うのだろうか?
色々調べると、詳細な情報を以下に見つけた。
- NVDLA : In-memory data formats
In-memory data formats — NVDLA Documentation
どうやら、重みと入力データでデータタイプをいろいろ指定できるらしい。 NVDLAの精度としてはint8, int16, fp16をサポートしている。
入力データの形は、Width, Height, Channelの3次元構造を入力することができる。 これに対して、Line Stride, Surface Strideを指定することで畳み込みのサイズを指定している。