Skip to content

Commit

Permalink
generalize for Conv2DBatchnorm and Pynq
Browse files Browse the repository at this point in the history
  • Loading branch information
jmduarte committed Apr 24, 2021
1 parent a6cf3c0 commit 6269e4e
Showing 1 changed file with 33 additions and 18 deletions.
51 changes: 33 additions & 18 deletions hls4ml/model/optimizer/passes/conv_single_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import re

from hls4ml.model.optimizer import OptimizerPass
from hls4ml.model.hls_model import Conv1D, Conv2D, register_layer
from hls4ml.model.hls_model import Conv1D, Conv2D, Conv2DBatchnorm, register_layer
from hls4ml.templates import templates

class SingleOutputConv1D(Conv1D):
Expand All @@ -17,6 +17,12 @@ class SingleOutputConv2D(Conv2D):
# Nothing to do, will pick up function and config from class name
pass

class SingleOutputConv2DBatchnorm(Conv2DBatchnorm):
''' Optimized Conv2DBatchnorm implementation for kernel_size = input_size resulting in single output pixel. '''

# Nothing to do, will pick up function and config from class name
pass

single_out_conv1d_function_template = 'nnet::single_output_conv_1d_{data_format}<{input_t}, {output_t}, {config}>({input}, {output}, {w}, {b});'
single_out_conv2d_function_template = 'nnet::single_output_conv_2d_{data_format}<{input_t}, {output_t}, {config}>({input}, {output}, {w}, {b});'

Expand All @@ -26,32 +32,41 @@ class SingleOutputConv2D(Conv2D):
# Register the layer types to the layer map
register_layer('SingleOutputConv1D', SingleOutputConv1D)
register_layer('SingleOutputConv2D', SingleOutputConv2D)
register_layer('SingleOutputConv2DBatchnorm', SingleOutputConv2DBatchnorm)

# Register the templates for config and function
for backend in ['Vivado', 'Pynq']:
templates.get_backend(backend).register_templates(
'SingleOutputConv1D',
single_out_conv1d_function_template,
templates.get_backend(backend).get_config_template('Conv1D'),
single_out_conv1d_include_list
)

templates.get_backend(backend).register_templates(
'SingleOutputConv2D',
single_out_conv2d_function_template,
templates.get_backend(backend).get_config_template('Conv2D'),
single_out_conv2d_include_list
)

# Register the templates for config and function
templates.get_backend('Vivado').register_templates(
'SingleOutputConv1D',
single_out_conv1d_function_template,
templates.get_backend('Vivado').get_config_template('Conv1D'),
single_out_conv1d_include_list
)

templates.get_backend('Vivado').register_templates(
'SingleOutputConv2D',
single_out_conv2d_function_template,
templates.get_backend('Vivado').get_config_template('Conv2D'),
single_out_conv2d_include_list
)
templates.get_backend(backend).register_templates(
'SingleOutputConv2DBatchnorm',
single_out_conv2d_function_template,
templates.get_backend(backend).get_config_template('Conv2DBatchnorm'),
single_out_conv2d_include_list
)

class OptimizeSingleOutConv(OptimizerPass):
def match(self, node):
return node.__class__.__name__ in ['Conv1D', 'Conv2D'] and \
return node.__class__.__name__ in ['Conv1D', 'Conv2D', 'Conv2DBatchnorm'] and \
node.get_attr('filt_height', 1) == node.get_attr('in_height', 1) and \
node.get_attr('filt_width') == node.get_attr('in_width') and \
node.get_attr('out_height', 1) == 1 and node.get_attr('out_width') == 1

def transform(self, model, node):
dim = node.__class__.__name__[-2:] # '1D' or '2D'
pw_node = model.make_node('SingleOutputConv' + dim, node.name, node.attributes.copy(), node.inputs.copy())
class_name = 'SingleOutput' + node.__class__.__name__
pw_node = model.make_node(class_name, node.name, node.attributes.copy(), node.inputs.copy())
model.replace_node(node, pw_node)

return True

0 comments on commit 6269e4e

Please sign in to comment.