Skip to content

Commit

Permalink
Added Cosimulation-passing HlsDenseSvd design. Added HlsLstmSvd design.
Browse files Browse the repository at this point in the history
  • Loading branch information
ribesstefano committed Sep 7, 2021
1 parent 4f3fa97 commit acac0f4
Show file tree
Hide file tree
Showing 20 changed files with 4,035 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ data/windows*
# Hardware Directories
vivado_hls.log
vitis_hls.log
hls/
hls_prj/
vivado/
vitis_include/
./token
Expand Down
9 changes: 2 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,11 @@ else()
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(HLS_INCLUDE_DIRS ${VIVADO_INCLUDE_DIRS})
endif()
find_package(OpenCv REQUIRED)
# find_package(OpenCv REQUIRED)

message(${HLS_INCLUDE_DIRS})

# Add all definitions
if (WIN32)
add_compile_definitions(IMAGE_OUTPUT_PATH="C:/Users/ste/phd/hls_projects/hls_svd/data")
else()
add_compile_definitions(IMAGE_OUTPUT_PATH="/mnt/c/Users/ste/phd/hls_projects/hls_svd/data")
endif()
# The following definitions is required for compiling half-precision numbers.
add_compile_definitions(HLS_NO_XIL_FPO_LIB)
# add_compile_definitions(USE_FLOAT)
Expand All @@ -52,7 +47,7 @@ add_compile_definitions(FIX_FRACT_WIDTH=5)

# Move executable in bin/, along side the DLLs (copied)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
file(COPY ${OpenCv_LIBS} DESTINATION ${EXECUTABLE_OUTPUT_PATH})
# file(COPY ${OpenCv_LIBS} DESTINATION ${EXECUTABLE_OUTPUT_PATH})

# NOTE: an object file becomes a library. All libraries/objects must be LINKED later!
# Tell the application where to find the other CMake config files.
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,6 @@ List of TODOs:

List of possible bugs:

* Constructing data handler storage might lead to segmentation faults. More checks needed.
* Constructing data handler storage might lead to segmentation faults.
* Having `R == 1` might trigger some asserts.
* Having `output_size == H` in HlsKernelV might break hardware runs.
132 changes: 132 additions & 0 deletions include/kernel/svd_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "svd_params.h"
#include "dma/svd_dma.h"
#include "dma/axis_lib.h"
#include "kernel/u_kernel.h"
#include "kernel/s_kernel.h"
#include "kernel/v_kernel.h"
Expand Down Expand Up @@ -67,6 +68,137 @@ void SvdKernel(const int num_active_inputs,
output_size, num_refinements_v, xus_port, v_port, y_port);
}

