Skip to content

Commit dad40aa

Browse files
committed
update interface for depth multiplier, though HLS doesn't yet implement it
1 parent c7cb71f commit dad40aa

File tree

7 files changed

+38
-11
lines changed

7 files changed

+38
-11
lines changed

hls4ml/backends/fpga/passes/codegen.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
class GenerateConvIm2col(OptimizerPass):
77
'''Generates tcode for im2col step of 1D/2d convolution'''
88

9+
# Note, DepthwizeConv1D/2D also matches because it inherits from Conv1D/2D
910
def match(self, node):
1011
return (
1112
isinstance(node, (Conv1D, Conv2D, SeparableConv1D, SeparableConv2D))

hls4ml/backends/vivado/vivado_backend.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
Conv1D,
1515
Conv2D,
1616
Dense,
17+
DepthwiseConv1D,
1718
DepthwiseConv2D,
1819
Embedding,
1920
GarNet,
@@ -314,6 +315,31 @@ def init_sepconv1d(self, layer):
314315
dw_output_t = NamedType(dw_out_name, dw_out_precision)
315316
layer.set_attr('dw_output_t', dw_output_t)
316317

318+
@layer_optimizer(DepthwiseConv1D)
319+
def init_depconv1d(self, layer):
320+
if layer.model.config.is_resource_strategy(layer):
321+
layer.set_attr('strategy', 'resource')
322+
n_in, n_out = self.get_layer_mult_size(layer)
323+
self.set_closest_reuse_factor(layer, n_in, n_out)
324+
else:
325+
layer.set_attr('strategy', 'latency')
326+
327+
out_width = layer.get_output_variable().shape[0]
328+
chosen_pf = layer.model.config.get_layer_config_value(layer, 'ParallelizationFactor', 1)
329+
valid_pf = self.get_valid_conv_partition_splits(1, out_width)
330+
if chosen_pf not in valid_pf:
331+
closest_pf = self.get_closest_reuse_factor(valid_pf, chosen_pf)
332+
valid_pf_str = ','.join(map(str, valid_pf))
333+
print(
334+
f'WARNING: Invalid ParallelizationFactor={chosen_pf} in layer "{layer.name}".'
335+
f'Using ParallelizationFactor={closest_pf} instead. Valid ParallelizationFactor(s): {valid_pf_str}.'
336+
)
337+
else:
338+
closest_pf = chosen_pf
339+
layer.set_attr('n_partitions', out_width // closest_pf)
340+
341+
layer.set_attr('implementation', layer.model.config.get_conv_implementation(layer).lower())
342+
317343
@layer_optimizer(Conv2D)
318344
def init_conv2d(self, layer):
319345
if len(layer.weights['weight'].data.shape) == 2: # This can happen if we assign weights of Dense layer to 1x1 Conv2D

hls4ml/converters/keras/convolution.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def parse_conv1d_layer(keras_layer, input_names, input_shapes, data_reader):
2727
if 'filters' in keras_layer['config']:
2828
layer['n_filt'] = keras_layer['config']['filters']
2929
else:
30-
layer['n_filt'] = layer['n_chan']
30+
layer['n_filt'] = layer['n_chan'] * layer.get('depth_multiplier')
3131
layer['filt_width'] = keras_layer['config']['kernel_size'][0]
3232
layer['stride_width'] = keras_layer['config']['strides'][0]
3333
layer['padding'] = keras_layer['config']['padding']
@@ -69,7 +69,7 @@ def parse_conv2d_layer(keras_layer, input_names, input_shapes, data_reader):
6969
if 'filters' in keras_layer['config']:
7070
layer['n_filt'] = keras_layer['config']['filters']
7171
else:
72-
layer['n_filt'] = layer['n_chan']
72+
layer['n_filt'] = layer['n_chan'] * layer.get('depth_multiplier')
7373
layer['filt_height'] = keras_layer['config']['kernel_size'][0]
7474
layer['filt_width'] = keras_layer['config']['kernel_size'][1]
7575
layer['stride_height'] = keras_layer['config']['strides'][0]

hls4ml/model/layers.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ class DepthwiseConv1D(Conv1D):
489489
Attribute('out_width'),
490490
Attribute('n_chan'),
491491
Attribute('depth_multiplier', default=1),
492+
Attribute('n_filt'), # = n_chan * depth_multiplier
492493
Attribute('filt_width'),
493494
Attribute('stride_width'),
494495
Attribute('pad_left'),
@@ -501,10 +502,10 @@ class DepthwiseConv1D(Conv1D):
501502

502503
def initialize(self):
503504
if self.get_attr('data_format') == 'channels_last':
504-
shape = [self.attributes['out_width'], self.attributes['n_chan'] * self.attributes['depth_multiplier']]
505+
shape = [self.attributes['out_width'], self.attributes['n_filt']]
505506
dims = [f'OUT_HEIGHT_{self.index}', f'N_CHAN_{self.index}']
506507
else:
507-
shape = [self.attributes['n_chan'] * self.attributes['depth_multiplier'], self.attributes['out_width']]
508+
shape = [self.attributes['n_filt'], self.attributes['out_width']]
508509
dims = [f'N_CHAN_{self.index}', f'OUT_WIDTH_{self.index}']
509510
self.add_output_variable(shape, dims)
510511

@@ -513,7 +514,6 @@ def initialize(self):
513514
)
514515

515516
self.add_bias(quantizer=self.get_attr('bias_quantizer'))
516-
self.set_attr('n_filt', self.get_attr('n_chan') * self.get_attr('depth_multiplier'))
517517

518518

519519
class Conv2D(Layer):
@@ -658,6 +658,7 @@ class DepthwiseConv2D(Conv2D):
658658
Attribute('out_width'),
659659
Attribute('n_chan'),
660660
Attribute('depth_multiplier', default=1),
661+
Attribute('n_filt'), # = n_chan * depth_multiplier
661662
Attribute('filt_height'),
662663
Attribute('filt_width'),
663664
Attribute('stride_height'),
@@ -677,12 +678,12 @@ def initialize(self):
677678
shape = [
678679
self.attributes['out_height'],
679680
self.attributes['out_width'],
680-
self.attributes['n_chan'] * self.attributes['depth_multiplier'],
681+
self.attributes['n_filt'],
681682
]
682683
dims = [f'OUT_HEIGHT_{self.index}', f'OUT_WIDTH_{self.index}', f'N_CHAN_{self.index}']
683684
else:
684685
shape = [
685-
self.attributes['n_chan'] * self.attributes['depth_multiplier'],
686+
self.attributes['n_filt'],
686687
self.attributes['out_height'],
687688
self.attributes['out_width'],
688689
]
@@ -694,7 +695,6 @@ def initialize(self):
694695
)
695696

