FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス <a href="https://msyksphinz.github.io/github_pages/">

AWS EC2 F1インスタンスを使ったハードウェア開発の勉強 (1. HDKのセットアップ)

f:id:msyksphinz:20180425234904p:plain

AWS EC2 F1インスタンスについて何となくわかってきたので、もう少し自分のデザインを使ったりだとか、カスタムデザインをF1に載せたりしてみたい。

F1インスタンスのハンズオンセミナーの時はSDAccelを使ったC/C++を使ったチュートリアルだったのだが、やはりまずは自分のVerilogデザインをコンパイルして、F1インスタンス上で動かせたら格好いいよね。

というわけで、SDAccelを使わないF1インスタンスの構築フローとしてAWS HDKを使ったフローを勉強してみる。

HDKはgithub上に公開されている。

github.com

このなかで、HDKのGetting Startedの章があるので、これを動かしていきたい。

github.com

HDKの使用条件

これはREADMEを読んで知ったのだが、このフローを流すためには、Vivado SDxが必要らしい。そんなのあったかな?

っていうか、個人で使っているようなフリーのVivadoではおそらく論理合成は出来なくて、ちゃんとVivado SDxを購入するか、結局はAWS EC2上のサーバで論理合成は実施しないといけないということらしい。これはちょっと面倒だなあ...

Vivado v2017.1_sdx (64-bit)
Vivado v2017.1_sdxop (64-bit)
Vivado v2017.1_sdx_AR70350 (64-bit)

というわけで、F1インスタンスを立ち上げて、フロントエンドサーバ上で作業を進めていく。

AWS HDKのダウンロードと実行

普通にスクリプトを実行していくだけだ。

$ export AWS_FPGA_REPO_DIR=/home/centos/src/project_data/aws-fpga
$ git clone https://github.com/aws/aws-fpga.git $AWS_FPGA_REPO_DIR
$ cd $AWS_FPGA_REPO_DIR
$ source hdk_setup.sh
...

Copying files to /home/centos/aws-fpga/hdk/common/verif/models/ddr4_model
Copying files to /home/centos/aws-fpga/hdk/common/verif/models/ddr4_rdimm_wrapper
patching ddr4_rank.sv file
INFO: DDR4 model build passed.
INFO: ATTENTION: Don't forget to set the CL_DIR variable for the directory of your Custom Logic.
INFO: Downloading the AR703530 patch.
INFO: Extracting the AR703530 patch.
Archive:  AR703530_SDx_patch.zip
   creating: /home/centos/aws-fpga/patches/AR703530/vivado/
   creating: /home/centos/aws-fpga/patches/AR703530/vivado/data/
 extracting: /home/centos/aws-fpga/patches/AR703530/vivado/data/version.dat
   creating: /home/centos/aws-fpga/patches/AR703530/vivado/lib/
   creating: /home/centos/aws-fpga/patches/AR703530/vivado/lib/lnx64.o/
  inflating: /home/centos/aws-fpga/patches/AR703530/vivado/lib/lnx64.o/librdi_timing.so
   creating: /home/centos/aws-fpga/patches/AR703530/vivado/patch_readme/
 extracting: /home/centos/aws-fpga/patches/AR703530/vivado/patch_readme/README_AR70350.txt
INFO: AWS HDK setup PASSED.
$ cd $HDK_DIR/cl/examples/cl_hello_world    # you can change cl_hello_world to any other example
$ export CL_DIR=$(pwd)

次に、論理合成を実行してみる。

$ vivado -mode batch        # Verify Vivado is installed.
$ cd $CL_DIR/build/scripts
$ ./aws_build_dcp_from_cl.sh

直ぐにコマンドプロンプトが戻ってきたので、何だこりゃと思ったのだが、どうもバックグラウンドで実行されているらしい。 しかも数時間かかるとのこと。こりゃ、面倒くさいな。。。

cl_hello_world の中身

cl_hello_world.sv というファイルがあるので見てみた。普通にSystemVerilogのモジュールだ。 AXIのレジスタスライスなどが定義されていたり、Hello Worldレジスタが定義されている。 こうやって制御するのか。もうちょっとかみ砕いていきたい。

  • /home/centos/aws-fpga/hdk/cl/examples/cl_hello_world/design/cl_hello_world.sv
module cl_hello_world

(
   `include "cl_ports.vh" // Fixed port definition

);

`include "cl_common_defines.vh"      // CL Defines for all examples
`include "cl_id_defines.vh"          // Defines for ID0 and ID1 (PCI ID's)
`include "cl_hello_world_defines.vh" // CL Defines for cl_hello_world
...
//-------------------------------------------------
// Hello World Register
//-------------------------------------------------
// When read it, returns the byte-flipped value.

always_ff @(posedge clk_main_a0)
   if (!rst_main_n_sync) begin                    // Reset
      hello_world_q[31:0] <= 32'h0000_0000;
   end
   else if (wready & (wr_addr == `HELLO_WORLD_REG_ADDR)) begin
      hello_world_q[31:0] <= wdata[31:0];
   end
   else begin                                // Hold Value
      hello_world_q[31:0] <= hello_world_q[31:0];
   end

assign hello_world_q_byte_swapped[31:0] = {hello_world_q[7:0],   hello_world_q[15:8],
                                           hello_world_q[23:16], hello_world_q[31:24]};

//-------------------------------------------------
// Virtual LED Register
//-------------------------------------------------
// Flop/synchronize interface signals
always_ff @(posedge clk_main_a0)
   if (!rst_main_n_sync) begin                    // Reset
      sh_cl_status_vdip_q[15:0]  <= 16'h0000;
      sh_cl_status_vdip_q2[15:0] <= 16'h0000;
      cl_sh_status_vled[15:0]    <= 16'h0000;
   end
   else begin
      sh_cl_status_vdip_q[15:0]  <= sh_cl_status_vdip[15:0];
      sh_cl_status_vdip_q2[15:0] <= sh_cl_status_vdip_q[15:0];
      cl_sh_status_vled[15:0]    <= pre_cl_sh_status_vled[15:0];
   end

// The register contains 16 read-only bits corresponding to 16 LED's.
// For this example, the virtual LED register shadows the hello_world
// register.
// The same LED values can be read from the CL to Shell interface
// by using the linux FPGA tool: $ fpga-get-virtual-led -S 0

always_ff @(posedge clk_main_a0)
   if (!rst_main_n_sync) begin                    // Reset
      vled_q[15:0] <= 16'h0000;
   end
   else begin
      vled_q[15:0] <= hello_world_q[15:0];
   end

// The Virtual LED outputs will be masked with the Virtual DIP switches.
assign pre_cl_sh_status_vled[15:0] = vled_q[15:0] & sh_cl_status_vdip_q2[15:0];