Zynq+Synthesijer入門

Pocket

先日開催された人工知能とハードウェア・ソフトウェア協調設計ワークショップで発表された杉本さんのZynq + Vivado HLSというチュートリアルがとても素晴らしい内容だったので,それにならってZynq + Synthesijerというガイドを書いてみました.RTLは,ほとんど書かなくて大丈夫です.

このガイドでは,Javaで記述したメモリをコピーするモジュールをPLに置き,それをPSから叩く,というシステムの作成を目指します.

スライドでは,コードなどが見づらいので,以下補足です.

Synthesije関連リソースの準備(p.7)

ファイル一式のダウンロードと環境変数の設定をします

% mkdir $HOME/synthesijer
% cd $HOME/synthesijer
% wget https://sourceforge.net/projects/synthesijer/files/synthesijer-2.0/synthesijer-20150315.jar
% wget https://sourceforge.net/projects/synthesijer/files/synthesijer-2.0/synthesijer_lib_20150315.zip
% wget https://sourceforge.net/projects/synthesijer/files/synthesijer-2.0/synthesijer-applications_20150315.zip
% export SYNTHESIJER=$HOME/synthesijer/synthesijer-20150315.jar
% unzip synthesijer_lib_20150315.zip
% export SYNTHESIJER_LIB=$HOME/synthesijer/synthesijer_lib_20150315
% unzip synthesijer-applications_20150315.zip
% export SYNTHESIJER_APP=$HOME/synthesijer/synthesijer-applications_20150315
% cd $HOME/synthesijer/work
% mkdir $HOME/synthesijer/work

Javaのコードを記述(p.10)

PL用のハードウェアモジュールのソースコードです.

import synthesijer.lib.axi.*;
import synthesijer.rt.*;

class AXIHP_MEMCPY{
  private final AXILiteSlave32RTL s0 = new AXILiteSlave32RTL();
  private final SimpleAXIMemIface32RTLTest m0 = new SimpleAXIMemIface32RTLTest();
  private void run(){
    int src_addr = s0.data[1];
    int dest_addr = s0.data[2];
      for(int i = 0; i < 256; i++){
        int d = m0.read_data(src_addr + (i<<2));
        m0.write_data(dest_addr + (i<<2), d);
      }
  }

  @auto
  public void main(){
    s0.data[0] = 0x00000000;
    while(s0.data[0] == 0x00000000) ; // wait for kick from PS
      run();
      s0.data[0] = 0x00000000; // to notify DONE to PS
  }
}

SynthesijerでJavaコードをコンパイル(p.11)

% java -cp $SYNTHESIJER:$SYNTHESIJER_APP/bin:. synthesijer.Main \
       --ip-exact=AXIHP_MEMCPY \
       AXIHP_MEMCPY.java \
       $SYNTHESIJER_APP/src/synthesijer/lib/axi/AXILiteSlave32RTL.java \
       $SYNTHESIJER_APP/src/synthesijer/lib/axi/SimpleAXIMemIface32RTL.java \
       $SYNTHESIJER_APP/src/synthesijer/lib/axi/SimpleAXIMemIface32RTLTest.java

IPパッケージの作成(p.12)

必要なソースコードを所定のディレクトリにコピーします

% grep src AXIHP_MEMCPY_v1_0/component.xml
<spirit:name>src/axi_lite_slave_32.vhd</spirit:name>
<spirit:name>src/dualportram.vhd</spirit:name>
<spirit:name>src/synthesijer_lib_axi_SimpleAXIMemIface32RTLTest.vhd</sprit:name>
<spirit:name>src/simple_axi_memiface_32.vhd</spirit:name>
<spirit:name>src/AXIHP_MEMCPY.vhd</sprit:name>
<spirit:name>src/axi_lite_slave_32.vhd</spirit:name>
<spirit:name>src/dualportram.vhd</spirit:name>
<spirit:name>src/synthesijer_lib_axi_SimpleAXIMemIface32RTLTest.vhd</sprit:name>
<spirit:name>src/simple_axi_memiface_32.vhd</spirit:name>
<spirit:name>src/AXIHP_MEMCPY.vhd</spirit:name>
% cp $SYNTHESIJER_APP/hdl/vhdl/axi_lite_slave_32.vhd AXIHP_MEMCPY_v1_0/src
% cp $SYNTHESIJER_LIB/vhdl/dualportram.vhd AXIHP_MEMCPY_v1_0/src
% cp synthesijer_lib_axi_SimpleAXIMemIface32RTLTest.vhd AXIHP_MEMCPY_v1_0/src
% cp $SYNTHESIJER_APP/hdl/vhdl/simple_axi_memiface_32.vhd AXIHP_MEMCPY_v1_0/src
% cp AXIHP_MEMCPY.vhd AXIHP_MEMCPY_v1_0/src/
% ls AXIHP_MEMCPY_v1_0/src
AXIHP_MEMCPY.vhd
dualportram.vhd
synthesijer_lib_axi_SimpleAXIMemIface32RTLTest.vhd
axi_lite_slave_32.vhd
simple_axi_memiface_32.vhd

ARM上のソースコードの記述(p.38)

PS用のソフトウェアのソースコードです.

#include "xil_printf.h"

int main()
{
        Xil_DCacheDisable();
        int i, mismatch = 0;
        volatile unsigned int src_data[256], dst_data[256];
        for(i = 0; i < 256; i++) src_data[i] = i;
        unsigned int *baseaddr = (unsigned int*)0x43c00000;
        xil_printf("\r\n");
        baseaddr[1] = (unsigned int)src_data;
        baseaddr[2] = (unsigned int)dst_data;
        baseaddr[0] = 0xFFFFFFFF;
        xil_printf("memcpy start, src=%08x dest=%08x\n\r", src_data, dst_data);
        while(baseaddr[0] != 0) ;
        xil_printf("memcpy done\n\r");
        for(i = 0; i < 256; i++){
                xil_printf("src_data[%d] = %d, ", i, src_data[i]);
                xil_printf("dst_data[%d] = %d\n\r", i, dst_data[i]);
                if(src_data[i] != dst_data[i]) mismatch = 1;
        }
        (mismatch==0)? xil_printf("memcpy success!\n\r") :
                       xil_printf("memcpy fail\n\r");
        return 0;
}

です.