はじめに
Xilinx Vitis の中を調べるのその17。
INTERFACEに、m_axi を指定した時にどのようなRTLコードが生成されるかをみてみます。
INTERFACE に m_axi を指定すると
下記のように、iNTERFACE に m_axi を指定してみました
#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 m_axi port=multi_out #pragma HLS INTERFACE m_axi port=multi_in1 #pragma HLS INTERFACE m_axi port=multi_in0 *multi_out = multi_in0 * multi_in1; }
生成されたRTLコードのINTERFACEのところです。
- ap_XXX
- m_axi_gmem_YYY
- s_axilite_control_ZZZ
- multi_in0/multi_in1
あれ、multi_in0とmulti_in1 が残っている。。何故?
module multi_apuint ( ap_clk, ap_rst_n, ap_start, ap_done, ap_idle, ap_ready, m_axi_gmem_AWVALID, m_axi_gmem_AWREADY, m_axi_gmem_AWADDR, m_axi_gmem_AWID, m_axi_gmem_AWLEN, m_axi_gmem_AWSIZE, m_axi_gmem_AWBURST, m_axi_gmem_AWLOCK, m_axi_gmem_AWCACHE, m_axi_gmem_AWPROT, m_axi_gmem_AWQOS, m_axi_gmem_AWREGION, m_axi_gmem_AWUSER, m_axi_gmem_WVALID, m_axi_gmem_WREADY, m_axi_gmem_WDATA, m_axi_gmem_WSTRB, m_axi_gmem_WLAST, m_axi_gmem_WID, m_axi_gmem_WUSER, m_axi_gmem_ARVALID, m_axi_gmem_ARREADY, m_axi_gmem_ARADDR, m_axi_gmem_ARID, m_axi_gmem_ARLEN, m_axi_gmem_ARSIZE, m_axi_gmem_ARBURST, m_axi_gmem_ARLOCK, m_axi_gmem_ARCACHE, m_axi_gmem_ARPROT, m_axi_gmem_ARQOS, m_axi_gmem_ARREGION, m_axi_gmem_ARUSER, m_axi_gmem_RVALID, m_axi_gmem_RREADY, m_axi_gmem_RDATA, m_axi_gmem_RLAST, m_axi_gmem_RID, m_axi_gmem_RUSER, m_axi_gmem_RRESP, m_axi_gmem_BVALID, m_axi_gmem_BREADY, m_axi_gmem_BRESP, m_axi_gmem_BID, m_axi_gmem_BUSER, multi_in0, multi_in1, 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 ); parameter ap_ST_fsm_pp0_stage0 = 1'd1; parameter C_S_AXI_CONTROL_DATA_WIDTH = 32; parameter C_S_AXI_CONTROL_ADDR_WIDTH = 5; parameter C_S_AXI_DATA_WIDTH = 32; parameter C_M_AXI_GMEM_ID_WIDTH = 1; parameter C_M_AXI_GMEM_ADDR_WIDTH = 64; parameter C_M_AXI_GMEM_DATA_WIDTH = 32; parameter C_M_AXI_GMEM_AWUSER_WIDTH = 1; parameter C_M_AXI_GMEM_ARUSER_WIDTH = 1; parameter C_M_AXI_GMEM_WUSER_WIDTH = 1; parameter C_M_AXI_GMEM_RUSER_WIDTH = 1; parameter C_M_AXI_GMEM_BUSER_WIDTH = 1; parameter C_M_AXI_GMEM_USER_VALUE = 0; parameter C_M_AXI_GMEM_PROT_VALUE = 0; parameter C_M_AXI_GMEM_CACHE_VALUE = 3; parameter C_M_AXI_DATA_WIDTH = 32; parameter C_S_AXI_CONTROL_WSTRB_WIDTH = (32 / 8); parameter C_S_AXI_WSTRB_WIDTH = (32 / 8); parameter C_M_AXI_GMEM_WSTRB_WIDTH = (32 / 8); parameter C_M_AXI_WSTRB_WIDTH = (32 / 8); input ap_clk; input ap_rst_n; input ap_start; output ap_done; output ap_idle; output ap_ready; output m_axi_gmem_AWVALID; input m_axi_gmem_AWREADY; output [C_M_AXI_GMEM_ADDR_WIDTH - 1:0] m_axi_gmem_AWADDR; output [C_M_AXI_GMEM_ID_WIDTH - 1:0] m_axi_gmem_AWID; output [7:0] m_axi_gmem_AWLEN; output [2:0] m_axi_gmem_AWSIZE; output [1:0] m_axi_gmem_AWBURST; output [1:0] m_axi_gmem_AWLOCK; output [3:0] m_axi_gmem_AWCACHE; output [2:0] m_axi_gmem_AWPROT; output [3:0] m_axi_gmem_AWQOS; output [3:0] m_axi_gmem_AWREGION; output [C_M_AXI_GMEM_AWUSER_WIDTH - 1:0] m_axi_gmem_AWUSER; output m_axi_gmem_WVALID; input m_axi_gmem_WREADY; output [C_M_AXI_GMEM_DATA_WIDTH - 1:0] m_axi_gmem_WDATA; output [C_M_AXI_GMEM_WSTRB_WIDTH - 1:0] m_axi_gmem_WSTRB; output m_axi_gmem_WLAST; output [C_M_AXI_GMEM_ID_WIDTH - 1:0] m_axi_gmem_WID; output [C_M_AXI_GMEM_WUSER_WIDTH - 1:0] m_axi_gmem_WUSER; output m_axi_gmem_ARVALID; input m_axi_gmem_ARREADY; output [C_M_AXI_GMEM_ADDR_WIDTH - 1:0] m_axi_gmem_ARADDR; output [C_M_AXI_GMEM_ID_WIDTH - 1:0] m_axi_gmem_ARID; output [7:0] m_axi_gmem_ARLEN; output [2:0] m_axi_gmem_ARSIZE; output [1:0] m_axi_gmem_ARBURST; output [1:0] m_axi_gmem_ARLOCK; output [3:0] m_axi_gmem_ARCACHE; output [2:0] m_axi_gmem_ARPROT; output [3:0] m_axi_gmem_ARQOS; output [3:0] m_axi_gmem_ARREGION; output [C_M_AXI_GMEM_ARUSER_WIDTH - 1:0] m_axi_gmem_ARUSER; input m_axi_gmem_RVALID; output m_axi_gmem_RREADY; input [C_M_AXI_GMEM_DATA_WIDTH - 1:0] m_axi_gmem_RDATA; input m_axi_gmem_RLAST; input [C_M_AXI_GMEM_ID_WIDTH - 1:0] m_axi_gmem_RID; input [C_M_AXI_GMEM_RUSER_WIDTH - 1:0] m_axi_gmem_RUSER; input [1:0] m_axi_gmem_RRESP; input m_axi_gmem_BVALID; output m_axi_gmem_BREADY; input [1:0] m_axi_gmem_BRESP; input [C_M_AXI_GMEM_ID_WIDTH - 1:0] m_axi_gmem_BID; input [C_M_AXI_GMEM_BUSER_WIDTH - 1:0] m_axi_gmem_BUSER; input [7:0] multi_in0; input [7:0] multi_in1; 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;
どうやら、入力信号である、multi_in0 と multi_in1 を ポインタにしないといけないっぽい。multi_out は既に ポインタになっているので、OK!
#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 mode=m_axi bundle=BUS_A port=multi_in0 #pragma HLS INTERFACE mode=m_axi bundle=BUS_B port=multi_in1 #pragma HLS INTERFACE mode=m_axi bundle=BUS_C port=multi_out *multi_out = (*multi_in0) * (*multi_in1); }
multi_in0 と multi_in1 が ポインタになったので、テストベンチも下記のように修正しました。
#include <string.h> #include <ap_int.h> void multi_apuint(ap_uint<8> *multi_in0, ap_uint<8> *multi_in1, ap_uint<16> *multi_out); int main(){ using namespace std; ap_uint<8> multi_in0; ap_uint<8> multi_in1; ap_uint<16> multi_out; for (multi_in0=0, multi_in1=1; multi_in0<10; multi_in0++, multi_in1++){ multi_apuint(&multi_in0, &multi_in1, &multi_out); cout << "multi_out = " << multi_out << endl; if (multi_out != (multi_in0 * multi_in1)) return(1); } return(0); }
生成されたRTLコード
m_axi_BUS_A_XXX, m_axi_BUS_B_YYY, m_axi_BUS_C_ZZZ の部分は、axi の信号です。
- ap_AAA : 変化なし
- m_axi_BUS_A_XXX : 追加
- m_axi_BUS_A_YYY : 追加
- m_axi_BUS_A_XXX : 追加
- s__axi_control_BBB : 役割が違うっポイ
module multi_apuint ( ap_clk, ap_rst_n, ap_start, ap_done, ap_idle, ap_ready, m_axi_BUS_A_XXX, m_axi_BUS_B_YYY, m_axi_BUS_C_ZZZ, 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 );
- m_axi_BUS_A_XXX は、multi_in0 の AXI の マスターポート
- m_axi_BUS_B_YYY は、multi_in1 の AXI の マスターポート
- m_axi_BUS_C_ZZZ は、multi_out の AXI の マスターポート
になっています。
- s_axi_control_BBB は、m_axi_BUS_A_XXX (multi_in0), m_axi_BUS_B_YYY (multi_in1), m_axi_BUS_C_ZZZ (multi_out) へのアドレスを生成しています。
おわりに
今回は、INTERFACE を s_axilite から m_axi にして、生成されたRTLコードをみてみました。