Skip to content

Commit

Permalink
Quartus Stream Variable Converter & Backend io_stream enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
bo3z committed Jul 26, 2022
1 parent 1bbcca5 commit d600882
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 7 deletions.
11 changes: 11 additions & 0 deletions hls4ml/backends/fpga/fpga_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,13 @@ def definition_cpp(self, name_suffix='', as_reference=False):
else: # Declaration
return 'hls::stream<{type}> {name}{suffix}("{name}")'.format(type=self.type.name, name=self.name, suffix=name_suffix)

class QuartusStreamVariableDefinition(VariableDefinition):
def definition_cpp(self, name_suffix='', as_reference=False):
if as_reference: # Function parameter
return 'stream<{type}> &{name}{suffix}'.format(type=self.type.name, name=self.name, suffix=name_suffix)
else: # Declaration
return 'stream<{type}> {name}{suffix}'.format(type=self.type.name, name=self.name, suffix=name_suffix)

class StreamVariableConverter(object):
def __init__(self, type_converter, prefix, definition_cls):
self.type_converter = type_converter
Expand All @@ -280,6 +287,10 @@ class VivadoStreamVariableConverter(StreamVariableConverter):
def __init__(self, type_converter):
super().__init__(type_converter=type_converter, prefix='Vivado', definition_cls=VivadoStreamVariableDefinition)

class QuartusStreamVariableConverter(StreamVariableConverter):
def __init__(self, type_converter):
super().__init__(type_converter=type_converter, prefix='Quartus', definition_cls=QuartusStreamVariableDefinition)

#endregion

#region InplaceVariable
Expand Down
7 changes: 3 additions & 4 deletions hls4ml/backends/quartus/passes/transform_types.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@

from hls4ml.model.optimizer import GlobalOptimizerPass
from hls4ml.model.types import InplaceVariable
from hls4ml.backends.fpga.fpga_types import ACTypeConverter, QuartusArrayVariableConverter, HLSTypeConverter, QuartusInplaceVariableConverter, QuartusStructMemberVariableConverter, StaticWeightVariableConverter

from hls4ml.backends.fpga.fpga_types import ACTypeConverter, QuartusArrayVariableConverter, HLSTypeConverter, QuartusInplaceVariableConverter, QuartusStreamVariableConverter, QuartusStructMemberVariableConverter, StaticWeightVariableConverter

class TransformTypes(GlobalOptimizerPass):
def __init__(self):
self.type_converter = HLSTypeConverter(precision_converter=ACTypeConverter())
self.array_var_converter = QuartusArrayVariableConverter(type_converter=self.type_converter)
self.struct_var_converter = QuartusStructMemberVariableConverter(type_converter=self.type_converter)
self.stream_var_converter = QuartusStreamVariableConverter(type_converter=self.type_converter)
self.weight_var_converter = StaticWeightVariableConverter(type_converter=self.type_converter)
self.inplace_var_converter = QuartusInplaceVariableConverter(type_converter=self.type_converter)

Expand All @@ -18,9 +18,8 @@ def transform(self, model, node):
for out_name, var in node.variables.items():
if isinstance(var, InplaceVariable):
new_var = self.inplace_var_converter.convert(var, io_type)

if io_type == 'io_stream':
raise Exception('Streaming IO is not supported in Quartus.')
new_var = self.stream_var_converter.convert(var)
elif io_type == 'io_parallel':
if node.name in node.model.inputs:
new_var = self.struct_var_converter.convert(var, pragma='hls_register', struct_name='inputs')
Expand Down
3 changes: 3 additions & 0 deletions hls4ml/templates/quartus/firmware/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ using stream_out = ihc::stream_out<T>;

#endif

// Include nnet::array - a custom array-like struct, mainly used with io_stream
#include "nnet_utils/nnet_types.h"

//hls-fpga-machine-learning insert numbers


