File Coverage

blib/lib/SystemC/Vregs.pm
Criterion Covered Total %
statement 102 358 28.4
branch 5 108 4.6
condition 4 85 4.7
subroutine 25 45 55.5
pod 14 26 53.8
total 150 622 24.1


line stmt bran cond sub pod time code
1             # See copyright, etc in below POD section.
2             ######################################################################
3              
4             package SystemC::Vregs;
5 3     3   90043 use SystemC::Vregs::Number;
  3         9  
  3         251  
6              
7 3     3   3230 use SystemC::Vregs::Enum;
  3         8  
  3         98  
8 3     3   3317 use SystemC::Vregs::Define;
  3         60  
  3         75  
9 3     3   1605 use SystemC::Vregs::Register;
  3         10  
  3         113  
10 3     3   21 use SystemC::Vregs::Number;
  3         4  
  3         130  
11 3     3   1782 use SystemC::Vregs::Rules;
  3         9  
  3         88  
12 3     3   1380 use SystemC::Vregs::Input::Layout;
  3         7  
  3         97  
13 3     3   1469 use SystemC::Vregs::Input::HTML;
  3         13  
  3         121  
14 3     3   1874 use SystemC::Vregs::Output::Layout;
  3         10  
  3         98  
15 3     3   17 use strict;
  3         6  
  3         92  
16 3     3   13 use Carp;
  3         4  
  3         155  
17 3         154 use vars qw ($Debug $VERSION
18 3     3   14 $Bit_Access_Regexp %Ignore_Keywords);
  3         3  
19 3     3   16 use base qw (SystemC::Vregs::Subclass); # In Vregs:: so we can get Vregs->warn()
  3         5  
  3         13714  