696697
self.add_bias(quantizer=self.get_attr('bias_quantizer'))
697-
self.set_attr('n_filt', self.get_attr('n_chan') * self.get_attr('depth_multiplier'))
698698

699699

700700
class Pooling1D(Layer):

hls4ml/model/optimizer/passes/seperable_to_dw_conv.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def transform(self, model, node):
7272

7373
# creating the attributes
7474
dw_attributes = {k: node.attributes[k] for k in SeperableToDepthwiseAndConv._dw_attributes if k in node.attributes}
75-
75+
dw_attributes['n_filt'] = dw_attributes['n_chan'] * dw_attributes['depth_multiplier']
7676
dw_attributes['use_bias'] = False
7777

7878
new_dw = model.make_node('DepthwiseConv' + dim, dw_name, dw_attributes, [node.inputs[0]])

hls4ml/templates/vivado/nnet_utils/nnet_sepconv1d_latency.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace nnet {
1010
template <class data_T, class res_T, typename CONFIG_T>
1111
void depthwise_conv_1d_latency_cl(data_T data[CONFIG_T::in_width * CONFIG_T::n_chan],
1212
res_T res[CONFIG_T::out_width * CONFIG_T::n_filt],
13-
typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_chan],
13+
typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_filt],
1414
typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) {
1515

1616
constexpr unsigned mult_n_in = CONFIG_T::filt_width * CONFIG_T::n_chan;

hls4ml/templates/vivado/nnet_utils/nnet_sepconv2d_latency.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ template <class data_T, class res_T, typename CONFIG_T>
1111
void depthwise_conv_2d_latency_cl(
1212
data_T data[CONFIG_T::in_height * CONFIG_T::in_width * CONFIG_T::n_chan],
1313
res_T res[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt],
14-
typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan],
14+
typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_filt],
1515
typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) {
1616

1717
constexpr unsigned mult_n_in = CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan;

0 commit comments

Comments
 (0)