21
21
22
22
import hls4ml
23
23
from hls4ml .converters .keras_to_hls import parse_default_keras_layer
24
- from hls4ml .model .types import FixedPrecisionType , NamedType
24
+ from hls4ml .model .attributes import ConfigurableAttribute , TypeAttribute
25
+ from hls4ml .model .types import FixedPrecisionType , RoundingMode , SaturationMode
25
26
26
27
27
28
# Keras implementation of a KL layer
@@ -47,21 +48,23 @@ def _merge_function(self, inputs):
47
48
class HKLLoss (hls4ml .model .layers .Layer ):
48
49
'''hls4ml implementation of a KL loss custom layer'''
49
50
51
+ _expected_attributes = [
52
+ ConfigurableAttribute ('table_size' , default = 1024 ),
53
+ ConfigurableAttribute ('exp_range' , default = 8 ),
54
+ TypeAttribute ('accum' ),
55
+ TypeAttribute (
56
+ 'sum' ,
57
+ default = FixedPrecisionType (18 , 8 , rounding_mode = RoundingMode .RND , saturation_mode = SaturationMode .SAT ),
58
+ ),
59
+ TypeAttribute (
60
+ 'exp_table' ,
61
+ default = FixedPrecisionType (18 , 8 , rounding_mode = RoundingMode .RND , saturation_mode = SaturationMode .SAT ),
62
+ ),
63
+ ]
64
+
50
65
def initialize (self ):
51
66
self .add_output_variable (shape = [1 ], dim_names = [f'KL_LOSS_{ self .index } ' ])
52
67
53
- print (self .attributes )
54
- if 'sum_t' not in self .attributes :
55
- self .set_attr ('sum_t' , self .get_attr ('accum_t' ))
56
- if 'exp_table_t' not in self .attributes :
57
- self .set_attr (
58
- 'exp_table_t' , NamedType (name = self .name + '_exp_table_t' , precision = FixedPrecisionType (width = 18 , integer = 8 ))
59
- )
60
- if 'table_size' not in self .attributes :
61
- self .set_attr ('table_size' , 1024 )
62
- if 'exp_range' not in self .attributes :
63
- self .set_attr ('exp_range' , 8 )
64
-
65
68
66
69
# Templates
67
70
distance_config_template = """struct config{index} : nnet::distance_config {{
@@ -73,8 +76,8 @@ def initialize(self):
73
76
static const unsigned table_size = {table_size};
74
77
static constexpr float exp_range = {exp_range};
75
78
}};\n """
76
- distance_function_template = 'nnet::{distance} <{input1_t}, {input2_t}, {output_t}, {config}>({input1}, {input2}, {output});'
77
- distance_include_list = ['../../../contrib/kl_layer /kl_layer.h' ]
79
+ distance_function_template = 'nnet::klloss <{input1_t}, {input2_t}, {output_t}, {config}>({input1}, {input2}, {output});'
80
+ distance_include_list = ['nnet_utils /kl_layer.h' ]
78
81
79
82
80
83
class HKLLossConfigTemplate (hls4ml .backends .template .LayerConfigTemplate ):
@@ -96,7 +99,6 @@ def __init__(self):
96
99
97
100
def format (self , node ):
98
101
params = {}
99
- params ['distance' ] = 'klloss'
100
102
params ['config' ] = f'config{ node .index } '
101
103
params ['input1_t' ] = node .get_input_variable (node .inputs [0 ]).type .name
102
104
params ['input2_t' ] = node .get_input_variable (node .inputs [1 ]).type .name
@@ -134,7 +136,7 @@ def main():
134
136
backend .register_template (HKLLossFunctionTemplate )
135
137
136
138
# Register HLS implementation
137
- p = Path ('kl_layer.h' )
139
+ p = Path (__file__ ). parent / 'kl_layer.h'
138
140
backend .register_source (p )
139
141
140
142
# Test if it works
0 commit comments