Expand Down
8 changes: 6 additions & 2 deletions hls4ml/templates/quartus/firmware/nnet_utils/nnet_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,24 @@
#include "ac_int.h"
#include "ac_fixed.h"
#include "math.h"
#include "nnet_helpers.h"
#else
#include "HLS/ac_int.h"
#include "HLS/ac_fixed.h"
#include "HLS/math.h"
#include "nnet_helpers.h"
#endif

#include "nnet_helpers.h"

typedef ac_fixed<16,6> table_default_t;

namespace nnet {

// Common type definitions
<<<<<<< HEAD
enum io_type {io_parallel = 0, io_stream};
=======
enum io_type {io_parallel = 0, io_serial, io_stream};
>>>>>>> ea9eb66a (Quartus Stream Variable Converter & Backend io_stream enabled)

// Default data types (??) TODO: Deprecate
typedef ac_fixed<16,4> weight_t_def;
Expand Down
44 changes: 43 additions & 1 deletion hls4ml/templates/quartus/firmware/nnet_utils/nnet_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@
#include <sstream>
#include <iostream>

#ifndef __INTELFPGA_COMPILER__
#include "stream.h"
template<typename T>
using stream = nnet::stream<T>;
template<typename T>
using stream_in = nnet::stream<T>;
template<typename T>
using stream_out = nnet::stream<T>;
#else
#include "HLS/hls.h"
#include "HLS/ac_int.h"
#include "HLS/ac_fixed.h"
template<typename T>
using stream = ihc::stream<T>;
template<typename T>
using stream_in = ihc::stream_in<T>;
template<typename T>
using stream_out = ihc::stream_out<T>;
#endif

namespace nnet {

template<class srcType, class dstType, size_t SIZE>
Expand All @@ -37,17 +57,39 @@ void convert_data(srcType *src, dstType *dst) {
dst[i] = dstType(src[i]);
}
}

template<class srcType, class dstType, size_t SIZE>
void convert_data_back(srcType *src, dstType *dst) {
for (size_t i = 0; i < SIZE; i++) {
dst[i] = static_cast<dstType>(src[i].to_double());
}
}

template<class srcType, class dstType, size_t SIZE>
void convert_data(srcType *src, stream_in<dstType> &dst) {
for (size_t i = 0; i < SIZE / dstType::size; i++) {
dstType ctype;
for (size_t j = 0; j < dstType::size; j++) {
ctype[j] = typename dstType::value_type(src[i * dstType::size + j]);
}
dst.write(ctype);
}
}

template<class srcType, class dstType, size_t SIZE>
void convert_data_back(stream_out<srcType> &src, dstType *dst) {
for (size_t i = 0; i < SIZE / srcType::size; i++) {
srcType ctype = src.read();
for (size_t j = 0; j < srcType::size; j++) {
dst[i * srcType::size + j] = dstType(ctype[j].to_double());
}
}
}

extern bool trace_enabled;
extern std::map<std::string, void *> *trace_outputs;
extern size_t trace_type_size;


constexpr int ceillog2(int x){
return (x <= 2) ? 1 : 1 + ceillog2((x+1) / 2);
}
Expand Down
42 changes: 42 additions & 0 deletions hls4ml/templates/quartus/firmware/nnet_utils/nnet_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef NNET_TYPES_H_
#define NNET_TYPES_H_

#include <assert.h>
#include <cstddef>
#include <cstdio>

namespace nnet {

// Fixed-size array
template<typename T, unsigned N>
struct array {
typedef T value_type;
static const unsigned size = N;

T data[N];

T& operator[](size_t pos) {
return data[pos];
}

const T& operator[](size_t pos) const {
return data[pos];
}

array& operator=(const array &other) {
if(&other == this)
return *this;

assert(N == other.size && "Array sizes must match.");

#pragma unroll
for (unsigned i = 0; i < N; i++) {
data[i] = other[i];
}
return *this;
}
};

}

#endif

0 comments on commit d600882

Please sign in to comment.