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