File Coverage

blib/lib/SystemC/Vregs/Output/CBitFields.pm
Criterion Covered Total %
statement 83 96 86.4
branch 17 22 77.2
condition 24 30 80.0
subroutine 9 10 90.0
pod 2 2 100.0
total 135 160 84.3


line stmt bran cond sub pod time code
1             # See copyright, etc in below POD section.
2             ######################################################################
3              
4             package SystemC::Vregs::Output::CBitFields;
5 1     1   574 use SystemC::Vregs::Number;
  1         2  
  1         38  
6 1     1   4 use SystemC::Vregs::Language;
  1         2  
  1         17  
7 1     1   4 use Carp;
  1         1  
  1         46  
8 1     1   5 use strict;
  1         2  
  1         32  
9 1     1   5 use vars qw($VERSION);
  1         2  
  1         52  
10 1     1   4 use base qw(SystemC::Vregs::Output::Class); # So we get enum_struct_write
  1         7  
  1         582  
11              
12             $VERSION = '1.470';
13              
14             ######################################################################
15             # CONSTRUCTOR
16              
17             sub new {
18 1     1 1 411 my $class = shift;
19 1         11 my $self = {@_};
20 1         4 bless $self, $class;
21 1         12 return $self;
22             }
23              
24             ######################################################################
25             ######################################################################
26             ######################################################################
27             ######################################################################
28              
29             sub _class_h_write_dw {
30 0     0   0 my $self = shift;
31 0         0 my $typeref = shift;
32 0         0 my $pack = shift;
33 0         0 my $fl = shift;
34              
35 0         0 my $wget = $fl->call_str($typeref->{name},"","w(");
36 0         0 my $wset = $fl->call_str($typeref->{name},"set","w(");
37              
38 0 0 0     0 if (($typeref->{words}||0) > 1) {
39             # make full dw accessors if the type is >32 bits
40 0         0 $fl->fn($typeref->{name},"","inline uint64_t dw(int b) const",
41             ,"{\n"
42             ."\tunion {uint64_t udw; uint32_t lw[2];} u;\n"
43             ."\tu.lw[0]=${wget}b*2+0); u.lw[1]=${wget}b*2+1); return u.udw; }\n");
44 0         0 $fl->fn($typeref->{name},"set","inline void dw(int b, uint64_t val)"
45             ,"{\n"
46             ."\tunion {uint64_t udw; uint32_t lw[2];} u;\n"
47             ."\tu.udw=val; ${wset}b*2+0,u.lw[0]); ${wset}b*2+1,u.lw[1]); }\n");
48             } else {
49             # still make dw accessors, but don't read or write w[1] because
50             # it doesn't exist.
51 0         0 $fl->fn($typeref->{name},"","inline uint64_t dw(int b) const"
52             ,"{\n"
53             ."\tunion {uint64_t udw; uint32_t lw[2];} u;\n"
54             ."\tu.lw[0]=${wget}b*2+0); u.lw[1]=0; return u.udw; }\n");
55 0         0 $fl->fn($typeref->{name},"set","inline void dw(int b, uint64_t val)"
56             ,"{\n"
57             ."\tunion {uint64_t udw; uint32_t lw[2];} u;\n"
58             ."\tu.udw=val; ${wset}b*2+0,u.lw[0]); }\n");
59             }
60             }
61              
62              
63             sub _class_write {
64 7     7   9 my $self = shift;
65 7         18 my $typeref = shift;
66 7         9 my $pack = shift;
67 7         11 my $fl = shift;
68              
69 7   50     24 my $clname = $typeref->{name} || "x";
70              
71 7         23 $fl->print("typedef struct {\n");
72             #use Data::Dumper; $fl->print(Dumper($typeref->{bitarray}));
73              
74             # What fields are non-contiguous? We need to add _#'s to differentiate the parts.
75 7         9 my %noncontig;
76             my %width_by_lsb;
77 0         0 my $lastbitref;
78 7         11 my $fieldlsb = undef;
79 7         11 for (my $bit=0; $bit<=$#{$typeref->{bitarray}}; $bit++) {
  487         1308  
80 480         1072 my $bitref = $typeref->{bitarray}[$bit]{bitref};
81 480 100 100     2271 if ($bitref && (!$lastbitref || $bitref != $lastbitref)) { # LSB of bitref
      66        
82 34         42 $fieldlsb = $bit;
83             }
84 480 100 100     2711 if ($bitref && $lastbitref && $bitref != $lastbitref
      100        
      100        
85             && defined $noncontig{$bitref->{name}}) {
86 5         15 $noncontig{$bitref->{name}} = 1; # 1=duplicate
87             }
88 480 100       962 if ($bitref) {
89 388   100     1474 $noncontig{$bitref->{name}} ||= 0; # 0=seen
90 388         546 $width_by_lsb{$fieldlsb}++;
91             }
92 480         788 $lastbitref = $bitref;
93             }
94              
95 7         13 my $padbits = 0;
96 7         8 my $padnum = 0;
97 7         9 $lastbitref = undef;
98 7         10 for (my $bit=0; $bit<=$#{$typeref->{bitarray}}; $bit++) {
  133         339  
99 126         197 my $bitref = $typeref->{bitarray}[$bit]{bitref};
100 126 100       200 if ($bitref) {
101 34 100       64 if ($padbits) {
102             # Need to output padding before this field
103 8 50       42 $fl->printf(" %s\t_pad_%d:%d;\n",
104             (($padbits > 32) ? "uint64_t" : "uint32_t"),
105             $padnum++, $padbits);
106 8         17 $padbits = 0;
107             }
108 34 100 66     283 if ($bitref && $lastbitref && $bitref != $lastbitref
      66        
      100        
109             && $noncontig{$bitref->{name}}) {
110             # Increment the suffix each time we hit a split in the non-contiguous field
111 6         11 $noncontig{$bitref->{name}}++;
112             }
113              
114 34         147 (my $lc_mnem = $bitref->{name}) =~ s/^(.)/lc $1/xe;
  34         99  
115 34         44 my $nc_suffix = "";
116 34 100       105 $nc_suffix = "_".$noncontig{$bitref->{name}} if $noncontig{$bitref->{name}};
117              
118 34 50       168 $fl->printf(" %s\t%s:%d;\n",
119             (($width_by_lsb{$bit} > 32) ? "uint64_t" : "uint32_t"),
120             $lc_mnem.$nc_suffix, $width_by_lsb{$bit});
121             # Jump ahead a number of bits
122 34         97 $bit += $width_by_lsb{$bit} - 1;
123             } else {
124 92         100 $padbits++;
125             }
126 126         179 $lastbitref = $bitref;
127             }
128              
129 7         26 $fl->print("} $clname;\n");
130 7         26 $fl->print("\n");
131             }
132              
133             sub write {
134 1     1 1 2 my $self = shift;
135 1         7 my %params = (@_);
136 1 50       6 my $pack = $params{pack} or croak "%Error: No pack=> parameter passed,";
137             # Dump headers for class name based accessors
138              
139 1         13 my $fl = SystemC::Vregs::File->open(language=>'C',
140             rules => $pack->{rules},
141             %params);
142              
143 1         22 $fl->include_guard();
144 1         4 $fl->print("\n");
145 1         7 $fl->comment("package $pack->{name}\n");
146 1         4 $fl->print("\n");
147              
148 1         6 $pack->{rules}->execute_rule ('defines_file_before', 'file_body', $pack);
149              
150 1         4 $fl->print("// Vregs library Files:\n");
151 1         2 foreach my $packref (@{$pack->{libraries}}) {
  1         5  
152 0         0 $fl->print("#include \"$packref->{name}_bitfields.h\"\n");
153             }
154              
155 1         13 $fl->print("\n\n");
156              
157 1         7 foreach my $typeref ($pack->enums_sorted) {
158 2         17 $self->enum_struct_write ($typeref, $pack, $fl);
159             }
160              
161 1         6 $fl->print("\n\n");
162             # Bitbashing done verbosely to avoid slow preprocess time
163             # We could use bit structures, but they don't work on non-contiguous fields
164              
165             # Sorted first does base classes, then children
166 1         9 foreach my $typeref ($pack->types_sorted) {
167 7         25 $self->_class_write($typeref, $pack, $fl);
168             }
169              
170 1         14 $pack->{rules}->execute_rule ('defines_file_after', 'file_body', $pack);
171              
172 1         30 $fl->close();
173             }
174              
175             ######################################################################
176             ######################################################################
177             #### Package return
178             1;
179             __END__