Skip to content

Commit 1c8c9ed

Browse files
committed
starting towards being able to split seperable
1 parent e3d5d49 commit 1c8c9ed

File tree

4 files changed

+62
-32
lines changed

4 files changed

+62
-32
lines changed

hls4ml/backends/fpga/fpga_backend.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,16 @@ def __init__(self, name):
7979
attrs.append(ConfigurableAttribute('reuse_factor', default=1))
8080
self.attribute_map[layer] = attrs
8181

82+
# seperable is kind of special because it is effectively two layers that will be split
83+
for layer in (SeparableConv1D, SeparableConv2D):
84+
attrs = self.attribute_map.get(layer, [])
85+
attrs.append(TypeAttribute('depthwise_accum'))
86+
attrs.append(TypeAttribute('pointwise_accum'))
87+
attrs.append(TypeAttribute('depthwise_result'))
88+
attrs.append(ConfigurableAttribute('depthwise_reuse_factor', default=1))
89+
attrs.append(ConfigurableAttribute('pointwise_reuse_factor', default=1))
90+
self.attribute_map[layer] = attrs
91+
8292
act_attrs = self.attribute_map.get(Activation, [])
8393
act_attrs.append(ConfigurableAttribute('table_size', default=1024))
8494
act_attrs.append(TypeAttribute('table', default=FixedPrecisionType(18, 8)))

hls4ml/backends/vivado/vivado_backend.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,6 @@ def _register_layer_attributes(self):
7676
attrs.append(ChoiceAttribute('conv_implementation', choices=['LineBuffer', 'Encoded'], default='LineBuffer'))
7777
self.attribute_map[layer] = attrs
7878

79-
sep_conv_layers = [SeparableConv1D, SeparableConv2D]
80-
for layer in sep_conv_layers:
81-
attrs = self.attribute_map.get(layer, [])
82-
attrs.append(TypeAttribute('dw_output', default=FixedPrecisionType(18, 8)))
83-
self.attribute_map[layer] = attrs
84-
8579
def _register_flows(self):
8680
initializers = self._get_layer_initializers()
8781
init_flow = register_flow('init_layers', initializers, requires=['optimize'], backend=self.name)

hls4ml/model/graph.py

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ def get_layer_config(self, layer):
100100

101101
return layer_config
102102

103+
def set_name_config(self, name, config):
104+
"""sets hls_config["LayerName"][name] = config"""
105+
hls_config = self.config['HLSConfig']
106+
layer_config = hls_config.setdefault('LayerName', {})
107+
layer_config[name] = config
108+
103109
def get_precision(self, layer, var='default'):
104110
precision = self.layer_name_precision.get(layer.name.lower() + '_' + var)
105111
type_name = layer.name.lower() + '_' + var + '_t'
@@ -183,6 +189,35 @@ def get_compression(self, layer):
183189

184190
return compression
185191

192+
def parse_name_config(self, layer_name, layer_cfg):
193+
"""This is used by _parse_hls_config below, but also in optimizers when a new layer config is created"""
194+
precision_cfg = layer_cfg.get('Precision')
195+
if isinstance(precision_cfg, dict):
196+
for var, precision in precision_cfg.items():
197+
self.layer_name_precision[layer_name.lower() + '_' + var] = precision
198+
else:
199+
self.layer_name_precision[layer_name.lower() + '_default'] = precision_cfg
200+
201+
rf = layer_cfg.get('ReuseFactor')
202+
if rf is not None:
203+
self.layer_name_rf[layer_name.lower()] = rf
204+
205+
targ_cycles = layer_cfg.get('TargetCycles')
206+
if targ_cycles is not None:
207+
self.layer_name_targ_cycles[layer_name.lower()] = targ_cycles
208+
209+
strategy = layer_cfg.get('Strategy')
210+
if strategy is not None:
211+
self.layer_name_strategy[layer_name.lower()] = strategy
212+
213+
conv_implementation = layer_cfg.get('ConvImplementation')
214+
if conv_implementation is not None:
215+
self.layer_name_conv_implementation[layer_name.lower()] = conv_implementation
216+
217+
compression = layer_cfg.get('Compression')
218+
if compression is not None:
219+
self.layer_name_compression[layer_name.lower()] = bool(compression)
220+
186221
def _parse_hls_config(self):
187222
hls_config = self.config['HLSConfig']
188223