/**
* @brief Sets the SVD kernel inputs, i.e. streams from arrays into
* hls::streams.
*
* @param[in] num_active_inputs The number of active inputs
* @param[in] input_size The input size
* @param[in] output_size The output size
* @param[in] num_refinements The number of refinements
* @param[in] x The input array. Shape: (N, I)
* @param[in] u The u array. Shape: (R, I, G)
* @param[in] s The s array. Shape: (R, N, G)
* @param[in] v The v array. Shape: (R, H, G)
* @param x_port The x port to be used as argument to SvdKernel
* @param u_port The u port to be used as argument to SvdKernel
* @param s_port The s port to be used as argument to SvdKernel
* @param v_port The v port to be used as argument to SvdKernel
*
* @tparam params Collection of SVD configuration params.
*/
#ifdef __VITIS_HLS__
template<typename params>
void SetSvdKernelInputs(const int num_active_inputs,
const int input_size,
const int output_size,
const int num_refinements[params::N],
const typename params::ActivationD* x,
const typename params::ActivationD* u,
const typename params::ActivationD* s,
const typename params::ActivationD* v,
hls::stream<typename params::VectTuAxiPacketType>& x_port,
hls::stream<typename params::VectTuAxiPacketType>& u_port,
hls::stream<typename params::VectG_AxiPacketType>& s_port,
hls::stream<typename params::VectTvAxiPacketType>& v_port) {
typedef typename params::ActivationD ActivationType;
const int kG = params::G;
const int kTu = params::Tu;
const int kTv = params::Tv;
const int kGTv = kG * kTv;
const int kNumTilesU = input_size / kTu;
const int kNumTilesV = output_size / kTv;
auto x_axis = svd::AxiStreamPort<params::VectTuAxiWidth>(x_port);
auto u_axis = svd::AxiStreamPort<params::VectTuAxiWidth>(u_port);
auto s_axis = svd::AxiStreamPort<params::VectG_AxiWidth>(s_port);
auto v_axis = svd::AxiStreamPort<params::VectTvAxiWidth>(v_port);
int max_R = num_refinements[0];
typename params::VectTuType x_val;
typename params::VectTuType u_val;
typename params::VectG_Type s_val;
typename params::VectTvType v_val;
for (int i = i; i < params::N; ++i) {
if (num_refinements[i] > max_R) {
max_R = num_refinements[i];
}
}
for (int j = 0; j < kNumTilesU; ++j) {
for (int i = 0; i < num_active_inputs; ++i) {
for (int k = 0; k < kTu; ++k) {
x_val[k] = x[i * input_size + j * kTu + k];
}
x_axis.template PushVector<ActivationType, kTu>(x_val);
}
}
for (int i = 0; i < max_R; ++i) {
for (int j = 0; j < kNumTilesU; ++j) {
for (int k = 0; k < kG; ++k) {
for (int ii = 0; ii < kTu; ++ii) {
u_val[ii] = u[i * kNumTilesU * kTu * kG + (j * kTu + ii) * kG + k];
}
u_axis.template PushVector<ActivationType, kTu>(u_val);
}
}
}
for (int i = 0; i < max_R; ++i) {
for (int j = 0; j < num_active_inputs; ++j) {
if (i < num_refinements[j]) {
for (int k = 0; k < kG; ++k) {
s_val[k] = s[i * num_active_inputs * kG + j * kG + k];
}
s_axis.template PushVector<ActivationType, kG>(s_val);
}
}
}
for (int i = 0; i < max_R; ++i) {
for (int k = 0; k < kNumTilesV; ++k) {
for (int j = 0; j < kG; ++j) {
for (int ii = 0; ii < kTv; ++ii) {
v_val[ii] = v[i * kNumTilesV * kTv * kG + (k * kTv + ii) * kG + j];
}
v_axis.template PushVector<ActivationType, kTv>(v_val);
}
}
}
}
#endif // __VITIS_HLS__

/**
* @brief Gets the svd kernel outputs, i.e. fills in an array from
* hls::streams.
*
* @param[in] num_active_inputs The number active inputs
* @param[in] output_size The output size (H)
* @param y_port The y port to be used as argument to SvdKernel
* @param y The output array. Shape: (N, G, H)
*
* @tparam params Collection of SVD configuration params.
*/
#ifdef __VITIS_HLS__
template<typename params>
void GetSvdKernelOutputs(const int num_active_inputs, const int output_size,
hls::stream<typename params::VectGTvAxiPacketType>& y_port,
typename params::ActivationD* y) {
typedef typename params::ActivationD ActivationType;
const int kG = params::G;
const int kTv = params::Tv;
const int kGTv = kG * kTv;
const int kNumTilesV = output_size / kTv;
auto y_axis = svd::AxiStreamPort<params::VectGTvAxiWidth>(y_port);
for (int j = 0; j < kNumTilesV; ++j) {
for (int i = 0; i < num_active_inputs; ++i) {
auto y_val = y_axis.template PopVector<ActivationType, kGTv>();
for (int k = 0; k < kTv; ++k) {
for (int ii = 0; ii < kG; ++ii) {
int y_idx = i * output_size * kG + ii * output_size + j * kTv + k;
y[y_idx] = y_val[k * kG + ii];
}
}
}
}
}
#endif // __VITIS_HLS__

} // svd