20              
21             $VERSION = '1.470';
22              
23             ######################################################################
24             #### Constants
25              
26             # Regexp matching valid bit access
27             $Bit_Access_Regexp = '^(RS?|)(WS?|W1CS?|H|)L?'."\$";
28              
29             # Loaded by user programs to prevent keyword warnings
30             %Ignore_Keywords = ();
31              
32             ######################################################################
33             ######################################################################
34             ######################################################################
35             ######################################################################
36             #### Creation
37              
38             #Fields:
39             # {name} Field name (Subclass)
40             # {at} File/line number (Subclass)
41             # {address_bits}
42             # {word_bits}
43             # {rebuild_comment}
44             # {attributes}{}{}
45             # {libraries}[] SystemC::Vregs ref
46             # {rules} SystemC::Vregs::Rules ref
47             # {enums}{} SystemC::Vregs::Enum ref
48             # {types}{} SystemC::Vregs::Type ref
49             # {regs}{} SystemC::Vregs::Regs ref
50             # {defines}{} SystemC::Vregs::Define ref
51              
52             sub new {
53 1     1 1 487 my $class = shift;
54 1         11 my $self = {address_bits => 32,
55             word_bits => 32, # Changing this isn't verified (change data_bits attribute instead)
56             rebuild_comment => undef,
57             attributes => {
58             # v2k => 0, # Use localparam instead of parameter
59             },
60             comments => 1,
61             protect_rdwr_only => 1,
62             @_};
63 1         3 bless $self, $class;
64 1         11 $self->{rules} = new SystemC::Vregs::Rules (package => $self, );
65             # Calculations
66 1         6 $self->{data_bytes} = $self->{word_bits}/8;
67 1         5 return $self;
68             }
69              
70             sub data_bits {
71 786     786 0 858 my $self = shift;
72 786   50     1376 return $self->attribute_value("data_bits")||32;
73             }
74              
75             sub addr_text_to_vec {
76 10     10 0 15 my $self = shift;
77 10         14 my $text = shift;
78 10         27 return SystemC::Vregs::Number::text_to_vec
79             ($self->{address_bits}, $text);
80             }
81              
82             sub addr_const_vec {
83 25     25 0 30 my $self = shift;
84 25         30 my $num = shift;
85 25         210 return Bit::Vector->new_Dec($self->{address_bits}, $num);
86             }
87              
88             ######################################################################
89             #### Access
90              
91             sub find_define {
92 0     0 1 0 my $pack = shift;
93 0         0 my $name = shift;
94 0         0 foreach my $packref ($pack, @{$pack->{libraries}}) {
  0         0  
95 0         0 my $regref = $packref->{defines}{$name};
96 0 0       0 return $regref if $regref;
97             }
98 0         0 return undef;
99             }
100             sub find_enum {
101 12     12 1 18 my $pack = shift;
102 12         17 my $name = shift;
103 12         14 foreach my $packref ($pack, @{$pack->{libraries}}) {
  12         34  
104 12         22 my $enumref = $packref->{enums}{$name};
105 12 50       45 return $enumref if $enumref;
106             }
107 0         0 return undef;
108             }
109             sub find_type {
110 34     34 1 40 my $pack = shift;
111 34         48 my $name = shift;
112 34         36 foreach my $packref ($pack, @{$pack->{libraries}}) {
  34         65  
113 34         61 my $typeref = $packref->{types}{$name};
114 34 100       111 return $typeref if $typeref;
115             }
116 32         82 return undef;
117             }
118             sub find_type_regexp {
119 0     0 1 0 my $pack = shift;
120 0         0 my $regexp = shift;
121 0         0 my @list;
122 0         0 foreach my $packref ($pack, @{$pack->{libraries}}) {
  0         0  
123 0         0 foreach my $matchref (values %{$packref->{types}}) {
  0         0  
124 0 0       0 if ($matchref->{name} =~ /$regexp/) {
125 0         0 push @list, $matchref;
126             }
127             }
128             }
129 0         0 return @list;
130             }
131             sub find_reg {
132 0     0 0 0 my $pack = shift;
133 0         0 my $name = shift;
134 0         0 foreach my $packref ($pack, @{$pack->{libraries}}) {
  0         0  
135 0         0 my $regref = $packref->{regs}{$name};
136 0 0       0 return $regref if $regref;
137             }
138 0         0 return undef;
139             }
140             sub find_reg_regexp {
141 0     0 0 0 my $pack = shift;
142 0         0 my $regexp = shift;
143 0         0 my @list;
144 0         0 foreach my $packref ($pack, @{$pack->{libraries}}) {
  0         0  
145 0         0 foreach my $matchref (values %{$packref->{regs}}) {
  0         0  
146 0 0       0 if ($matchref->{name} =~ /$regexp/) {
147 0         0 push @list, $matchref;
148             }
149             }
150             }
151 0         0 return @list;
152             }
153              
154             sub regs_sorted {
155 0     0 1 0 my $pack = shift;
156 0 0 0     0 return (sort {(defined $a->{addr} && defined $b->{addr} && $a->{addr}->Lexicompare($b->{addr}))
  0 0 0     0  
      0        
      0        
157             || ( (defined $a->{addr} && !defined $b->{addr}) ? 1:0) # IE any# > undef
158             || $a->{name} cmp $b->{name}}
159 0         0 (values %{$pack->{regs}}));
160             }
161             sub types_sorted {
162 2     2 1 4 my $pack = shift;
163 26 50 100     189 return (sort {($b->{subclass_level} <=> $a->{subclass_level})
  2         19  
164             || ($a->{inherits_level} <=> $b->{inherits_level})
165             || ($a->{name} cmp $b->{name})}
166 2         4 (values %{$pack->{types}}));
167             }
168             sub enums_sorted {
169 1     1 1 2 my $pack = shift;
170 1         8 return (sort {$a->{name} cmp $b->{name}}
  1         9  
171 1         2 (values %{$pack->{enums}}));
172             }
173             sub defines_sorted {
174 1     1 1 2 my $pack = shift;
175 5         13 return (sort {$a->{sort_key} cmp $b->{sort_key}}
  1         7  
176 1         3 (values %{$pack->{defines}}));
177             }
178              
179             sub attribute_value {
180 786     786 0 859 my $self = shift;
181 786         923 my $attr = shift;
182 786 50       1809 return $self->{attributes}{$attr} if defined $self->{attributes}{$attr};
183 786         4397 return undef;
184             }
185              
186             ######################################################################
187             #### html parsing
188              
189             sub html_read {
190 0     0 1 0 my $self = shift;
191 0         0 my $filename = shift;
192              
193 0         0 SystemC::Vregs::Input::HTML->new()->read
194             (pack => $self,
195             filename => $filename);
196             }
197              
198             sub three_way_replace {
199 0     0 0 0 my $orig_name = shift;
200 0         0 my $orig_inh = shift;
201 0         0 my $sub_name = shift;
202             # Take "FOO*", "BAR*", and "BARBAZ" and return "FOOBAZ"
203              
204 0 0       0 $orig_name =~ /^([^*]*)[*]$/ or die "%Error: Missing * in original name: $orig_name";
205 0         0 my $orig_name_prefix = $1;
206 0 0       0 $orig_inh =~ /^([^*]*)[*]$/ or die "%Error: Missing * in inherit name: $orig_inh";
207 0         0 my $orig_inh_prefix = $1;
208 0         0 my $new_name = substr($sub_name,length($orig_inh_prefix));
209 0         0 return ($orig_name_prefix . $new_name);
210             }
211              
212             ######################################################################
213             #### Reading files
214              
215             sub regs_read {
216 1     1 1 311 my $self = shift;
217 1         3 my $filename = shift;
218              
219 1         11 SystemC::Vregs::Input::Layout->new()->read
220             (pack => $self,
221             filename => $filename);
222             }
223              
224             sub regs_read_check {
225 0     0 1 0 my $self = shift;
226 0         0 $self->regs_read(@_);
227 0         0 $self->check();
228 0         0 $self->exit_if_error();
229             }
230              
231             sub rules_read {
232 0     0 0 0 my $self = shift;
233 0         0 my $filename = shift;
234 0 0       0 $self->{rules}->read ($filename) if -r $filename;
235             }
236              
237             ######################################################################
238             #### Checks/Cleanups
239              
240             sub check {
241 1     1 1 363 my $self = shift;
242              
243             # Eliminate wildcarding
244 1         2 foreach my $typeref (values %{$self->{types}}) {
  1         4  
245 7         20 $typeref->dewildcard();
246             }
247 1         3 foreach my $regref (values %{$self->{regs}}) {
  1         3  
248 3         10 $regref->dewildcard();
249             }
250              
251             # Check enums first; type checking requires enums
252 1         5 foreach my $defref ($self->defines_sorted) {
253 4         12 $defref->check();
254             }
255 1         3 foreach my $enumref (values %{$self->{enums}}) {
  1         3  
256 2         10 $enumref->check();
257             }
258             # Sorted, as we want to do base classes first
259 1         7 foreach my $typeref ($self->types_sorted) {
260 7         29 $typeref->check();
261             }
262 1         4 foreach my $regref (values %{$self->{regs}}) {
  1         6  
263 3         22 $regref->check();
264             }
265             #use Data::Dumper; print Dumper($self);
266             }
267              
268             ######################################################################
269             #### Masking
270              
271             sub remove_if_mismatch {
272 0     0 0   my $self = shift;
273 0   0 0     my $test_cb = shift || sub { return $self->is_mismatch($_[0]); }; # Default cb
  0            
274 0 0         print "remove_if_mismatch($test_cb)\n" if $Debug;
275 0           foreach my $typeref ($self->types_sorted) {
276 0           $typeref->remove_if_mismatch($test_cb);
277             }
278 0           foreach my $regref ($self->regs_sorted) { # Must do types before regs
279 0           $regref->remove_if_mismatch($test_cb);
280             }
281 0           foreach my $enumref ($self->enums_sorted) {
282 0           $enumref->remove_if_mismatch($test_cb);
283             }
284 0           foreach my $defref ($self->defines_sorted) {
285 0           $defref->remove_if_mismatch($test_cb);
286             }
287             }
288              
289             sub is_mismatch {
290 0     0 0   my $self = shift;
291 0           my $itemref = shift;
292             # Called by each object, return true if there's a mismatch
293 0           my $mismatch;
294 0 0         if (my $prod = $self->{if_product}) {
295 0 0         if (my $itemprod = $itemref->attribute_value("Product")) {
296 0           $prod = lc $prod;
297 0           $itemprod = lc $itemprod;
298             #print "Prod check $prod =? $itemprod for $self->{name}\n";
299 0 0         if ($itemprod =~ /(.*)\+$/) {
300 0           $mismatch = $prod lt $1;
301             } else {
302 0           $mismatch = $prod ne $itemprod;
303             }
304 0 0 0       print " ProductMismatch: deleting $itemref->{name}\n" if $mismatch && $Debug;
305             }
306             }
307 0           return $mismatch;
308             }
309              
310             ######################################################################
311             ######################################################################
312             #### Defines
313              
314             sub _force_mask {
315 0     0     my $pack = shift;
316 0           my $mask = shift;
317             # Return new mask which assumes power-of-2 alignment of all registers
318 0           my $bit;
319 0           for ($bit=$pack->{address_bits}-1; $bit>=1; --$bit) { # Ignore bits 1&0
320 0 0         if ($mask->bit_test($bit)) {
321 0           last;
322             }
323             }
324 0           for (; $bit>=0; --$bit) {
325 0           $mask->Bit_On($bit);
326             }
327 0           return $mask;
328             }
329              
330             sub _valid_mask {
331 0     0     my $pack = shift;
332 0           my $addr = shift;
333 0           my $mask = shift;
334              
335             # if (($addr & ~$mask) != $addr)
336 0           my $a = Bit::Vector->new($pack->{address_bits});
337 0           my $b = Bit::Vector->new($pack->{address_bits});
338 0           $a->Complement($mask);
339 0           $b->Intersection($a,$addr);
340 0 0         return 0 if !$b->equal($addr);
341              
342 0           my $one = 1;
343 0           for (my $bit=0; $bit<$pack->{address_bits}; $bit++) {
344 0 0         if ($mask->bit_test($bit)) {
345 0 0         return 0 if !$one;
346             } else {
347 0           $one = 0;
348             }
349             }
350 0           return 1;
351             }
352              
353             sub SystemC::Vregs::Type::_create_defines {
354 0     0     my $typeref = shift;
355 0 0         return if $typeref->attribute_value("nofielddefines");
356              
357             # Make size alias
358 0           (my $nor_mnem = $typeref->{name}) =~ s/^R_//;
359 0           new_push SystemC::Vregs::Define::Value
360             (pack => $typeref->{pack},
361             name => "CSIZE_".$nor_mnem,
362             rst_val => $typeref->{words}*$typeref->{pack}{data_bytes},
363             is_verilog => 1, # In C++ use Class::SIZE
364             is_perl => 1,
365             desc => "Class Size", );
366              
367 0 0         if ($typeref->{name} =~ /^R_/) {
368 0           for (my $word=0; $word<$typeref->{words}; $word++) {
369 0           my $wr_mask = 0;
370 0           for (my $bit=$word*$typeref->{pack}->{word_bits};
371             $bit<(($word+1)*$typeref->{pack}->{word_bits});
372             $bit++) {
373 0           my $bitent = $typeref->{bitarray}[$bit];
374 0 0         next if !$bitent;
375 0 0         $wr_mask |= (1<<($bit % $typeref->{pack}->{word_bits})) if ($bitent->{write});
376             }
377 0 0         my $wd=""; $wd=$word if $word;
  0            
378 0           new_push SystemC::Vregs::Define::Value
379             (pack => $typeref->{pack},
380             name => "CM${wd}_".$nor_mnem."_WRITABLE",
381             rst_val => sprintf("%08X",$wr_mask,),
382             bits=>$typeref->{pack}->{word_bits},
383             is_verilog => 1, # In C++ use Class::BITMASK_WRITABLE
384             desc => "Writable mask", );
385             }
386             }
387              
388             # Make bit alias
389 0           foreach my $bitref ($typeref->fields_sorted) {
390 0 0         next if $bitref->ignore;
391             { # Wide-word defines
392 0 0         my $rnum = 0; $rnum = 1 if $#{$bitref->{bitlist_range}};
  0            
  0            
  0            
393 0           foreach my $bitrange (reverse @{$bitref->{bitlist_range}}) {
  0            
394 0           $bitref->_create_defines_range ($typeref, $bitrange, $rnum++, 1);
395             }
396             }
397              
398             # Multi-word defines
399 0 0         if ($typeref->{words}>1) {
400 0 0         my $rnum = 0; $rnum = 1 if $#{$bitref->{bitlist_range_32}};
  0            
  0            
401 0           foreach my $bitrange (reverse @{$bitref->{bitlist_range_32}}) {
  0            
402 0           $bitref->_create_defines_range ($typeref, $bitrange, $rnum++, 0);
403             }
404             }
405             }
406             }
407              
408             sub SystemC::Vregs::Bit::_create_defines_range {
409 0     0     my $bitref = shift;
410 0           my $typeref = shift;
411 0           my $bitrange = shift;
412 0           my $rnum = shift;
413 0           my $wideword = shift;
414              
415 0           my ($msb,$lsb,$nbits,$srcbit) = @{$bitrange};
  0            
416 0           my $bit_mnem = $bitref->{name};
417 0           my $comment = $bitref->{comment};
418 0           (my $nor_mnem = $typeref->{name}) =~ s/^R_//;
419              
420             # For multi-ranged fields, we append a _1 for the first range, _2, ...
421 0 0         my $rstr = ""; $rstr = "_".$rnum if $rnum;
  0            
422              
423             # For multi-word structures, make verilog defines that include
424             # the word number, and subtract 32* that value. This allows for
425             # easy extraction using multiple busses and/or multi-cycle transactions.
426 0           for (my $word=-1; $word<$typeref->{words}; $word++) {
427             # word=-1 indicates we are making the wide structure
428 0 0 0       next if $word==-1 && !$wideword;
429 0 0 0       next if $word!=-1 && $wideword;
430 0 0         my $wstr = ""; $wstr = $word if $word>=0;
  0            
431              
432             # If a single field in word #0, CR0_ would be the same as a CR_, so suppress
433 0 0 0       next if $msb<32 && $word!=-1 && $rnum==0;
      0        
434              
435 0 0 0       if ($word==-1
      0        
      0        
      0        
436             || ($msb>=($word*32) && $msb<($word*32+32))
437             || ($lsb>=($word*32) && $lsb<($word*32+32))) {
438 0           my $wlsb = $lsb;
439 0           my $wmsb = $msb;
440 0 0         $wlsb -= $word*32 if $word!=-1;
441 0 0         $wmsb -= $word*32 if $word!=-1;
442              
443 0           new_push SystemC::Vregs::Define::Value
444             (pack => $typeref->{pack},
445             name => "CR${wstr}_".$nor_mnem."_".$bit_mnem.$rstr,
446             rst_val => $wmsb.":".$wlsb,
447             is_verilog => 1,
448             desc => "Field Bit Range: $comment",
449             desc_trivial => 1,);
450 0           new_push SystemC::Vregs::Define::Value
451             (pack => $typeref->{pack},
452             name => "CB${wstr}_".$nor_mnem."_".$bit_mnem.$rstr,
453             rst_val => $wlsb,
454             desc => "Field Start Bit: $comment",
455             desc_trivial => 0,);
456 0           new_push SystemC::Vregs::Define::Value
457             (pack => $typeref->{pack},
458             name => "CE${wstr}_".$nor_mnem."_".$bit_mnem.$rstr,
459             rst_val => $wmsb,
460             desc => "Field End Bit: $comment",
461             desc_trivial => 1,);
462 0 0 0       if ($wstr eq "" && $typeref->{attributes}{macros_32_bits}) {
463 0           new_push SystemC::Vregs::Define::Value
464             (pack => $typeref->{pack},
465             name => "CBSZ${wstr}_".$nor_mnem."_".$bit_mnem.$rstr,
466             rst_val => $wmsb - $wlsb + 1,
467             desc => "Field Bit Size: $comment",
468             desc_trivial => 1,);
469             }
470             }
471             }
472 0           for (my $bitwidth=8; $bitwidth<=256; $bitwidth *=2) {
473 0           my $bitword = int($lsb/$bitwidth);
474 0           my $wlsb = $lsb - $bitword*$bitwidth;
475 0           my $wmsb = $msb - $bitword*$bitwidth;
476 0 0         if ($typeref->{attributes}{"macros_${bitwidth}_bits"}) {
477 0           new_push SystemC::Vregs::Define::Value
478             (pack => $typeref->{pack},
479             name => "CRW${bitwidth}_".$nor_mnem."_".$bit_mnem.$rstr,
480             rst_val => $wmsb.":".$wlsb,
481             is_verilog => 1,
482             desc => "Field Bit Range for ${bitwidth}-bit extracts",
483             desc_trivial => 1,);
484 0           new_push SystemC::Vregs::Define::Value
485             (pack => $typeref->{pack},
486             name => "CAW${bitwidth}_".$nor_mnem."_".$bit_mnem.$rstr,
487             rst_val => $bitword,
488             desc => "Field Word Number for ${bitwidth}-bit extracts",
489             desc_trivial => 1,);
490             }
491             }
492 0 0 0       if (($bitref->{numbits}>1 || $typeref->attribute_value("creset_one_bit"))
      0        
      0        
493             && ($bitref->{rst_val}
494             || ($typeref->attribute_value("creset_zero")
495             && (defined $bitref->{rst_val})))) {
496 0           new_push SystemC::Vregs::Define::Value
497             (pack => $typeref->{pack},
498             name => "CRESET_${nor_mnem}_${bit_mnem}",
499             rst_val => sprintf("%x",$bitref->{rst_val}),
500             bits => $bitref->{numbits},
501             is_verilog => 1,
502             desc => "Field Reset",
503             desc_trivial => 1,);
504             }
505             }
506              
507             sub SystemC::Vregs::Enum::_create_defines {
508 0     0     my $self = shift;
509              
510 0           foreach my $fieldref ($self->fields_sorted()) {
511 0           new_push SystemC::Vregs::Define::Value
512             (pack => $self->{pack},
513             name => "E_".$self->{name}."_".$fieldref->{name},
514             bits => $fieldref->{bits},
515             rst_val => sprintf("%x",$fieldref->{rst_val}),
516             desc => "Enum Value: $fieldref->{desc}",
517             desc_trivial => 0,);
518             }
519             }
520              
521             sub create_defines {
522 0     0 0   my $pack = shift;
523 0           my $skip_if_done = shift;
524             # Make define addresses
525              
526 0 0 0       return if ($skip_if_done && $pack->{defines_computed});
527 0           $pack->{defines_computed} = 1;
528              
529 0           my $bit4 = $pack->addr_const_vec($pack->{data_bytes});
530 0           my $bit32 = $pack->addr_const_vec(0xffffffff);
531              
532 0           foreach my $regref ($pack->regs_sorted()) {
533 0           my $classname = $regref->{name};
534 0           (my $nor_mnem = $classname) =~ s/^R_//;
535 0           my $addr = $regref->{addr};
536 0           my $spacing = $regref->{spacing};
537 0           my $range = $regref->{range};
538 0           my $range_high = $regref->{range_high};
539 0           my $range_low = $regref->{range_low};
540              
541 0   0       my $nofields = ($regref->attribute_value("nofielddefines")
542             || $regref->{typeref}->attribute_value("nofielddefines"));
543              
544             # Make master alias
545 0           new_push SystemC::Vregs::Define::Value
546             (pack => $pack,
547             name => "RA_".$nor_mnem,
548             val => $addr,
549             rst_val => $addr->to_Hex, bits => $pack->{address_bits},
550             desc => "Address of $classname",
551             desc_trivial => 1,);
552              
553 0 0 0       if ($range ne "" || 1) {
554 0           new_push SystemC::Vregs::Define::Value
555             (pack => $pack,
556             name => "RAE_".$nor_mnem,
557             rst_val => $regref->{addr_end}->to_Hex,
558             bits => $pack->{address_bits},
559             desc => "Ending Address of Register + 1",
560             desc_trivial => 1,);
561              
562 0 0         if (!$nofields) {
563 0 0         new_push SystemC::Vregs::Define::Value
564             (pack => $pack,
565             name => "RAC_".$nor_mnem,
566             rst_val => $regref->{range_ents},
567             bits => (($regref->{range_ents}->Lexicompare($bit32) > 0)
568             ? $pack->{address_bits} : 32),
569             desc => "Number of entries",
570             desc_trivial => 1,);
571             }
572              
573 0 0 0       if (! $regref->{spacing}->equal($bit4)
574             && !$nofields) {
575 0           new_push SystemC::Vregs::Define::Value
576             (pack => $pack,
577             name => "RRP_".$nor_mnem,
578             rst_val => $regref->{spacing}->to_Hex,
579             bits => $pack->{address_bits},
580             desc => "Range spacing",
581             desc_trivial => 1,);
582             }
583             }
584              
585 0 0 0       if (!$nofields
      0        
586             && ($range ne ""
587             || ($regref->{typeref}{words}>1
588             && $regref->{typeref}{words} > ($pack->data_bits / 32)))) {
589 0           my $wordspace = $regref->{pack}->addr_const_vec($regref->{typeref}{words}*4);
590 0 0         if ($regref->{spacing}->equal($wordspace)) {
591 0           my $val = Bit::Vector->new($regref->{pack}{address_bits});
592 0           $val->subtract($regref->{addr_end},$addr,0); #end-start
593 0 0         new_push SystemC::Vregs::Define::Value
594             (pack => $pack,
595             name => "RRS_".$nor_mnem,
596             rst_val => $val->to_Hex,
597             bits => (($val != 0) ? $pack->{address_bits} : 32),
598             desc => "Range byte size",
599             desc_trivial => 1,);
600             } else {
601 0           new_push SystemC::Vregs::Define::Value
602             (pack => $pack,
603             name => "RRS_".$nor_mnem,
604             rst_val => "Non_Contiguous",
605             desc => "Range byte size: This register region contains gaps.",
606             desc_trivial => 0,);
607             }
608              
609 0           my $delta = Bit::Vector->new($regref->{pack}{address_bits});
610 0           $delta->subtract($regref->{addr_end},$addr,1); #end-start-1
611 0 0         if (_valid_mask ($pack, $addr, $delta)) {
612 0           new_push SystemC::Vregs::Define::Value
613             (pack => $pack,
614             name => "RAM_".$nor_mnem,
615             rst_val => $delta->to_Hex,
616             bits => $pack->{address_bits},
617             desc => "Address Mask",
618             desc_trivial => 1,);
619             } else {
620             # We could just leave it out, but that leads to a lot of "bug"
621             # reports about the define being missing!
622 0           new_push SystemC::Vregs::Define::Value
623             (pack => $pack,
624             name => "RAM_".$nor_mnem,
625             rst_val => "Not_Aligned",
626             desc => "Address Mask: This register is not naturally aligned, so a mask will not work.",
627             desc_trivial => 0,);
628             }
629             }
630              
631             # If small range, make a alias per range
632 0 0 0       if (!$nofields
      0        
633             && $range ne ""
634             && $regref->{range_ents} < 17) {
635 0           for (my $range_val=$range_low; $range_val <= $range_high; $range_val++) {
636 0           my $range_addr = Bit::Vector->new_Dec($regref->{pack}{address_bits},
637             $regref->{spacing} * $range_val);
638 0           $range_addr->add($regref->{addr}, $range_addr, 0);
639 0           new_push SystemC::Vregs::Define::Value
640             (pack => $pack,
641             name => "RA_".$nor_mnem.$range_val,
642             val => $range_addr,
643             rst_val => $range_addr->to_Hex,
644             bits => $regref->{pack}{address_bits},
645             desc => "Address of Entry ${classname}${range_val}",
646             desc_trivial => 0,);
647             }
648             }
649             }
650              
651 0           my %moddef = ();
652 0           foreach my $regref ($pack->regs_sorted()) {
653 0           my $classname = $regref->{name};
654 0           (my $nor_mnem = $classname) =~ s/^R_//;
655 0           for (my $str=$nor_mnem; $str=~s/[A-Z][a-z0-9_]*$//;) {
656             #print "$nor_mnem\t$str\t",$regref->{addr},"\n";
657 0 0         next if $str eq "";
658 0           $moddef{$str}{count}++;
659 0           $moddef{$str}{addr}
660             = SystemC::Vregs::Number::min($moddef{$str}{addr},$regref->{addr});
661 0           $moddef{$str}{addr_end}
662             = SystemC::Vregs::Number::max($moddef{$str}{addr_end},$regref->{addr_end});
663             }
664             }
665              
666 0           foreach my $nor_mnem (sort (keys %moddef)) {
667 0           my $modref = $moddef{$nor_mnem};
668 0 0         next if $modref->{count} < 2;
669 0           my $addr = $modref->{addr};
670 0           my $addr_end = $modref->{addr_end};
671             #print "$nor_mnem\t$addr\t$addr_end\n";
672              
673             # Make master alias
674 0           new_push SystemC::Vregs::Define::Value
675             (pack => $pack,
676             name => "RBASEA_".$nor_mnem,
677             val => $addr,
678             rst_val => $addr->to_Hex, bits => $pack->{address_bits},
679             desc => "Base address of $nor_mnem registers",
680             desc_trivial => 1,);
681 0           new_push SystemC::Vregs::Define::Value
682             (pack => $pack,
683             name => "RBASEAE_".$nor_mnem,
684             val => $addr_end,
685             rst_val => $addr_end->to_Hex, bits => $pack->{address_bits},
686             desc => "Ending base address of $nor_mnem registers",
687             desc_trivial => 1,);
688 0           my $delta = Bit::Vector->new($pack->{address_bits});
689 0           $delta->subtract($modref->{addr_end},$addr,1); #end-start-1
690 0           $delta = _force_mask ($pack, $delta);
691 0           new_push SystemC::Vregs::Define::Value
692             (pack => $pack,
693             name => "RBASEAM_".$nor_mnem,
694             rst_val => $delta->to_Hex,
695             bits => $pack->{address_bits},
696             desc => "Address Mask (may be forced to power-of-two)",
697             desc_trivial => 1,);
698             }
699              
700 0           foreach my $typeref ($pack->types_sorted) {
701 0           $typeref->_create_defines();
702             }
703              
704 0           foreach my $classref ($pack->enums_sorted) {
705 0           $classref->_create_defines();
706             }
707             }
708              
709             ######################################################################
710             ######################################################################
711             #### Diags
712              
713             sub dump {
714 0     0 0   my $self = shift;
715 0   0       my $fh = shift || \*STDOUT;
716 0   0       my $indent = shift||" ";
717 0           print $fh $indent,"Pack: ",$self->{name},"\n";
718 0           foreach my $typeref (values %{$self->{types}}) {
  0            
719 0           $typeref->dump($fh,$indent." ");
720             }
721 0           foreach my $regref (values %{$self->{regs}}) {
  0            
722 0           $regref->dump($fh,$indent." ");
723             }
724 0           foreach my $enumref (values %{$self->{enums}}) {
  0            
725 0           $enumref->dump($fh,$indent." ");
726             }
727 0           foreach my $defref ($self->defines_sorted) {
728 0           $defref->dump($fh,$indent." ");
729             }
730             }
731              
732             ######################################################################
733             ######################################################################
734             #### Saving
735              
736             sub regs_write {
737             # Dump register definitions
738 0     0 1   my $self = shift;
739 0           my $filename = shift;
740 0           return SystemC::Vregs::Output::Layout->new->write
741             (filename => $filename,
742             keep_timestamp => 1,
743             pack => $self,
744             );
745             }
746              
747             ######################################################################
748             #### Package return
749             package Vregs;
750             1;
751             __END__