From 21a6eaeed229fa4aaf923679d00a175ec185949c Mon Sep 17 00:00:00 2001 From: HamzaEzzRa Date: Tue, 11 Aug 2026 22:25:22 -0400 Subject: [PATCH] fix(vivado): Derive softmax layer config name from activation attribute --- .../backends/vivado/passes/core_templates.py | 2 +- test/pytest/test_softmax.py | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/hls4ml/backends/vivado/passes/core_templates.py b/hls4ml/backends/vivado/passes/core_templates.py index 755eb6de44..777a435ab0 100644 --- a/hls4ml/backends/vivado/passes/core_templates.py +++ b/hls4ml/backends/vivado/passes/core_templates.py @@ -347,7 +347,7 @@ def format(self, node): use_multidim = node.get_attr('n_inner', 1) > 1 or node.get_attr('n_outer', 1) > 1 use_multidim = use_multidim and node.model.config.get_config_value('IOType') == 'io_parallel' params['activation'] = 'softmax' if not use_multidim else 'softmax_multidim' - params['config'] = f'softmax_config{node.index}' + params['config'] = '{}_config{}'.format(node.get_attr('activation'), node.index) return self.template.format(**params) diff --git a/test/pytest/test_softmax.py b/test/pytest/test_softmax.py index 418f64b558..894d8bc4f0 100644 --- a/test/pytest/test_softmax.py +++ b/test/pytest/test_softmax.py @@ -19,6 +19,7 @@ def generate_data(input_shape): return np.clip(d, -32, 31) +@pytest.mark.parametrize('softmax_impl', ['activation', 'standalone']) @pytest.mark.parametrize('backend', ['Vivado', 'Vitis', 'Quartus', 'Catapult']) @pytest.mark.parametrize('strategy', ['stable', 'latency', 'argmax']) @pytest.mark.parametrize( @@ -35,10 +36,15 @@ def generate_data(input_shape): ('16,6', (8, 8, 3), '18,8', 'io_stream', False), ], ) -def test_softmax(test_case_id, backend, strategy, generate_data, input_bits, input_shape, table_bits, io_type, custom_accum): +def test_softmax( + test_case_id, softmax_impl, backend, strategy, generate_data, input_bits, input_shape, table_bits, io_type, custom_accum +): X = generate_data model = tf.keras.models.Sequential() - model.add(tf.keras.layers.Activation(input_shape=input_shape, activation='softmax', name='softmax')) + if softmax_impl == 'activation': + model.add(tf.keras.layers.Activation(input_shape=input_shape, activation='softmax', name='softmax')) + else: + model.add(tf.keras.layers.Softmax(input_shape=input_shape, name='softmax')) model.compile() table_type = f'fixed<{table_bits}, RND, SAT>' @@ -73,12 +79,16 @@ def test_softmax(test_case_id, backend, strategy, generate_data, input_bits, inp assert acc_hls4ml >= 0.98 +@pytest.mark.parametrize('softmax_impl', ['activation', 'standalone']) @pytest.mark.parametrize('backend', ['Vivado', 'Vitis', 'Quartus', 'Catapult']) @pytest.mark.parametrize('io_type', ['io_parallel', 'io_stream']) -def test_softmax_skipped(test_case_id, backend, io_type): +def test_softmax_skipped(test_case_id, softmax_impl, backend, io_type): X = np.random.rand(100, 10) dense = tf.keras.layers.Dense(14, input_shape=(10,), name='dense') - softmax = tf.keras.layers.Activation(activation='softmax', name='softmax') + if softmax_impl == 'activation': + softmax = tf.keras.layers.Activation(activation='softmax', name='softmax') + else: + softmax = tf.keras.layers.Softmax(name='softmax') model = tf.keras.models.Sequential([dense, softmax]) model.compile()