#endif // end KERNEL_SVD_KERNEL_H_
5 changes: 0 additions & 5 deletions include/kernel/v_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -565,11 +565,6 @@ void KernelV(const int num_active_inputs,
// #pragma HLS ARRAY_PARTITION variable=y_buffer complete dim=2 // I'm not accessing N dimension in parallel
#pragma HLS ARRAY_PARTITION variable=y_buffer complete dim=3
#pragma HLS BIND_STORAGE variable=y_buffer type=ram_t2p impl=bram latency=1

#ifndef __SYNTHESIS__
std::cout << "[INFO] V-Kernel, FIFO depth: " << kStreamDepth_V << std::endl;
#endif

// const int R_max = params::R;
int R_max = num_refinements[0];
Get_Max_R:
Expand Down
170 changes: 170 additions & 0 deletions include/layers/dense/hls/dense_svd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#ifndef LAYERS_DENSE_HLS_DENSE_SVD_H_
#define LAYERS_DENSE_HLS_DENSE_SVD_H_

#include "svd_params.h"
#include "kernel/svd_kernel.h"

#include "ap_int.h"


namespace svd {

static const int kDenseNumGates = 1;

typedef svd::SvdParameters<NUM_INPUTS, INPUT_SIZE, HIDDEN_SIZE, NUM_ITERATIONS,
NUM_TILES_U, NUM_TILES_V, NUM_ZERO_TILES_U, NUM_ZERO_TILES_V,
kDenseNumGates, ap_fixed<FIX_WIDTH, FIX_FRACT_WIDTH>,
ap_fixed<FIX_WIDTH, FIX_FRACT_WIDTH>,
ap_fixed<FIX_WIDTH, FIX_FRACT_WIDTH> > dense_params;

#ifndef __VITIS_HLS__
#else
template <typename params>
void DenseSvdKernel(const int num_active_inputs,
const int input_size,
const int output_size,
const int num_refinements[params::N],
// const hls::vector<int, params::N> num_refinements,
hls::stream<typename params::VectTuAxiPacketType>& x_port,
hls::stream<typename params::VectTuAxiPacketType>& u_port,
hls::stream<typename params::VectG_AxiPacketType>& s_port,
hls::stream<typename params::VectTvAxiPacketType>& v_port,
hls::stream<typename params::VectGTvAxiPacketType>& bias_port,
hls::stream<typename params::VectTvAxiPacketType>& y_port) {
#pragma HLS TOP name=DenseSvdKernel
// #pragma HLS INLINE
#pragma HLS DATAFLOW
#pragma HLS STABLE variable=s_port
#pragma HLS STABLE variable=v_port
#pragma HLS STABLE variable=bias_port
static_assert(params::G == 1, "DenseSvdKernel must have params::G equal to one.");
assert(params::G == 1);
typedef typename params::ActivationD ActivationType;
typedef svd::AxiStreamFifo<params::VectGTvAxiWidth> WrapperFifoGTv;
hls::stream<typename WrapperFifoGTv::PacketType> y_fifo;
#pragma HLS STREAM variable=y_fifo depth=2
auto y_axis = svd::AxiStreamFifo<params::VectGTvAxiWidth>(y_fifo);
auto y_out_axis = svd::AxiStreamPort<params::VectGTvAxiWidth>(y_port);
auto bias_axis = svd::AxiStreamPort<params::VectGTvAxiWidth>(bias_port);
svd::SvdKernel<params, WrapperFifoGTv>(num_active_inputs, input_size,
output_size, num_refinements, x_port, u_port, s_port, v_port, y_fifo);
Apply_Bias:
for (int i = 0; i < output_size / params::Tv; ++i) {
for (int j = 0; j < num_active_inputs; ++j) {
#pragma HLS PIPELINE II=1
const int kGTv = params::G * params::Tv; // NOTE: G is actually equal to 1.
const auto y_val = y_axis.template PopVector<ActivationType, kGTv>();
const auto bias_val = bias_axis.template PopVector<ActivationType, kGTv>();
const auto y_out = y_val + bias_val;
// #pragma HLS BIND_OP variable=y_out op=add impl=dsp latency=3
y_out_axis.template PushVector<ActivationType, kGTv>(y_out);
}
}
}
#endif // end __VITIS_HLS__

/**
* @brief Sets the DenseSvd kernel inputs, i.e. streams from arrays into
* hls::streams.
*
* @param[in] num_active_inputs The number of active inputs
* @param[in] input_size The input size
* @param[in] output_size The output size
* @param[in] num_refinements The number of refinements
* @param[in] x The input array. Shape: (N, I)
* @param[in] u The u array. Shape: (R, I, G)
* @param[in] s The s array. Shape: (R, N, G)
* @param[in] v The v array. Shape: (R, H, G)
* @param[in] bias The bias array. Shape: (N, G, H)
* @param x_port The x port to be used as argument to SvdKernel
* @param u_port The u port to be used as argument to SvdKernel
* @param s_port The s port to be used as argument to SvdKernel
* @param v_port The v port to be used as argument to SvdKernel
* @param bias_port The bias port to be used as argument to
* SvdKernel
*
* @tparam params Collection of SVD configuration params.
*/
#ifdef __VITIS_HLS__
template <typename params>
void SetDenseSvdInputs(const int num_active_inputs,
const int input_size,
const int output_size,
const int num_refinements[params::N],
const typename params::ActivationD* x,
const typename params::ActivationD* u,
const typename params::ActivationD* s,
const typename params::ActivationD* v,
const typename params::ActivationD* bias,
hls::stream<typename params::VectTuAxiPacketType>& x_port,
hls::stream<typename params::VectTuAxiPacketType>& u_port,
hls::stream<typename params::VectG_AxiPacketType>& s_port,
hls::stream<typename params::VectTvAxiPacketType>& v_port,
hls::stream<typename params::VectGTvAxiPacketType>& bias_port) {
typedef typename params::ActivationD ActivationType;
const int kG = params::G; // NOTE: G is actually equal to 1.
const int kTu = params::Tu;
const int kTv = params::Tv;
const int kGTv = kG * kTv;
const int kNumTilesU = input_size / kTu;
const int kNumTilesV = output_size / kTv;
auto bias_axis = svd::AxiStreamPort<params::VectGTvAxiWidth>(bias_port);
typename params::VectGTvType bias_val;
for (int i = 0; i < kNumTilesV; ++i) {
for (int j = 0; j < num_active_inputs; ++j) {
for (int k = 0; k < kTv; ++k) {
for (int ii = 0; ii < kG; ++ii) {
int bias_idx = j * output_size * kG + ii * output_size + i * kTv + k;
bias_val[k * kG + ii] = bias[bias_idx];
}
}
bias_axis.template PushVector<ActivationType, kGTv>(bias_val);
}
}
svd::SetSvdKernelInputs<params>(num_active_inputs, input_size,
output_size, num_refinements, x, u, s, v, x_port, u_port, s_port, v_port);
}
#endif // __VITIS_HLS__

} // svd

void HlsDenseSvd(const int num_active_inputs,
const int input_size,
const int output_size,
const int num_refinements[svd::dense_params::N],
hls::stream<typename svd::dense_params::VectTuAxiPacketType>& x_port,
hls::stream<typename svd::dense_params::VectTuAxiPacketType>& u_port,
hls::stream<typename svd::dense_params::VectG_AxiPacketType>& s_port,
hls::stream<typename svd::dense_params::VectTvAxiPacketType>& v_port,
hls::stream<typename svd::dense_params::VectGTvAxiPacketType>& bias_port,
hls::stream<typename svd::dense_params::VectTvAxiPacketType>& y_port);


/**
* @brief HLS Wrapper that calls a DenseSvd accelerator.
*
* Useful in Cosimulation.
*
* @param[in] num_active_inputs The number of active inputs
* @param[in] input_size The input size
* @param[in] output_size The output size
* @param[in] num_refinements The number of refinements
* @param[in] x The input array. Shape: (N, I)
* @param[in] u The u array. Shape: (R, I, G)
* @param[in] s The s array. Shape: (R, N, G)
* @param[in] v The v array. Shape: (R, H, G)
* @param[in] bias The bias array. Shape: (N, G, H)
* @param y The y array. Shape: (N, G, H)
*/
void HlsWrapperDenseSvd(const int num_active_inputs,
const int input_size,
const int output_size,
const int num_refinements[svd::dense_params::N],
const typename svd::dense_params::ActivationD* x,
const typename svd::dense_params::ActivationD* u,
const typename svd::dense_params::ActivationD* s,
const typename svd::dense_params::ActivationD* v,
const typename svd::dense_params::ActivationD* bias,
typename svd::dense_params::ActivationD* y);

#endif // end DENSE_HLS_DENSE_SVD_H_);
Loading

0 comments on commit acac0f4

Please sign in to comment.