@@ -255,32 +290,7 @@ def _parse_hls_config(self):
255290
layer_name_cfg = hls_config.get('LayerName')
256291
if layer_name_cfg is not None:
257292
for layer_name, layer_cfg in layer_name_cfg.items():
258-
precision_cfg = layer_cfg.get('Precision')
259-
if isinstance(precision_cfg, dict):
260-
for var, precision in precision_cfg.items():
261-
self.layer_name_precision[layer_name.lower() + '_' + var] = precision
262-
else:
263-
self.layer_name_precision[layer_name.lower() + '_default'] = precision_cfg
264-
265-
rf = layer_cfg.get('ReuseFactor')
266-
if rf is not None:
267-
self.layer_name_rf[layer_name.lower()] = rf
268-
269-
targ_cycles = layer_cfg.get('TargetCycles')
270-
if targ_cycles is not None:
271-
self.layer_name_targ_cycles[layer_name.lower()] = targ_cycles
272-
273-
strategy = layer_cfg.get('Strategy')
274-
if strategy is not None:
275-
self.layer_name_strategy[layer_name.lower()] = strategy
276-
277-
conv_implementation = layer_cfg.get('ConvImplementation')
278-
if conv_implementation is not None:
279-
self.layer_name_conv_implementation[layer_name.lower()] = conv_implementation
280-
281-
compression = layer_cfg.get('Compression')
282-
if compression is not None:
283-
self.layer_name_compression[layer_name.lower()] = bool(compression)
293+
self.parse_name_config(layer_name, layer_cfg)
284294

285295
def _validate_hls_config(self):
286296
use_dataflow = False

hls4ml/model/layers.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ def __init__(self, model, name, attributes, inputs, outputs=None):
100100

101101
layer_config = self.model.config.get_layer_config(self)
102102
for config_key, config_value in layer_config.items():
103+
print(f'{config_key=}, {config_value=}')
103104
config_key = convert_to_snake_case(config_key)
104105
if config_key in self.attributes:
105106
print(
@@ -179,6 +180,12 @@ def _set_accum_t(self):
179180
accum_t = NamedType(*reversed(self.model.config.get_precision(self, 'accum')))
180181
self.set_attr('accum_t', accum_t)
181182

183+
def _set_type_t(self, name):
184+
has_type_t = any(a for a in self.expected_attributes if a.name == name + '_t' and isinstance(a, TypeAttribute))
185+
if has_type_t:
186+
type_t = NamedType(*reversed(self.model.config.get_precision(self, name)))
187+
self.set_attr(name + '_t', type_t)
188+
182189
def get_input_node(self, input_name=None):
183190
if input_name is None:
184191
if len(self.inputs) > 0:
@@ -470,6 +477,11 @@ def initialize(self):
470477

471478
self.add_bias(quantizer=self.get_attr('bias_quantizer'))
472479

480+
# set the needed types if needed
481+
self._set_type_t('pointwise_accum')
482+
self._set_type_t('depthwise_accum')
483+
self._set_type_t('depthwise_result')
484+
473485

474486
class DepthwiseConv1D(Conv1D):
475487
def initialize(self):
@@ -616,6 +628,10 @@ def initialize(self):
616628

617629
self.add_bias(quantizer=self.get_attr('bias_quantizer'))
618630

631+
self._set_type_t('pointwise_accum')
632+
self._set_type_t('depthwise_accum')
633+
self._set_type_t('depthwise_result')
634+
619635

620636
class DepthwiseConv2D(Conv2D):
621637
def initialize(self):

0 commit comments

Comments
 (0)