xref: /freebsd/sys/dev/bnxt/bnxt_en/convert_hsi.pl (revision e9ac41698b2f322d55ccf9da50a3596edb2c1800)
1#!/usr/bin/env perl
2
3# This script cleans up the "official" Broadcom hsi_struct_defs.h file as distributed
4# to something somewhat more programmer friendly.
5#
6
7my $do_decode = 0;
8
9if (! -f $ARGV[0]) {
10	print "Input file not specified (should be path to hsi_struct_defs.h)\n";
11	exit 1;
12}
13
14if (!open(IN, "<", $ARGV[0])) {
15	print "Failure to open input file\n";
16	exit 1;
17}
18
19if (!open(OUT, ">", "hsi_struct_def.h")) {
20	print "Failure to open output file\n";
21	exit 1;
22}
23
24$/=undef;
25my $header = <IN>;
26close IN;
27
28print OUT <<END_OF_NOTICE;
29/*-
30 *   BSD LICENSE
31 *
32 *   Copyright (c) 2016 Broadcom, All Rights Reserved.
33 *   The term Broadcom refers to Broadcom Limited and/or its subsidiaries
34 *
35 *   Redistribution and use in source and binary forms, with or without
36 *   modification, are permitted provided that the following conditions
37 *   are met:
38 *     * Redistributions of source code must retain the above copyright
39 *       notice, this list of conditions and the following disclaimer.
40 *     * Redistributions in binary form must reproduce the above copyright
41 *       notice, this list of conditions and the following disclaimer in
42 *       the documentation and/or other materials provided with the
43 *       distribution.
44 *
45 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
46 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
47 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
48 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
49 *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
52 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
53 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
55 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 */
57
58END_OF_NOTICE
59
60# Convert line endings
61$header =~ s/\r\n/\n/gs;
62
63# Convert arrays of two u32_t to a single uint64_t
64$header =~ s/\bu32_t(\s+[a-zA-Z0-9_]+)\[2\]/uint64_t$1/gs;
65
66# Convert uint32_t *_lo/uint32_t *_hi to a single uint64_t
67$header =~ s/\bu32_t(\s+[a-zA-Z0-9_]+)_lo;\s*\r?\n\s*u32_t(\s+[a-zA-Z0-9_]+)_hi/uint64_t$1/gs;
68
69# Convert types
70$header =~ s/\bu([0-9]+)_t\b/uint$1_t/gs;
71
72# Convert literals
73$header =~ s/\b((?:0x)?[0-9a-f]+)UL/UINT32_C($1)/gs;
74
75# Strip comments
76#$header =~ s/^(\s*[^\/\s][^\/]+?)\s*\/\*.*?\*\/\s*?$/$1/gm;
77#$header =~ s/[ \t]*\/\*.*?\*\/\s*?\n?//gs;
78
79# Pack structs
80#$header =~ s/}(\s+)([^\s]+_t[,;])/} __attribute__((packed))$1$2/gs;
81
82# Normalize indent
83$header =~ s/(    ) +(#define)/$1$2/gs;
84$header =~ s/^(}[^\n]*;)\n([^\n])/$1\n\n$2/gsm;
85$header =~ s/([^\n])\n(typedef)/$1\n\n$2/gs;
86$header =~ s/        /\t/g;
87$header =~ s/    /\t/g;
88$header =~ s/([^\s]\t+) +/$1/g;
89
90# Remove typedefs and pack structs
91$header =~ s/^typedef struct (.*?)\n{\n(.*?)}[^\n]*;/struct $1 {\n$2} __attribute__((packed));/gsm;
92
93print OUT $header;
94close OUT;
95
96if ($do_decode) {
97	if(!open(OUT, ">", "hsi_struct_decode.c")) {
98		print "Failure to open decoder output file\n";
99		exit 1;
100	}
101
102	print OUT <<END_OF_NOTICE;
103	/*-
104	 *   BSD LICENSE
105	 *
106	 *   Copyright (c) 2016 Broadcom, All Rights Reserved.
107	 *   The term Broadcom refers to Broadcom Limited and/or its subsidiaries
108	 *
109	 *   Redistribution and use in source and binary forms, with or without
110	 *   modification, are permitted provided that the following conditions
111	 *   are met:
112	 *     * Redistributions of source code must retain the above copyright
113	 *       notice, this list of conditions and the following disclaimer.
114	 *     * Redistributions in binary form must reproduce the above copyright
115	 *       notice, this list of conditions and the following disclaimer in
116	 *       the documentation and/or other materials provided with the
117	 *       distribution.
118	 *
119	 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
120	 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
121	 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
122	 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
123	 *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
124	 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
125	 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
126	 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
127	 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
128	 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
129	 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
130	 */
131
132END_OF_NOTICE
133
134	if(!open(HDR, ">", "hsi_struct_decode.h")) {
135		print "Failure to open decoder output header file\n";
136		exit 1;
137	}
138
139	print HDR <<END_OF_NOTICE;
140	/*-
141	 *   BSD LICENSE
142	 *
143	 *   Copyright(c) 2014-2015 Broadcom Corporation.
144	 *   All rights reserved.
145	 *
146	 *   Redistribution and use in source and binary forms, with or without
147	 *   modification, are permitted provided that the following conditions
148	 *   are met:
149	 *
150	 *     * Redistributions of source code must retain the above copyright
151	 *       notice, this list of conditions and the following disclaimer.
152	 *     * Redistributions in binary form must reproduce the above copyright
153	 *       notice, this list of conditions and the following disclaimer in
154	 *       the documentation and/or other materials provided with the
155	 *       distribution.
156	 *     * Neither the name of Broadcom Corporation nor the names of its
157	 *       contributors may be used to endorse or promote products derived
158	 *       from this software without specific prior written permission.
159	 *
160	 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
161	 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
162	 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
163	 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
164	 *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
165	 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
166	 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
167	 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
168	 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
169	 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
170	 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
171	 */
172
173END_OF_NOTICE
174
175	print OUT "#ifdef HSI_DEBUG\n#include <inttypes.h>\n#include <rte_common.h>\n#include <rte_log.h>\n#include \"hsi_struct_def_dpdk.h\"\n#include \"hsi_struct_decode.h\"\n#include \"hsi_struct_decode.h\"\n\n";
176	print HDR "#ifdef HSI_DEBUG\n#include \"hsi_struct_def_dpdk.h\"\n\n";
177
178	my $hdr_defs = '';
179
180	sub print_single_val
181	{
182		my $field=shift;
183		my $type=shift;
184		my $max_field_len=shift;
185		my $name = shift;
186		my $macroshash = shift;
187		my %macros = %$macroshash;
188		$macrosref = shift;
189		my @macros = @$macrosref;
190		$macrosref = shift;
191		my @fields = @$macrosref;
192
193		if ($type eq 'uint32_t') {
194			printf OUT "\tRTE_LOG(DEBUG, PMD, \"  % *s = 0x%%08\"PRIX32\"\\n\", data->$field);\n",$max_field_len,$field;
195		}
196		elsif ($type eq 'uint16_t') {
197			printf OUT "\tRTE_LOG(DEBUG, PMD, \"  % *s = 0x%%04\"PRIX16\"\\n\", data->$field);\n",$max_field_len,$field;
198		}
199		elsif ($type eq 'uint8_t') {
200			printf OUT "\tRTE_LOG(DEBUG, PMD, \"  % *s = 0x%%02\"PRIX8\"\\n\", data->$field);\n",$max_field_len,$field;
201		}
202		elsif ($type eq 'uint64_t') {
203			printf OUT "\tRTE_LOG(DEBUG, PMD, \"  % *s = 0x%%016\"PRIX64\"\\n\", data->$field);\n",$max_field_len,$field;
204		}
205		elsif ($type eq 'char') {
206			if ($field =~ s/\[([0-9]+)\]//) {
207				printf OUT "\tRTE_LOG(DEBUG, PMD, \"  % *s = \\\"%%.$1s\\\"\\n\", data->$field);\n",$max_field_len,$field;
208			}
209			else {
210				printf OUT "\tRTE_LOG(DEBUG, PMD, \"  % *s = 0x%%02\"PRIX8\"\\n\", data->$field);\n",$max_field_len,$field;
211			}
212		}
213		else {
214			print "Unhandled type: '$type'\n";
215		}
216
217		my $macro_prefix = uc($name).'_'.uc($field).'_';
218		# Special handling for the common flags_type field
219		$macro_prefix =~ s/FLAGS_TYPE_$/FLAGS_/ if ($field eq 'flags_type');
220		# Special handling for _hi types
221		$macro_prefix =~ s/_HI_/_/ if ($name =~ /_hi$/);
222
223		$macro_prefix =~ s/\[[0-9]+\]//;
224		my %vmacros;
225		my $vmacros_have_mask = 0;
226		my @vmacros;
227		my %subfields;
228		my $all_single_bits=1;
229	MACRO:
230		foreach my $macro (@macros) {
231			if ($macro =~ /^$macro_prefix(.*)_MASK$/) {
232				my $macro = $&;
233				my $maskdef = $macros{$macro};
234				my $subfield = $1;
235				my $subfield_value = "(data->$field & $macro)";
236				if (defined $macros{"$macro_prefix$subfield\_SFT"}) {
237					$subfield_value = "($subfield_value >> $macro_prefix$subfield\_SFT)";
238				}
239				$maskdef =~ s/[x0 ]//g;
240				if ($type eq 'uint64_t') {
241					printf OUT "\tRTE_LOG(DEBUG, PMD, \"  % *s   $subfield = %%0*\" PRIX64 \"\\n\", %u, $subfield_value);\n", $max_field_len, '', length($maskdef);
242				}
243				else {
244					printf OUT "\tRTE_LOG(DEBUG, PMD, \"  % *s   $subfield = %%0*X\\n\", %u, $subfield_value);\n", $max_field_len, '', length($maskdef);
245				}
246				delete $$macroshash{$macro};
247			}
248			elsif ($macro =~ /^$macro_prefix(.*)_SFT$/) {
249				delete $$macroshash{$macro};
250			}
251			elsif ($macro =~ /^$macro_prefix\MASK$/) {
252				$vmacros_have_mask = 1;
253				delete $$macroshash{$macro};
254			}
255			elsif ($macro =~ /^$macro_prefix(.*)$/) {
256				my $macro = $&;
257				my $subfield = $1;
258
259				# Check for longer fields with the same base... ie: link and link_speed
260				foreach my $extra_field (@fields) {
261					next if ($extra_field eq $field);
262					if ($extra_field =~ /^$field/) {
263						my $extra_prefix = uc($name).'_'.uc($extra_field).'_';
264						next MACRO if ($macro =~ /^$extra_prefix/);
265					}
266				}
267
268				push @vmacros, $macro;
269				my $macroeval = $macros{$macro};
270				$macroeval =~ s/UINT32_C\((.*?)\)/$1/g;
271				$vmacros{$macro} = eval("$macroeval");
272				$subfields{$macro} = $subfield;
273
274				$all_single_bits = 0 if ($vmacros{$macro} & ($vmacros{$macro}-1));
275				$all_single_bits = 0 if ($vmacros{$macro} == 0);
276			}
277		}
278		if ($all_single_bits) {
279			foreach my $macro (@vmacros) {
280				my $subfield_value = "(data->$field & $macro)";
281				printf OUT "\tRTE_LOG(DEBUG, PMD, \"  % *s   $subfields{$macro} : %%s\\n\", $subfield_value?\"ON\":\"OFF\");\n", $max_field_len, '';
282				delete $$macroshash{$macro};
283			}
284		}
285		else {
286			printf OUT "\tRTE_LOG(DEBUG, PMD, \"  % *s   Value : %%s\\n\",\n", $max_field_len, '';
287			foreach my $macro (@vmacros) {
288				my $subfield_value = "data->$field";
289				$subfield_value = "($subfield_value & $macro_prefix\MASK)" if $vmacros_have_mask;
290				print OUT "\t\t$subfield_value == $macro ? \"$subfields{$macro}\" :\n";
291				delete $$macroshash{$macro};
292			}
293			print OUT "\t\t\"Unknown\");\n";
294		}
295	}
296
297	while ($header =~ /^typedef\s+struct\s+(.*?)\s+{(.*?)^}/msg) {
298		my ($name,$def) = ($1, $2);
299		my @fields=();
300		my %type=();
301		my @macros=();
302		my %macros=();
303		my $max_field_len=0;
304
305		# First, pull out all the fields in order...
306		while($def =~ /^\s*([^\s#\/]+?)\s+([^;\/\s]+?)\s*;/mg) {
307			my ($type, $name) = ($1, $2);
308			push @fields, $name;
309			$type{$name}=$type;
310			$max_field_len = length($name) if length($name) > $max_field_len;
311		}
312		# Now, pull out the macros...
313		while($def =~ /^\s*\#define\s+([^\s]+?)\s+(.*?)\s*$/mg) {
314			push @macros, $1;
315			$macros{$1}=$2;
316		}
317
318		# Now, generate code to print the struct...
319		print OUT "void decode_$name(const char *string __rte_unused, struct $name *data) {\n\tRTE_LOG(DEBUG, PMD, \"$name\\n\");\n";
320		print HDR "void decode_$name(const char *string __rte_unused, struct $name *data);\n";
321		$hdr_defs .= "#define decode_$name(x, y) {}\n";
322		foreach my $field (@fields) {
323			if ($field =~ /\[([0-9]+)\]/) {
324				if ($type{$field} eq 'char') {
325					print_single_val($field, $type{$field}, $max_field_len, $name, \%macros, \@macros, \@fields);
326				}
327				else {
328					foreach my $idx (0..$1-1) {
329						my $item = $field;
330						$item =~ s/\[[0-9]+\]/[$idx]/;
331						print_single_val($item, $type{$field}, $max_field_len, $name, \%macros, \@macros, \@fields);
332					}
333				}
334			}
335			else {
336				print_single_val($field, $type{$field}, $max_field_len, $name, \%macros, \@macros, \@fields);
337			}
338		}
339	#	print "Unhandled macros:\n",join("\n", keys %macros),"\n" if (keys %macros > 0);
340		print OUT "}\n\n";
341	}
342	print OUT "#endif\n";
343
344	print HDR "#else\n";
345	print HDR $hdr_defs;
346	print HDR "#endif\n";
347	close OUT;
348	close HDR;
349}
350