33from hls4ml .model .types import Source
44
55
6+ def generate_pointwise_conv1d_fn (layer_idx , reuse_factor = 1 ):
7+ """Generate a C++ function for a pointwise convolution layer.
8+
9+ Args:
10+ layer_idx (int): Index of layer ('index' attribute).
11+ reuse_factor (int): Number of partitions to divide the input into.
12+
13+ Returns:
14+ str: Generated C++ function
15+ """
16+
17+ generated_code = (
18+ "template<class data_T, class res_T, typename CONFIG_T>\n "
19+ "class pointwise_conv_{index} : public PointwiseConv1D<data_T, res_T, CONFIG_T> {{\n "
20+ " public:\n "
21+ " static void pointwise_conv(\n "
22+ " data_T data[CONFIG_T::in_width * CONFIG_T::n_chan],\n "
23+ " res_T res[CONFIG_T::out_width * CONFIG_T::n_filt],\n "
24+ " typename CONFIG_T::weight_t weights[CONFIG_T::n_chan * CONFIG_T::n_filt],\n "
25+ " typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) {{\n "
26+ " data_T data_tmp[CONFIG_T::reuse_factor][CONFIG_T::in_width * CONFIG_T::n_chan / CONFIG_T::reuse_factor];\n " # noqa: E501
27+ " #pragma HLS ARRAY_PARTITION variable=data_tmp complete dim=0\n "
28+ " res_T res_tmp[CONFIG_T::reuse_factor][CONFIG_T::out_width * CONFIG_T::n_filt / CONFIG_T::reuse_factor];\n " # noqa: E501
29+ " #pragma HLS ARRAY_PARTITION variable=res_tmp complete dim=0\n \n "
30+ " RFInputLoop:\n "
31+ " for (int jj = 0; jj < CONFIG_T::reuse_factor; jj++) {{\n "
32+ " #pragma HLS UNROLL\n "
33+ " InnerInputLoop:\n "
34+ " for (int ii = 0; ii < CONFIG_T::in_width * CONFIG_T::n_chan / CONFIG_T::reuse_factor; ii++) {{\n "
35+ " #pragma HLS UNROLL\n "
36+ " data_tmp[jj][ii] = data[jj * CONFIG_T::in_width * CONFIG_T::n_chan / CONFIG_T::reuse_factor + ii];\n " # noqa: E501
37+ " }}\n "
38+ " }}\n \n "
39+ ).format (index = layer_idx )
40+ indent = " "
41+ for i in range (reuse_factor ):
42+ generated_code += indent
43+ generated_code += (
44+ f"pointwise_conv_1d_latency_cl<data_T, res_T, CONFIG_T>(data_tmp[{ i } ], res_tmp[{ i } ], weights, biases);\n "
45+ )
46+
47+ generated_code += (
48+ "\n "
49+ " RFOutputLoop:\n "
50+ " for (int jj = 0; jj < CONFIG_T::reuse_factor; jj++) {\n "
51+ " #pragma HLS UNROLL\n "
52+ " InnerOutputLoop:\n "
53+ " for (int ii = 0; ii < CONFIG_T::out_width * CONFIG_T::n_filt / CONFIG_T::reuse_factor; ii++) {\n "
54+ " #pragma HLS UNROLL\n "
55+ " res[jj * CONFIG_T::out_width * CONFIG_T::n_filt / CONFIG_T::reuse_factor + ii] = res_tmp[jj][ii];\n " # noqa: E501
56+ " }\n "
57+ " }\n "
58+ " }\n "
59+ "};\n "
60+ )
61+
62+ return generated_code
63+
64+
665class GeneratePointwiseConv1D (OptimizerPass ):
766 '''Generates code for pointwise 1D convolution'''
867
@@ -17,7 +76,7 @@ def transform(self, model, node):
1776 raise Exception (f'Cannot generate instructions for node { node .name } ({ node_class } )' )
1877
1978 def _generate_pointwise_conv1d (self , node ):
20- code_str = node . model . config . backend . generate_pointwise_conv1d_fn (
79+ code_str = generate_pointwise_conv1d_fn (
2180 node .get_attr ('index' ),
2281 node .get_attr ('reuse_factor' ),
2382 )
0 commit comments