FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

AWS EC2 F1インスタンスを使ったハードウェア開発の勉強 (11. 割り込み信号によるFPGAからホストへの通知機能)

AWS F1インスタンス HDK の勉強を続けている。 目標としては、以下の部分にAXIマスタを接続してDRAMにアクセスし、データをフェッチする。

  1. DMAでホストからデータをDDR4メモリに格納する。
  2. AXIマスタデータをフェッチする
  3. 演算し、結果を格納する。

として、例えば行列積のアクセラレータをF1インスタンス上で動作させてみたい。ここまでは上手くできたのだが、計算の完了をホストに通知する方法があまりよくない。

Configurationバスにアクセスして、計算完了フラグが立っていた場合に次の計算のためのデータを流し込む。 これでは時間がかかるので、割り込みのような機能を使用したい。

github.com

  • 今の方式では 1us に一度状態を読み込みに行く機構のため、あまり良くない。
  while (matrix_finished == 0) begin
    tb.peek(.addr(`HELLO_WORLD_REG_ADDR), .data(matrix_finished), .size(DataSize::UINT16), .intf(AxiPort::PORT_OCL));         // start read & write
    $display ("Reading 0x%x from address 0x%x", matrix_finished, `HELLO_WORLD_REG_ADDR);
    #1us;
  end

HDKの資料を見ていると、割り込み通知のための信号が用意されている。

github.com

f:id:msyksphinz:20180531000721p:plain

Interrupts

16 user interrupt source are supported. There is mapping logic that maps the user interrupts to MSI-X vectors. Mapping registers in the DMA controller map the 16 user interrupt sources to MSI-X vectors.

There are two sets of signals to generate interrupts:

  • cl_sh_apppf_irq_req[15:0] (from CL to SH)
  • sh_cl_apppf_irq_ack[15:0] (from SH to CL)

This interface uses single clock pulses for the req/ack. The CL asserts (active high) cl_sh_apppf_irq_req[x] for a single clock to assert the interrupt request to the SH. The SH will respond with a single clock pulse on sh_cl_apppf_irq_ack[x] to acknowledge the interrupt. Once the CL asserts a request on a particular bit[x], it should not assert a request for the same bit[x] until it has recieved the ack for bit[x] from the SH. The CL may assert requests on other bits[y] (y!=x).


というわけで、計算が完了すると、cl_sh_apppf_irq_req信号を使って割り込みをホストに対して通知してみる。

github.com

  • hdk/cl/examples/cl_dram_matrix/design/cl_int_matrix_calc.sv:embed:cite
...

logic [15: 0]           w_int_input;
assign w_int_input = {15'h000, matrix_calc_done};
...
lib_pipe #(.WIDTH(32), .STAGES(4)) PIPE_IN (.clk (clk),
                                            .rst_n (rst_n),
                                            .in_bus({int_trig, sh_cl_irq_ack}),
                                            .out_bus({cl_sh_irq_req, int_ack})
                                            );

計算が完了すると、matrix_calc_doneをアサートし、割り込みポートから通知する。

これにより、ホストのテストベンチに割り込みが通知されることが確認できる。

            50734000 : [cl_axi_mstr_bus  R] DATA=000001530000015200000151000001500000014f0000014e0000014d0000014c0000014b0000014a000001490000014800000147000001460000014500000144
            50738000 : [cl_axi_mstr_bus  R] DATA=000001630000016200000161000001600000015f0000015e0000015d0000015c0000015b0000015a000001590000015800000157000001560000015500000154
            50750000 : [matrix] result FIFO read     00000000000328b8
            50754000 : [cl_axi_mstr_bus AW] LEN=  0 SIZE=3 ADDR=0000000400020038
            50754000 : [cl_axi_mstr_bus  W] STB=0000000000000000 DATA=000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000328b8
Received interrupt  0
[            50772000] : Sending ack for interrupt  0
            51206000 : [axi_mstr_cfg_bus R] ADDR=00000500
            51210000 : [axi_mstr_cfg_bus R] ADDR=00000500
Reading 0x00000001 from address 0x00000500

おそらくこれは、sdk/userspace/utils/sh_dpi_tasks.c に通知が行われている。sv_int_ack() の部分に、さらに追加したい処理を記述する、ということかな。

void int_handler(uint32_t int_num)
{
// Vivado does not support svGetScopeFromName
#ifdef SV_TEST
  #ifndef VIVADO_SIM
    svScope scope;
    scope = svGetScopeFromName("tb");
    svSetScope(scope);
  #endif
#endif

  cosim_printf("Sample Received interrupt %2d", int_num);

#ifdef SV_TEST
  sv_int_ack(int_num);
#endif

}