[susieq] Update qib_genbits.pl to handle SusieQ definitions
[people/peper/gpxe.git] / src / drivers / infiniband / qib_genbits.pl
1 #!/usr/bin/perl -w
2 #
3 # Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License as
7 # published by the Free Software Foundation; either version 2 of the
8 # License, or any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 use strict;
20 use warnings;
21
22 my $offsets = {};
23 my $defaults = {};
24 my $structures = {};
25 my $structure = "";
26
27 while ( <> ) {
28   chomp;
29   if ( /^\#define (\S+)_OFFS (\S+)$/ ) {
30     $structure = $1;
31     $offsets->{$structure} = $2;
32   } elsif ( /^\#define ${structure}_DEF (\S+)$/ ) {
33     $defaults->{$structure} = $1;
34   } elsif ( /^\#define ${structure}_(\S+)_LSB (\S+)$/ ) {
35     $structures->{$structure}->{$1}->{LSB} = $2;
36   } elsif ( /^\#define ${structure}_(\S+)_MSB (\S+)$/ ) {
37     $structures->{$structure}->{$1}->{MSB} = $2;
38   } elsif ( /^\#define ${structure}_(\S+)_RMASK (\S+)$/ ) {
39     $structures->{$structure}->{$1}->{RMASK} = $2;
40   } elsif ( /^\s*$/ ) {
41     # Do nothing
42   } else {
43     print "$_\n";
44   }
45 }
46
47 my $data = [ map { { name => $_, offset => $offsets->{$_},
48                      default => $defaults->{$_} }; }
49              sort { hex ( $offsets->{$a} ) <=> hex ( $offsets->{$b} ) }
50              keys %$offsets ];
51
52 foreach my $datum ( @$data ) {
53   next unless exists $structures->{$datum->{name}};
54   $structure = $structures->{$datum->{name}};
55   my $fields = [ map { { name => $_, lsb => $structure->{$_}->{LSB},
56                          msb => $structure->{$_}->{MSB},
57                          rmask => $structure->{$_}->{RMASK} }; }
58                  sort { hex ( $structure->{$a}->{LSB} ) <=>
59                             hex ( $structure->{$b}->{LSB} ) }
60                  keys %$structure ];
61   $datum->{fields} = $fields;
62 }
63
64 print "\n/* This file has been further processed by $0 */\n\n";
65 print "FILE_LICENCE ( GPL2_ONLY );\n\n";
66
67 foreach my $datum ( @$data ) {
68   printf "#define %s_offset 0x%08xUL\n",
69       $datum->{name}, hex ( $datum->{offset} );
70   if ( exists $datum->{fields} ) {
71     my $lsb = 0;
72     my $reserved_idx = 0;
73     printf "struct %s_pb {\n", $datum->{name};
74     foreach my $field ( @{$datum->{fields}} ) {
75       my $pad_width = ( hex ( $field->{lsb} ) - $lsb );
76       die "Inconsistent LSB/RMASK in $datum->{name} before $field->{name}\n"
77           if $pad_width < 0;
78       printf "\tpseudo_bit_t _unused_%u[%u];\n", $reserved_idx++, $pad_width
79           if $pad_width;
80       $lsb += $pad_width;
81       # Damn Perl can't cope with 64-bit hex constants
82       my $width = 0;
83       die "Missing RMASK in $datum->{name}.$field->{name}\n"
84           unless defined $field->{rmask};
85       my $rmask = $field->{rmask};
86       while ( $rmask =~ /^(0x.+)f$/i ) {
87         $width += 4;
88         $rmask = $1;
89       }
90       $rmask = hex ( $rmask );
91       while ( $rmask ) {
92         $width++;
93         $rmask >>= 1;
94       }
95       if ( defined $field->{msb} ) {
96         my $msb_width = ( hex ( $field->{msb} ) - $lsb + 1 );
97         $width ||= $msb_width;
98         die "Inconsistent LSB/MSB/RMASK in $datum->{name}.$field->{name}\n"
99             unless $width == $msb_width;
100       }
101       printf "\tpseudo_bit_t %s[%u];\n", $field->{name}, $width;
102       $lsb += $width;
103     }
104     my $pad_width = ( 64 - $lsb );
105     die "Inconsistent LSB/RMASK in $datum->{name} final field\n"
106         if $pad_width < 0;
107     printf "\tpseudo_bit_t _unused_%u[%u];\n", $reserved_idx++, $pad_width
108         if $pad_width;
109     printf "};\n";
110     printf "struct %s {\n\tPSEUDO_BIT_STRUCT ( struct %s_pb );\n};\n",
111         $datum->{name}, $datum->{name};
112   }
113   printf "/* Default value: %s */\n", $datum->{default}
114       if defined $datum->{default};
115   print "\n";
116 }