Класс Vivado HLS с членом типа hls :: stream <int>& приводит к ошибке: «Константа» имеет несинтезируемый тип ... » - PullRequest
0 голосов
/ 06 декабря 2018

Я пытаюсь выяснить, возможно ли создать экземпляр класса в vivado_hls, который имеет ссылочные члены hls :: stream <>, чтобы я мог напрямую читать / записывать поток без необходимости передавать поток в качестве аргумента поцепочка вызовов.

ПРИМЕЧАНИЕ. Это в vivado_hls 2018.2, а модулем верхнего уровня для этого проекта является "ModuleX". Рассмотрим упрощенный сценарий ниже:

#include <hls_stream.h>
#include <ap_int.h>

using hls_int = ap_uint<32>;

class X
{
  private:
    hls::stream<hls_int> &s1;
    hls::stream<hls_int> &s2;

  public:
    X(hls::stream<hls_int> &_s1, hls::stream<hls_int> &_s2) :
        s1(_s1), s2(_s2)
    {}

    void Run()
    {
        hls_int s = s2.read();
        hls_int out = s * 2;
        s1.write(out);
    }
};

void ModuleX(hls::stream<hls_int> &s1, hls::stream<hls_int> &s2)
{
    #pragma HLS INTERFACE ap_ctrl_none PORT=return
    #pragma HLS STREAM VARIABLE=s1 DEPTH=1
    #pragma HLS STREAM VARIABLE=s2 DEPTH=1

    static X x {s1, s2};

    x.Run();
}

При таком подходе я получаюследующая ошибка: ERROR: [SYNCHK 200-11] ClassWithStreamRefs.cpp:18: Constant 'x.s2.V.V' has an unsynthesizable type 'i32P*' (possible cause(s): pointer to pointer or global pointer).

Я понимаю, что скрытый компилятор, вероятно, хранит ссылку как указатель на поток, но это должно быть ошибкой с инструментами для этого сценария до сих поркак я считаю, поскольку он блокирует, то, что я вижу как действительный HLS.

Надеюсь, есть другой способ реализовать то, что я ищу (ссылки, а не значения хранятся в классе).

Что-то еще, что я попробовал, работало ниже.Тем не менее, это крайне нежелательно, потому что подход добавляет 2 тактовых цикла задержки (по 1 на входе и выходе - без веской причины).

#include <hls_stream.h>
#include <ap_int.h>

using hls_int = ap_uint<32>;

class X
{
  public:
    hls::stream<hls_int> s1;
    hls::stream<hls_int> s2;
    X()
    {
        #pragma HLS STREAM VARIABLE=s1 DEPTH=1
        #pragma HLS STREAM VARIABLE=s2 DEPTH=1
    }

    void Run()
    {
        hls_int s = s2.read();
        hls_int out = s * 2;
        s1.write(out);
    }
};

void ModuleX(hls::stream<hls_int> &s1, hls::stream<hls_int> &s2)
{
    #pragma HLS INTERFACE ap_ctrl_none PORT=return
    #pragma HLS INLINE
    static X x;

    x.s2.write(s2.read());
    x.Run();
    s1.write(x.s1.read());
}

Вот пример tcl-скрипта (хотя он в основном просто генерируетсяvivado_hls)

open_project ClassWithStreamRef
set_top ModuleX
add_files ClassWithStreamRefs.cpp -cflags "-std=c++11"
open_solution "solution1"
set_part {xczu19eg-ffvc1760-2-i} -tool vivado
create_clock -period 10 -name default
csynth_design

1 Ответ

0 голосов
/ 09 декабря 2018

Я не уверен насчет основного механизма, но удаление квалификатора static позволяет Vivado HLS 2018.2 синтезировать пример.Это, однако, создает новый экземпляр X при каждом вызове функции top, поэтому ее поля не сохраняются.В приведенном ниже примере это решается путем добавления другой статической переменной в верхнюю функцию для сохранения и передачи ее по ссылке на конструктор X.

#include <hls_stream.h>
#include <ap_int.h>

using hls_int = ap_uint<32>;

struct State
{
    hls_int counter;
};

class X
{
  private:
    hls::stream<hls_int> &s1;
    hls::stream<hls_int> &s2;
    State& state;

  public:
    X(hls::stream<hls_int> &_s1, hls::stream<hls_int> &_s2, State& _state) :
        s1(_s1), s2(_s2), state(_state)
    {}

    void Run()
    {
        hls_int s = s2.read();
        s1.write(s + state.counter++);
    }
};

void ModuleX(hls::stream<hls_int> &s1, hls::stream<hls_int> &s2)
{
    #pragma HLS INTERFACE ap_ctrl_none PORT=return
    #pragma HLS STREAM VARIABLE=s1 DEPTH=1
    #pragma HLS STREAM VARIABLE=s2 DEPTH=1

    static State state {0};
    X x {s1, s2, state};

    x.Run();
}
...