File Coverage

blib/lib/SystemC/Vregs/Type.pm
Criterion Covered Total %
statement 125 183 68.3
branch 37 80 46.2
condition 3 17 17.6
subroutine 19 24 79.1
pod 4 16 25.0
total 188 320 58.7


line stmt bran cond sub pod time code
1             # See copyright, etc in below POD section.
2             ######################################################################
3              
4             package SystemC::Vregs::Type;
5 3     3   15 use SystemC::Vregs::Number;
  3         4  
  3         111  
6 3     3   1411 use SystemC::Vregs::Bit;
  3         8  
  3         123  
7 3     3   15 use Bit::Vector::Overload;
  3         6  
  3         100  
8              
9 3     3   15 use strict;
  3         4  
  3         153  
10 3     3   15 use vars qw ($VERSION);
  3         5  
  3         114  
11 3     3   12 use base qw (SystemC::Vregs::Subclass);
  3         6  
  3         6408  
12             $VERSION = '1.470';
13              
14             # Fields:
15             # {name} Field name (Subclass)
16             # {nor_name} Field name
17             # {at} File/line number (Subclass)
18             # {pack} Parent SystemC::Vregs ref
19             # {bits} Width of structure
20             # {words} Width of structure
21             # {inherits} Text inherits description
22             # {inherits_typeref} Inherits SystemC::Vregs::Type
23             # {inherits_level} Depth of inheritance
24             # {fields}{} SystemC::Vregs::Bit
25              
26             ######################################################################
27             # Accessors
28              
29             sub new {
30 7 50   7 1 10 my $class = shift; $class = ref $class if ref $class;
  7         13  
31 7         53 my $self = $class->SUPER::new(bitarray=>[],
32             attributes=>{},
33             inherits_level=>0,
34             subclass_level=>0,
35             @_);
36 7 50       24 $self->{pack} or die; # Should have been passed as parameter
37 7         21 $self->{pack}{types}{$self->{name}} = $self;
38 7         17 return $self;
39             }
40              
41             sub delete {
42 0     0 0 0 my $self = shift;
43 0 0       0 $self->{pack} or die;
44 0         0 $self->{deleted} = 1; # So can see in any dangling refs.
45 0         0 delete $self->{pack}{types}{$self->{name}};
46             }
47              
48             sub inherits {
49 14     14 1 23 my $self = shift;
50 14         16 my $val = shift;
51 14 100       35 if (defined ($val)) {
52 7         19 $self->{inherits} = $val;
53 7         12 ($self->{inherits} =~ s/^\s*:\s*//);
54 7         9 $self->{inherits_level} = 0;
55 7 100       18 $self->{inherits_level}++ if $self->{inherits} ne "";
56 7         20 $self->{inherits_level}++ while ($self->{inherits} =~ /:/g);
57             }
58 14         37 return $self->{inherits};
59             }
60              
61             sub find_bit {
62 0     0 0 0 my $self = shift;
63 0         0 my $name = shift;
64 0         0 return $self->{fields}{$name};
65             }
66              
67             sub attribute_value {
68 31     31 0 38 my $typeref = shift;
69 31         174 my $attr = shift;
70 31 50       80 return $typeref->{attributes}{$attr} if defined $typeref->{attributes}{$attr};
71 31 50 66     97 return $typeref->{inherits_typeref}{attributes}{$attr}
72             if (defined $typeref->{inherits_typeref}
73             && defined $typeref->{inherits_typeref}{attributes}{$attr});
74 31 50       98 return $typeref->{pack}{attributes}{$attr} if defined $typeref->{pack}{attributes}{$attr};
75 31         92 return undef;
76             }
77              
78             sub numbytes {
79 5     5 0 7 my $self = shift;
80 5         25 return int(($self->{numbits}+7)/8);
81             }
82              
83             ######################################################################
84              
85             sub dewildcard {
86 7     7 0 10 my $self = shift;
87              
88             # Expand any bit wildcards
89 7         7 foreach my $fieldref (values %{$self->{fields}}) {
  7         21  
90 24         52 $fieldref->dewildcard;
91             }
92              
93             # Expand type wildcards
94             #print ::Dumper($self);
95 7 50 50     47 return if (($self->{name}||"") !~ /\*/);
96 0 0       0 print "Type Wildcard ",$self->inherits(),"\n" if $SystemC::Vregs::Debug;
97 0         0 (my $regexp = $self->inherits()) =~ s/[*]/\.\*/g;
98 0         0 my $gotone;
99 0         0 foreach my $matchref ($self->{pack}->find_type_regexp("^$regexp")) {
100 0         0 $gotone = 1;
101 0         0 my $newname = SystemC::Vregs::three_way_replace
102             ($self->{name}, $self->inherits(), $matchref->{name});
103 0 0       0 print " Wildcarded $matchref->{name} to $newname\n" if $SystemC::Vregs::Debug;
104 0         0 my $newref = $self->new (pack=>$self->{pack},
105             name=>$newname,
106             at => $matchref->{at},
107             );
108 0         0 $newref->copy_attributes_from($matchref);
109 0         0 $newref->copy_attributes_from($self);
110 0         0 $newref->inherits($matchref->{name});
111             }
112 0 0       0 $gotone or $self->warn ("No types matching wildcarded type: ",$self->inherits(),"\n");
113 0         0 $self->delete();
114             }
115              
116             ######################################################################
117              
118             sub check_name {
119 7     7 0 16 my $self = shift;
120 7         17 my $field = $self->{name};
121 7 50       33 ($field =~ /^[A-Z][a-zA-Z0-9_]*$/)
122             or $self->warn ("Type names must match [capitals][alphanumerics]: $field\n");
123 7         19 ($self->{nor_name} = $field);
124             }
125              
126             our $_Check_Inherit_Notice = ("If using Product codes with wildcarded registers,\n"
127             ."add a specific Product=xyz attribute to the type definition\n");
128              
129             sub check_inherit {
130 7     7 0 12 my $typeref = shift;
131 7         22 my $inh = $typeref->inherits();
132 7 100       21 return if !$inh;
133 2         10 my $ityperef = $typeref->{pack}->find_type($inh);
134 2         6 $typeref->{inherits_typeref} = $ityperef;
135 2 50       7 if (!$ityperef) {
136 0         0 $typeref->warn ("Cannot find subclass definition: $inh\n"
137             .$_Check_Inherit_Notice);
138 0         0 $_Check_Inherit_Notice = "";
139 0         0 return;
140             }
141              
142             #print "INH $typeref->{name} $inh;\n";
143 2         6 for (my $bit=0; $bit<=$#{$typeref->{bitarray}}; $bit++) {
  2         12  
144 0 0       0 if (my $bitref = $typeref->{bitarray}[$bit]{bitref}) {
145 0 0       0 if (my $ibitref = $ityperef->{bitarray}[$bit]{bitref}) {
146 0         0 my $iname = $ityperef->{name} . "::" . $ibitref->{name};
147             #print " ib$bit $bitref->{name} $iname $ibitref->{overlaps}\n";
148 0 0       0 if ($bitref->{name} eq $ibitref->{name}) {
149 0 0       0 if ($bitref->{bits} ne $ibitref->{bits}) {
150 0         0 $bitref->warn("Bits $bitref->{bits} don't match $ibitref->{bits} inherited from $iname\n");
151 0         0 next;
152             }
153             } else {
154 0 0       0 if (!$bitref->is_overlap_ok($ibitref)) {
155 0         0 $bitref->warn("Bit $bit overlaps inherited $iname\n"
156             ."Perhaps you need a 'Overlaps $ibitref->{name}.' in $bitref->{name}'s description\n");
157             }
158             }
159             }
160             }
161             }
162             }
163              
164             sub check {
165 7     7 1 12 my $self = shift;
166             #print ::Dumper($self);
167 7         19 $self->check_name();
168 7         10 foreach my $fieldref (values %{$self->{fields}}) {
  7         25  
169 24         69 $fieldref->check();
170             }
171 7         25 $self->check_inherit();
172 7         22 foreach my $fieldref ($self->fields_sorted_inherited) {
173 29         82 $fieldref->computes_type($self);
174             }
175 7         27 $self->computes();
176             }
177              
178             sub remove_if_mismatch {
179 0     0 0 0 my $self = shift;
180 0         0 my $test_cb = shift;
181 0         0 my $rm=0; my $cnt=0;
  0         0  
182 0         0 foreach my $fieldref (values %{$self->{fields}}) {
  0         0  
183 0 0       0 $rm++ if $fieldref->remove_if_mismatch($test_cb);
184 0         0 $cnt++;
185             }
186 0 0 0     0 if ($test_cb->($self) || ($rm && $rm == $cnt)) {
      0        
187 0         0 $self->delete;
188             }
189             }
190              
191             sub computes {
192 7     7 0 11 my $typeref = shift;
193             # Create vector describing bit layout of the word
194 7         20 $typeref->_computes_words();
195 7         24 $typeref->_computes_inh_level_recurse(0);
196             #
197 7         15 my $mnem_vec = "";
198 7         13 my $last_bitref = 0;
199 7         9 my $x = 0;
200 7         33 for (my $bit=($typeref->{words}*$typeref->{pack}{word_bits})-1; $bit>=0; $bit--) {
201 480         714 my $bitent = $typeref->{bitarray}[$bit];
202 480 100       762 if (!defined $bitent) {
203 92         220 $x++;
204             } else {
205 388         563 my $bitref = $bitent->{bitref};
206 388 50       722 next if !$bitref;
207 388         558 my $bits = $bitref->{bits};
208 388         484 my $bit_mnem = $bitref->{name};
209 388         754 $bits =~ s/^w0//;
210 388 100       811 if ($last_bitref != $bitref) {
211 34 50       68 $mnem_vec .= sprintf "X[%d], ", $bit+1 if $x==1;
212 34 100       87 $mnem_vec .= sprintf "X[%d:%d], ", $bit+$x, $bit+1 if $x>1;
213 34         40 $x = 0;
214 34 50       91 $mnem_vec .= $bit_mnem . (($bits eq "") ? ", " : "$bits, ");
215             }
216 388         1054 $last_bitref = $bitref;
217             }
218             }
219 7         13 my $bit=-1;
220 7 50       19 $mnem_vec .= sprintf "X[%d], ", $bit+1 if $x==1;
221 7 50       16 $mnem_vec .= sprintf "X[%d:%d], ", $bit+$x, $bit+1 if $x>1;
222 7         29 $mnem_vec =~ s/, $//;
223 7         53 $typeref->{mnem_vec} = $mnem_vec;
224             }
225              
226             sub _computes_words {
227 7     7   10 my $self = shift;
228              
229 7         11 my $words = 0;
230 7         19 foreach my $bitref ($self->fields_sorted_inherited) {
231 29         34 foreach my $bit (@{$bitref->{bitlist}}) {
  29         63  
232 393         997 my $bitword = ((int($bit / $self->{pack}->data_bits)+1)
233             * $self->{pack}->data_bits/32);
234 393 100       1062 $words = $bitword if $words < $bitword;
235             }
236             }
237 7 50       25 if (my $numbits = $self->attribute_value('numbits')) {
238 0         0 $self->{words} = int(($numbits+31)/32);
239 0 0       0 $self->{words} = 1 if $self->{words}<1;
240 0         0 $self->{numbits} = $numbits;
241             } else { # Make a guess based on the fields used.
242 7         15 $self->{words} = $words;
243 7         19 $self->{numbits} = $words*32;
244             }
245             }
246              
247             sub _computes_inh_level_recurse {
248 9     9   12 my $self = shift;
249 9         10 my $level = shift;
250 9 50       25 if ($self->{subclass_level} > $level) {
251 0         0 $level = $self->{subclass_level};
252             }
253 9         15 $self->{subclass_level} = $level;
254             # If a class is a baseclass of this class, the baseclass needs bigger level.
255 9 100       25 if (my $ityperef = $self->{inherits_typeref}) {
256 2         9 $ityperef->_computes_inh_level_recurse($level+1);
257             }
258             # If a class is used as a field in this class, the used class needs bigger level.
259 9         25 foreach my $fieldref ($self->fields) {
260 32         105 my $ityperef = $fieldref->{pack}->find_type($fieldref->{type});
261 32 50       99 if ($ityperef) {
262 0         0 $ityperef->_computes_inh_level_recurse($level+1);
263             }
264             }
265             #print STDERR "LEVEL $self->{name} $level;\n";
266             }
267              
268             ######################################################################
269              
270             sub fields {
271 9     9 1 12 my $typeref = shift;
272 9         11 return (values %{$typeref->{fields}});
  9         33  
273             }
274              
275             sub fields_sorted {
276 0     0 0 0 my $typeref = shift;
277 0 0       0 return (sort {$b->{bitlist}[0] <=> $a->{bitlist}[0]
  0         0  
278             || $a->{name} cmp $b->{name}}
279 0         0 (values %{$typeref->{fields}}));
280             }
281              
282             sub fields_sorted_inherited {
283 14     14 0 18 my $typeref = shift;
284 14         14 my @flds = (values %{$typeref->{fields}});
  14         44  
285 14 100       42 if ($typeref->{inherits_typeref}) {
286 4         6 foreach my $fld (values %{$typeref->{inherits_typeref}->{fields}}) {
  4         14  
287 16 100       48 next if $typeref->{fields}{$fld->{name}}; # Inherited, but redefined in class.
288 10         25 push @flds, $fld;
289             }
290             }
291 14 50       46 return (sort {$b->{bitlist}[0] <=> $a->{bitlist}[0]
  84         228  
292             || $a->{name} cmp $b->{name}}
293             @flds);
294             }
295              
296             sub dump {
297 0     0 0   my $self = shift;
298 0   0       my $fh = shift || \*STDOUT;
299 0   0       my $indent = shift||" ";
300 0   0       print $fh +($indent,"Type: ",$self->{name},
301             " bits:",$self->{bits}||'',
302             "\n");
303 0           foreach my $fieldref (values %{$self->{fields}}) {
  0            
304 0           $fieldref->dump($fh,$indent." ");
305             }
306             }
307              
308             ######################################################################
309             #### Package return
310             1;
311             __END__