LoginSignup
0
0

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-10-30

やりたいこと

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の部屋

0
0
0

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
  3. You can use dark theme
What you can do with signing up
0
0