Vengineerの戯言

人生は短いけど、長いです。人生を楽しみましょう!

Xilinx Vitis の中を調べる(その13)

はじめに

Xilinx Vitis の中を調べるのその13。

その12で終わりにしようかな?と思っていましたが、C/C++コードに対する #pragma の INTERFACE に指定する ap_hs を違うものに変えたらどうなるか?をみることにしました。

ap_hs を s_axilite に変えてみた

下記のように、ap_hs を s_axilite に変えて、VitisでRTLを生成しました。C++コードのファイル名を mult_apuint_axilite.cpp にしました。

// multi_apuint.cpp
//
#include <ap_int.h>
//
void multi_apuint(ap_uint<8> multi_in0, ap_uint<8> multi_in1, ap_uint<16> *multi_out){
#pragma HLS PIPELINE
#pragma HLS INTERFACE s_axilite port=multi_out
#pragma HLS INTERFACE s_axilite port=multi_in1
#pragma HLS INTERFACE s_axilite port=multi_in0
    *multi_out = multi_in0 * multi_in1;
}

生成されたRTLは?

solution1/syn/verilog/multi_apuint.v は、下記のようになりました。

// RTL generated by Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2022.1 (64-bit)
// Version: 2022.1
// Copyright (C) Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
//
// ===========================================================

