search
LoginSignup
0

posted at

updated at

【VItisHLS】内部信号にhls::stream< hls::axis<hoge_t , ... > >は使えない

やりたいこと

AXI4-Streamの入出力を持つやつを繋げたものをIPをラップしたIPを作りたい。

コード

sample.hpp
#ifndef SAMPLE_HPP
#define SAMPLE_HPP

#include <iostream>
#include <ap_int.h>
#include <random>
#include "hls_stream.h"
#include "ap_axi_sdata.h"

const uint32_t W_USR = 32;
typedef hls::axis< uint32_t, W_USR, 0, 0> my_axis;

void top_func(
    hls::stream<my_axis>& in_a, 
    hls::stream<my_axis>& in_b , 
    hls::stream<my_axis>& in_c , 
    hls::stream<my_axis>& out_res  
);

#endif // SAMPLE_HPP
sample.cpp
#include "sample.hpp"

// 内部IP 1
void add_st (
    hls::stream<my_axis>& in_a,
    hls::stream<my_axis>& in_b,
    hls::stream<my_axis>& out_res
){
    my_axis a, b, res;
    in_a.read(a);
    in_b.read(b);
    res.data = a.data + b.data;
    res.user = a.user;
    res.last = a.last;
    out_res.write( res );
}

// 内部IP 2
void sub_st (
    hls::stream<my_axis>& in_a,
    hls::stream<my_axis>& in_b,
    hls::stream<my_axis>& out_res
){
    my_axis a, b, res;
    in_a.read(a);
    in_b.read(b);
    res.data = a.data - b.data;
    res.user = a.user;
    res.last = a.last;
    out_res.write( res );
}

// wrapするトップモジュール
void top_func(
    hls::stream<my_axis>& in_a, 
    hls::stream<my_axis>& in_b, 
    hls::stream<my_axis>& in_c, 
    hls::stream<my_axis>& out_res
){

    #pragma HLS INTERFACE axis port=in_a
    #pragma HLS INTERFACE axis port=in_b
    #pragma HLS INTERFACE axis port=in_c
    #pragma HLS INTERFACE axis port=out_res
    #pragma HLS DATAFLOW

    hls::stream<my_axis> a_plus_b_st;

    add_st( in_a , in_b , a_plus_b_st );
    sub_st( a_plus_b_st , in_c , out_res );
}
tb_sample.cpp
#include "sample.hpp"

int main(){

    hls::stream<my_axis> in_a, in_b, in_c, out_exp_res, out_act_res;
    
    std::mt19937 engine(0);
    const uint32_t TEST_SIZE = 1024;
    const uint32_t RAND_LIM  = 10000;

    for( uint32_t i = 0 ; i < TEST_SIZE ; ++i ){

        my_axis a,b,c,res;

        a.data = engine() % RAND_LIM ;
        b.data = engine() % RAND_LIM ;
        c.data = engine() % RAND_LIM ;

        a.user = i;
        b.user = i + 1000;
        c.user = i + 2000;

        a.last = (i == TEST_SIZE - 1) ? 1 : 0;

        in_a.write(a);
        in_b.write(b);
        in_c.write(c);

        res.data = a.data + b.data - c.data;
        res.last = a.last;

        out_exp_res.write( res );
    }

    for( int i = 0 ; i < TEST_SIZE ; ++i ){
        top_func( in_a, in_b, in_c, out_act_res );
    }

    for( int i = 0 ; i < TEST_SIZE ; ++i ) {
        my_axis act_res, exp_res;
        out_act_res.read( act_res );
        out_exp_res.read( exp_res );

        if( act_res.data != exp_res.data ) {
            printf("result is not same\n");
            return 1;
        }

        if( act_res.last != exp_res.last ) {
            printf("TLAST timing is not same\n");
            printf("TEST FAILED\n");
            return 1;
        }

        if( act_res.last == 1 )
            printf("TLAST is detected at %d\n" , i );
    }

    printf("TEST PASSED\n");

    return 0;
}

エラー内容

これらを用いてIPを生成しようとするとC Simulationは通るが、C Synthsisで以下のエラーが出る。

ERROR: [HLS 214-208] The ap_axis|ap_axiu|qdma_axis|hls::axis data types must only be used for AXI-Stream ports in the interface. 'a_plus_b_st' is not an AXI-Stream and/or is not a port in the interface
ERROR: [HLS 200-1715] Encountered problem during source synthesis

エラー内容で検索すると、それっぽい質問が出た1

解決方法

外部ポートを持たないhls::streamにはhls::axisを用いない。

参考にした記事2によると、Vitis HLS 2020.2より外部ポートを持たないhls::stream<hls::axis<hoge_t, ... >>は弾かれるようになったらしい。そのため以下のようにhls::axisを用いない形に変える必要がある。

解決方法(tuserやtlastを用いない場合)
hls::stream<uint32_t> a_plus_b_st;

今回の場合はtuser, tlastを用いているため、次のようにすることで解決した。

解決方法(tuserやtlastを用いる場合)
struct internal_st{
    uint32_t       data;
    ap_uint<W_USR> user;
    bool           last;
};

hls::stream<internal_st> a_plus_b_st;

最初に出た記事の

Because B is not an external interface, you cannot define it as an axis interface. You can simply declare it as an hls::stream<int32_t> to stream data from block_1 to block_2.

を, 『内部信号にhls::streamを使うな』に勘違いして永遠にエラーを出していた(馬鹿すぎる)。
marseeさんに感謝。

  1. [HLS 214-208] The ap_axis|ap_axiu|qdma_axis|hls::axis data types must only be used for AXI-Stream ports in the interface/FPGA

  2. Vitis HLS 2020.2 で hls::stream の ap_axiu , ap_axis データタイプが AXI4-Stream ポートでしか使用できない / FPGAの部屋

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0