読者です 読者をやめる 読者になる 読者になる

FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

Vivado-HLSとAXI4-DMAの試行(3. Vivado-HLSのカスタムIPをSDKから制御する)

Vivado

AXI4-DMAを試行している。Vivado-HLSでカスタムIPを作成し、Vivado-HLSのコアをAXI4-Streamで接続し、SDKから制御できるようになりたい。

前回、VivadoにカスタムIPをインプリメントし、デザインを生成した。次にSDKを使って制御してみる。

msyksphinz.hatenablog.com

VivadoのカスタムIPから割り込みを受信する方法

まず、Zynq上に作成したデザインをもう一度振り返ってみる。

f:id:msyksphinz:20161008031432p:plain

今回、xlconcatという、信号をconcatするブロックを使っている。これでmatrix_hls_accelブロックの割り込み通知信号をProcessingSystemに接続しており、この配線を通じて割り込みを通知する。

f:id:msyksphinz:20161008031459p:plain

AXI4-DMAでの通信方法の基本

AXI4-DMAを通じてデータを転送する基本は、XAxiDma_SimpleTransferだ。

    XAxiDma_SimpleTransfer(&AxiDma, (unsigned int) matrix_c, DIM*DIM*sizeof(float),
                           XAXIDMA_DEVICE_TO_DMA);

XAXIDMA_DEVICE_TO_DMAもしくはXAXIDMA_DMA_TO_DEVICEを選択する。DEVICE_TO_DMAならばPLからPSへの転送、DMA_TO_DEVICEならばPSからPLへの転送のようだ。

データの転送の方法だが、まずはソースデータとなるmatrix_a[DIM][DIM], matrix_b[DIM][DIM]を転送し、演算を実行、演算が終了するとmatrix_c[DIM][DIM]へ回収する。

  int status;
  status = XAxiDma_SimpleTransfer(&AxiDma, (unsigned int) A, dma_size, XAXIDMA_DMA_TO_DEVICE);
  status = XAxiDma_SimpleTransfer(&AxiDma, (unsigned int) B, dma_size, XAXIDMA_DMA_TO_DEVICE);

  // 演算を実行

  status = XAxiDma_SimpleTransfer(&AxiDma, (unsigned int) res_hw, dma_size, XAXIDMA_DEVICE_TO_DMA);

とすれば良いだろう。また、演算の終了は割り込みで通知すれば良いかな?

  // Initialize the exception handler
  Xil_ExceptionInit();
  // Register the exception handler
  //print("Register the exception handler\n\r");
  Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
  //Enable the exception handler
  Xil_ExceptionEnable();
  // Connect the Adder ISR to the exception table
  xil_printf ("Connect the Adder ISR to the Exception handler table\n\r");
  result = XScuGic_Connect(&ScuGic,XPAR_FABRIC_HLS_ACCEL_1_INTERRUPT_INTR,(Xil_InterruptHandler)XMmultIsr,&MatrixAccel);
  if(result != XST_SUCCESS){
    return result;
  }
  // xil_printf ("Enable the Adder ISR\n\r");
  XScuGic_Enable(&ScuGic,XPAR_FABRIC_HLS_ACCEL_1_INTERRUPT_INTR);

XPAR_FABRIC_HLS_ACCEL_1_INTERRUPT_INTRは 割り込みポートの61番と定義した。

#define XPAR_FABRIC_HLS_ACCEL_1_INTERRUPT_INTR (61)

これはPSの割り込みポートとして定義されているポートだ。

f:id:msyksphinz:20161008032405p:plain

61番のポートに割り込みが発生すると、XMmultIsr()が呼ばれるようにする。

void XMmultIsr(void *InstancePtr){
  XHls_matrix_accel *pExample = (XHls_matrix_accel *)InstancePtr;

  xil_printf("Received\n");

  //Disable the global interrupt
  XHls_matrix_accel_InterruptGlobalDisable(pExample);
  //Disable the local interrupt
  XHls_matrix_accel_InterruptDisable(pExample,0xffffffff);

...

まだソースコードが完成していないので、ソースコードの公開は出来ないが、とりあえず割り込み通知を受信は確認できた。下記のコンソールで、"Received"の文字が受信できていることが分かる。

f:id:msyksphinz:20161008032627p:plain

ただし、回収したデータおかしい。うまく計算できていないようだ。これはもうちょっとデバッグが必要だな。