`timescale 1 ns / 1 ps

(* CORE_GENERATION_INFO="multi_apuint_multi_apuint,hls_ip_2022_1,{HLS_INPUT_TYPE=cxx,HLS_INPUT_FLOAT=0,HLS_INPUT_FIXED=0
,HLS_INPUT_PART=xc7z010i-clg225-1L,HLS_INPUT_CLOCK=10.000000,HLS_INPUT_ARCH=pipeline,HLS_SYN_CLOCK=6.170000,HLS_SYN_LAT=
0,HLS_SYN_TPT=1,HLS_SYN_MEM=0,HLS_SYN_DSP=0,HLS_SYN_FF=80,HLS_SYN_LUT=145,HLS_VERSION=2022_1}" *)

module multi_apuint (
        ap_start,
        ap_done,
        ap_idle,
        ap_ready,
        s_axi_control_AWVALID,
        s_axi_control_AWREADY,
        s_axi_control_AWADDR,
        s_axi_control_WVALID,
        s_axi_control_WREADY,
        s_axi_control_WDATA,
        s_axi_control_WSTRB,
        s_axi_control_ARVALID,
        s_axi_control_ARREADY,
        s_axi_control_ARADDR,
        s_axi_control_RVALID,
        s_axi_control_RREADY,
        s_axi_control_RDATA,
        s_axi_control_RRESP,
        s_axi_control_BVALID,
        s_axi_control_BREADY,
        s_axi_control_BRESP,
        ap_clk,
        ap_rst_n
);

parameter    C_S_AXI_CONTROL_DATA_WIDTH = 32;
parameter    C_S_AXI_CONTROL_ADDR_WIDTH = 6;
parameter    C_S_AXI_DATA_WIDTH = 32;

parameter C_S_AXI_CONTROL_WSTRB_WIDTH = (32 / 8);
parameter C_S_AXI_WSTRB_WIDTH = (32 / 8);

input   ap_start;
output   ap_done;
output   ap_idle;
output   ap_ready;
input   s_axi_control_AWVALID;
output   s_axi_control_AWREADY;
input  [C_S_AXI_CONTROL_ADDR_WIDTH - 1:0] s_axi_control_AWADDR;
input   s_axi_control_WVALID;
output   s_axi_control_WREADY;
input  [C_S_AXI_CONTROL_DATA_WIDTH - 1:0] s_axi_control_WDATA;
input  [C_S_AXI_CONTROL_WSTRB_WIDTH - 1:0] s_axi_control_WSTRB;
input   s_axi_control_ARVALID;
output   s_axi_control_ARREADY;
input  [C_S_AXI_CONTROL_ADDR_WIDTH - 1:0] s_axi_control_ARADDR;
output   s_axi_control_RVALID;
input   s_axi_control_RREADY;
output  [C_S_AXI_CONTROL_DATA_WIDTH - 1:0] s_axi_control_RDATA;
output  [1:0] s_axi_control_RRESP;
output   s_axi_control_BVALID;
input   s_axi_control_BREADY;
output  [1:0] s_axi_control_BRESP;
input   ap_clk;
input   ap_rst_n;

... 途中略

インターフェース部

ap_XXX 関連の信号は、変わらず。 s_axi_control_XXXXが追加され、multi_in0、multi_in1、multi_out は削除されました。

変わらない信号

        ap_clk
        ap_rst_n
        ap_start
        ap_done
        ap_idle
        ap_ready

追加された信号

        s_axi_control_AWVALID,
        s_axi_control_AWREADY,
        s_axi_control_AWADDR,
        s_axi_control_WVALID,
        s_axi_control_WREADY,
        s_axi_control_WDATA,
        s_axi_control_WSTRB,
        s_axi_control_ARVALID,
        s_axi_control_ARREADY,
        s_axi_control_ARADDR,
        s_axi_control_RVALID,
        s_axi_control_RREADY,
        s_axi_control_RDATA,
        s_axi_control_RRESP,
        s_axi_control_BVALID,
        s_axi_control_BREADY,
        s_axi_control_BRESP,

削除された信号

        multi_in1_ap_vld,
        multi_in0_ap_vld,
        multi_out_ap_ack,
        multi_in0,
        multi_in0_ap_ack,
        multi_in1,
        multi_in1_ap_ack,
        multi_out,
        multi_out_ap_vld

s_axi_control_XXX <=> multi_in0/multi_in1/multi_out

s_axi_control_XXX <=> multi_in0/multi_in1/multi_out の部分は、multi_apuint_control_s_axi モジュールが行っているようです。

s_axi_control_XXX 信号から

  • multi_in0 : 出力
  • multi_in1 : 出力
  • multi_out / multi_out_ap_vld : 入力

を作っています。

multi_apuint_control_s_axi #(
    .C_S_AXI_ADDR_WIDTH( C_S_AXI_CONTROL_ADDR_WIDTH ),
    .C_S_AXI_DATA_WIDTH( C_S_AXI_CONTROL_DATA_WIDTH ))
control_s_axi_U(
    .AWVALID(s_axi_control_AWVALID),
    .AWREADY(s_axi_control_AWREADY),
    .AWADDR(s_axi_control_AWADDR),
    .WVALID(s_axi_control_WVALID),
    .WREADY(s_axi_control_WREADY),
    .WDATA(s_axi_control_WDATA),
    .WSTRB(s_axi_control_WSTRB),
    .ARVALID(s_axi_control_ARVALID),
    .ARREADY(s_axi_control_ARREADY),
    .ARADDR(s_axi_control_ARADDR),
    .RVALID(s_axi_control_RVALID),
    .RREADY(s_axi_control_RREADY),
    .RDATA(s_axi_control_RDATA),
    .RRESP(s_axi_control_RRESP),
    .BVALID(s_axi_control_BVALID),
    .BREADY(s_axi_control_BREADY),
    .BRESP(s_axi_control_BRESP),
    .ACLK(ap_clk),
    .ARESET(ap_rst_n_inv),
    .ACLK_EN(1'b1),
    .multi_in0(multi_in0),
    .multi_in1(multi_in1),
    .multi_out(ret_V_fu_65_p2),
    .multi_out_ap_vld(multi_out_ap_vld)
);

multi_in0/multi_in1 への信号は、下記のコードのように、multi_apuint_mult_8ns_8ns_16_1_1 の din0/din1 に接続しています。 multi_out からの信号は、multi_apuint_mult_8ns_8ns_16_1_1 の dout に接続しています。multi_out_ap_vld 信号は、ap_start 信号が High の時、High になっています。

multi_apuint_mul_8ns_8ns_16_1_1 #(
    .ID( 1 ),
    .NUM_STAGE( 1 ),
    .din0_WIDTH( 8 ),
    .din1_WIDTH( 8 ),
    .dout_WIDTH( 16 ))
mul_8ns_8ns_16_1_1_U1(
    .din0(ret_V_fu_65_p0),
    .din1(ret_V_fu_65_p1),
    .dout(ret_V_fu_65_p2)
);

always @ (*) begin
    if ((ap_start == 1'b1)) begin
        multi_out_ap_vld = 1'b1;
    end else begin
        multi_out_ap_vld = 1'b0;
    end
end

assign ret_V_fu_65_p0 = ret_V_fu_65_p00;

assign ret_V_fu_65_p00 = multi_in1;

assign ret_V_fu_65_p1 = ret_V_fu_65_p10;

assign ret_V_fu_65_p10 = multi_in0;

multi_apuint_mul_8ns_8ns_16_1_1 モジュールは、ap_hs の時に生成されたコードと同じです。

おわりに

次回は、C/RTL Simulation にて生成されるコードをみてみます。