File Coverage

blib/lib/SystemC/Vregs/Define.pm
Criterion Covered Total %
statement 68 93 73.1
branch 17 30 56.6
condition 8 26 30.7
subroutine 15 19 78.9
pod n/a
total 108 168 64.2


line stmt bran cond sub pod time code
1             # See copyright, etc in below POD section.
2             ######################################################################
3              
4             package SystemC::Vregs::Define;
5 3     3   17 use SystemC::Vregs::Number;
  3         7  
  3         151  
6 3     3   15 use SystemC::Vregs::Subclass;
  3         5  
  3         60  
7 3     3   13 use Verilog::Language; # For value parsing
  3         5  
  3         54  
8              
9 3     3   14 use strict;
  3         4  
  3         101  
10 3     3   15 use vars qw ($VERSION);
  3         5  
  3         123  
11 3     3   17 use base qw (SystemC::Vregs::Subclass);
  3         7  
  3         371  
12             $VERSION = '1.470';
13              
14             #Fields:
15             # {name} Field name (Subclass)
16             # {at} File/line number (Subclass)
17             # {pack} Parent SystemC::Vregs ref
18             # {class} Parent SystemC::Vregs::Type ref
19             # {bits} Width or undef for unsized
20             # {desc} Description
21             # {rst} Reset value or 'X'
22             # {rst_val} {rst} as a hex value
23             # {sort_key} Order to output into file
24             # {is_manual} Created by user (vs from program)
25              
26             ######################################################################
27             ######################################################################
28             ######################################################################
29             ######################################################################
30             #### SystemC::Vregs::Define::Value
31              
32             package SystemC::Vregs::Define::Value;
33 3     3   16 use strict;
  3         5  
  3         279  
34 3     3   24 use base qw (SystemC::Vregs::Subclass);
  3         12  
  3         842  
35              
36             sub new {
37 4     4   7 my $class = shift;
38 4         17 my $self = $class->SUPER::new(@_);
39 4 50       16 $self->{pack} or die; # Should have been passed as parameter
40 4         21 $self->{pack}{defines}{$self->{name}} = $self;
41 4   33     245 $self->{sort_key} ||= '000000_' . $self->{name};
42 4         11 return $self;
43             }
44              
45             sub delete {
46 0     0   0 my $self = shift;
47             #print "DEST $self->{name}\n";
48 0         0 $self->{deleted} = 1; # So can see in any dangling refs.
49 0 0       0 if ($self->{pack}) {
50 0         0 delete $self->{pack}{defines}{$self->{name}};
51             }
52             }
53              
54             sub attribute_value {
55 8     8   12 my $self = shift;
56 8         10 my $attr = shift;
57 8 100       32 return $self->{attributes}{$attr} if defined $self->{attributes}{$attr};
58 4         10 return undef;
59             }
60              
61 3     3   17 use vars qw($_Defines_New_Push_Val);
  3         5  
  3         2744  
62             sub new_push {
63 0     0   0 my $class = shift;
64             # Like new, but add automatic to bottom of existing definitions
65 0         0 my $self = $class->new(@_);
66 0   0     0 $_Defines_New_Push_Val = ($_Defines_New_Push_Val||0) + 1;
67 0         0 $self->{sort_key} = sprintf("%06d_%s",$_Defines_New_Push_Val,$self->{name});
68 0         0 return $self;
69             }
70              
71             sub clean_desc {
72 4     4   4 my $self = shift;
73 4         23 $self->{desc} = $self->clean_sentence($self->{desc});
74 4 50       12 ($self->{desc}) or $self->warn("Empty description, please document it.\n");
75             }
76              
77             sub clean_rst {
78 4     4   5 my $self = shift;
79 4         7 my $field = $self->{rst};
80              
81 4 100       8 if ($self->attribute_value('freeform')) {
82             # Floating point number, etc, keep free-form
83 2         5 $self->{bits} = -1;
84             } else {
85 2         10 my $bits = Verilog::Language::number_bits ($field);
86 2 50       21 if (!$bits) { return $self->warn ("Number of bits in constant not specified: $field\n"); }
  0         0  
87 2         4 $self->{bits} = $bits;
88 2 100       20 if ($field =~ /\'s?h([0-9a-f_]+)$/i) {
89             # Prevent overflowing 32 bits by keeping the number in hex form
90 1         4 my $valhex = lc $1;
91 1         3 $valhex =~ s/_//g;
92 1         3 $self->{rst_val} = $valhex;
93             } else {
94 1         6 my $val = Verilog::Language::number_value ($field);
95 1 50       25 if (!defined $val) { return $self->warn ("Value of constant unparsable: $field\n"); }
  0         0  
96 1         6 $self->{rst_val} = sprintf("%x",$val);
97             }
98             }
99              
100             # Note Enum and Bit rst_vals are decimal, Define rst_vals are hex. Yuk.
101              
102 4         6 my $bits = $self->{bits};
103 4 50 33     16 if (defined $self->{class}{bits}
104             && ($self->{class}{bits} != $bits)) {
105 0         0 return $self->warn ("Define value doesn't match register width: $field != "
106             .$self->{class}{bits}."\n");
107             }
108 4         10 $self->{class}{bits} = $bits;
109              
110 4 50 66     63 if ($bits && $bits<32 && hex($self->{rst_val}||"0")>= (1<<$bits)) {
      100        
      66        
111 0         0 $self->warn ("Define value wider than width: ".$self->{rst}." > width "
112             .$self->{class}{bits}."\n");
113             }
114             }
115              
116             sub check_name {
117 4     4   5 my $self = shift;
118 4         6 my $field = $self->{name};
119 4 50       11 if ($self->{is_manual}) {
120 4 100       9 if ($self->attribute_value('allowlc')) {
121 2 50       14 if ($field !~ /^[a-zA-Z][a-zA-Z0-9_]*$/) {
122 0         0 return $self->warn ("Define field names must match [alpha][alphanumerics_]: $field\n");
123             }
124             } else {
125 2 50       14 if ($field !~ /^[A-Z][A-Z0-9_]*$/) {
126 0         0 return $self->warn ("Define field names must match [capital][capitalnumerics_]: $field\n");
127             }
128             }
129             }
130             }
131              
132             sub check {
133 4     4   5 my $self = shift;
134 4         9 $self->clean_desc();
135 4         9 $self->clean_rst();
136 4         10 $self->check_name();
137             }
138              
139             sub remove_if_mismatch {
140 0     0     my $self = shift;
141 0           my $test_cb = shift;
142 0 0         if ($test_cb->($self)) {
143 0           $self->delete;
144 0           return 1;
145             }
146 0           return undef;
147             }
148              
149             sub dump {
150 0     0     my $self = shift;
151 0   0       my $fh = shift || \*STDOUT;
152 0   0       my $indent = shift||" ";
153 0   0       print $fh +($indent,"Def: ",$self->{name},
      0        
      0        
154             " width:",$self->{bits}||'',
155             " rst:",$self->{rst}||'',
156             " rst_val:",$self->{rst_val}||'',
157             "\n");
158             }
159              
160             ######################################################################
161             #### Package return
162             1;
163             __END__