line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# See copyright, etc in below POD section. |
2
|
|
|
|
|
|
|
###################################################################### |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
package SystemC::Vregs::Input::HTML; |
5
|
3
|
|
|
3
|
|
14
|
use Carp; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
161
|
|
6
|
3
|
|
|
3
|
|
13
|
use strict; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
78
|
|
7
|
|
|
|
|
|
|
|
8
|
3
|
|
|
3
|
|
1267
|
use SystemC::Vregs::Input::TableExtract; |
|
3
|
|
|
|
|
10
|
|
|
3
|
|
|
|
|
32
|
|
9
|
3
|
|
|
3
|
|
156
|
use vars qw($VERSION $Debug); |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
11360
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
$VERSION = '1.470'; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
###################################################################### |
14
|
|
|
|
|
|
|
# CONSTRUCTOR |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub new { |
17
|
0
|
|
|
0
|
1
|
|
my $class = shift; |
18
|
0
|
|
|
|
|
|
my $self = {@_}; |
19
|
0
|
|
|
|
|
|
bless $self, $class; |
20
|
0
|
|
|
|
|
|
return $self; |
21
|
|
|
|
|
|
|
} |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
###################################################################### |
24
|
|
|
|
|
|
|
# Reading |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub read { |
27
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
28
|
0
|
|
|
|
|
|
my %params = (#filename => |
29
|
|
|
|
|
|
|
#pack => |
30
|
|
|
|
|
|
|
@_); |
31
|
0
|
0
|
|
|
|
|
my $pack = $params{pack} or croak "%Error: No pack=> parameter passed,"; |
32
|
0
|
|
|
|
|
|
$self->{pack} = $pack; |
33
|
|
|
|
|
|
|
# Dump headers for class name based accessors |
34
|
|
|
|
|
|
|
|
35
|
0
|
|
|
|
|
|
my $te = new SystemC::Vregs::Input::TableExtract(depth=>0, ); |
36
|
0
|
|
|
|
|
|
$te->{_vregs_inp} = $self; |
37
|
0
|
|
|
|
|
|
$te->parse_file($params{filename}); |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
###################################################################### |
41
|
|
|
|
|
|
|
# Callbacks from table extract |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
sub new_item { |
44
|
0
|
|
|
0
|
0
|
|
my $self = $_[0]; |
45
|
0
|
|
|
|
|
|
my $bittableref = $_[1]; |
46
|
0
|
|
|
|
|
|
my $flagref = $_[2]; # Hash of {heading} = value_of_heading |
47
|
|
|
|
|
|
|
#Create a new register/class/enum, called from the html parser |
48
|
0
|
0
|
|
|
|
|
print "new_item:",::Dumper(\$flagref, $bittableref) if $SystemC::Vregs::Input::TableExtract::Debug; |
49
|
|
|
|
|
|
|
|
50
|
0
|
0
|
|
|
|
|
if ($flagref->{Register}) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
51
|
0
|
|
|
|
|
|
new_register (@_); |
52
|
|
|
|
|
|
|
} elsif ($flagref->{Class}) { |
53
|
0
|
|
|
|
|
|
new_register (@_); |
54
|
|
|
|
|
|
|
} elsif ($flagref->{Enum}) { |
55
|
0
|
|
|
|
|
|
new_enum (@_); |
56
|
|
|
|
|
|
|
} elsif (defined $flagref->{Defines}) { # Name not required, so defined. |
57
|
0
|
|
|
|
|
|
new_define (@_); |
58
|
|
|
|
|
|
|
} elsif ($flagref->{Package}) { |
59
|
0
|
|
|
|
|
|
new_package (@_); |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub new_package { |
64
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
65
|
0
|
|
|
|
|
|
my $bittableref = shift; my @bittable = @{$bittableref}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
66
|
0
|
|
|
|
|
|
my $flagref = shift; # Hash of {heading} = value_of_heading |
67
|
|
|
|
|
|
|
# Create a new package |
68
|
0
|
|
|
|
|
|
my $pack = $self->{pack}; |
69
|
|
|
|
|
|
|
|
70
|
0
|
0
|
|
|
|
|
($flagref->{Package}) or die; |
71
|
0
|
0
|
|
|
|
|
(!$self->{_got_package_decl}) or return $pack->warn($flagref, "Multiple Package attribute sections, previous at $self->{_got_package_decl}.\n"); |
72
|
|
|
|
|
|
|
|
73
|
0
|
|
0
|
|
|
|
my $attr = $flagref->{Attributes}||""; |
74
|
0
|
0
|
|
|
|
|
print "PACK ATTR $attr\n" if $Debug; |
75
|
0
|
|
|
|
|
|
$pack->attributes_parse($attr); |
76
|
0
|
|
|
|
|
|
$self->{_got_package_decl} = $flagref->{at}; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub new_define { |
80
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
81
|
0
|
|
|
|
|
|
my $bittableref = shift; my @bittable = @{$bittableref}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
82
|
0
|
|
|
|
|
|
my $flagref = shift; # Hash of {heading} = value_of_heading |
83
|
|
|
|
|
|
|
# Create a new enumeration |
84
|
0
|
0
|
|
|
|
|
return if $#bittable<0; # Empty list of defines |
85
|
0
|
|
|
|
|
|
my $pack = $self->{pack}; |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
#print ::Dumper(\$flagref, $bittableref); |
88
|
0
|
0
|
|
|
|
|
(defined $flagref->{Defines}) or die; |
89
|
0
|
|
0
|
|
|
|
$flagref->{Defines} ||= ""; |
90
|
0
|
|
|
|
|
|
my $defname = _cleanup_column($flagref->{Defines}); |
91
|
0
|
0
|
0
|
|
|
|
$defname .= "_" if $defname ne "" && $defname !~ /_$/; |
92
|
0
|
0
|
|
|
|
|
$defname = "" if $defname eq "_"; |
93
|
|
|
|
|
|
|
|
94
|
0
|
|
0
|
|
|
|
my $whole_table_attr = $flagref->{Attributes}||""; |
95
|
|
|
|
|
|
|
|
96
|
0
|
|
|
|
|
|
my ($const_col, $mnem_col, $def_col) |
97
|
|
|
|
|
|
|
= $self->_choose_columns ($flagref, |
98
|
|
|
|
|
|
|
[qw(Constant Mnemonic Definition)], |
99
|
|
|
|
|
|
|
[qw(Product)], |
100
|
|
|
|
|
|
|
$bittable[0]); |
101
|
0
|
0
|
|
|
|
|
defined $const_col or return $pack->warn ($flagref, "Define table is missing column headed 'Constant'\n"); |
102
|
0
|
0
|
|
|
|
|
defined $mnem_col or return $pack->warn ($flagref, "Define table is missing column headed 'Mnemonic'\n"); |
103
|
0
|
0
|
|
|
|
|
defined $def_col or return $pack->warn ($flagref, "Define table is missing column headed 'Definition'\n"); |
104
|
|
|
|
|
|
|
|
105
|
0
|
|
|
|
|
|
foreach my $row (@bittable) { |
106
|
0
|
0
|
|
|
|
|
print " Row:\n" if $Debug; |
107
|
0
|
|
|
|
|
|
foreach my $col (@$row) { |
108
|
0
|
0
|
|
|
|
|
print " Ent:$col\n" if $Debug; |
109
|
0
|
0
|
|
|
|
|
if (!defined $col) { |
110
|
0
|
|
|
|
|
|
$pack->warn ($flagref, "Column ".($col+1)." is empty\n"); |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
} |
113
|
0
|
0
|
|
|
|
|
next if $row eq $bittable[0]; # Ignore header |
114
|
|
|
|
|
|
|
|
115
|
0
|
|
|
|
|
|
my $val_mnem = $row->[$mnem_col]; |
116
|
0
|
|
|
|
|
|
my $desc = $row->[$def_col]; |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
# Skip blank/reserved values |
119
|
0
|
0
|
0
|
|
|
|
next if ($val_mnem eq "" && ($desc eq "" || $desc =~ /^reserved/i)); |
|
|
|
0
|
|
|
|
|
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
# Check for empty field |
122
|
0
|
|
|
|
|
|
my $defref = new SystemC::Vregs::Define::Value |
123
|
|
|
|
|
|
|
(pack => $pack, |
124
|
|
|
|
|
|
|
name => $defname . $val_mnem, |
125
|
|
|
|
|
|
|
rst => $row->[$const_col], |
126
|
|
|
|
|
|
|
desc => $desc, |
127
|
|
|
|
|
|
|
at => $flagref->{at}, |
128
|
|
|
|
|
|
|
is_manual => 1, |
129
|
|
|
|
|
|
|
); |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
# Take special user defined fields and add to table |
132
|
0
|
|
|
|
|
|
for (my $colnum=0; $colnum<=$#{$bittable[0]}; $colnum++) { |
|
0
|
|
|
|
|
|
|
133
|
0
|
|
|
|
|
|
my $col = $bittable[0][$colnum]; |
134
|
0
|
|
|
|
|
|
$col =~ s/\s+//; |
135
|
0
|
0
|
|
|
|
|
if ($col =~ /^\s*\(([a-zA-Z_0-9]+)\)\s*$/) { |
136
|
0
|
|
|
|
|
|
my $var = $1; |
137
|
0
|
|
0
|
|
|
|
my $val = _cleanup_column($row->[$colnum]||""); |
138
|
0
|
0
|
|
|
|
|
$defref->{attributes}{$var} = $val if $val =~ /^([][a-zA-Z._:0-9+]+)$/; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
} |
141
|
0
|
|
|
|
|
|
$defref->attributes_parse($whole_table_attr); |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub new_enum { |
146
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
147
|
0
|
|
|
|
|
|
my $bittableref = shift; my @bittable = @{$bittableref}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
148
|
0
|
|
|
|
|
|
my $flagref = shift; # Hash of {heading} = value_of_heading |
149
|
|
|
|
|
|
|
# Create a new enumeration |
150
|
0
|
|
|
|
|
|
my $pack = $self->{pack}; |
151
|
|
|
|
|
|
|
|
152
|
0
|
0
|
|
|
|
|
($flagref->{Enum}) or die; |
153
|
0
|
|
|
|
|
|
my $classname = _cleanup_column($flagref->{Enum}); |
154
|
|
|
|
|
|
|
|
155
|
0
|
|
|
|
|
|
my ($const_col, $mnem_col, $def_col) |
156
|
|
|
|
|
|
|
= $self->_choose_columns ($flagref, |
157
|
|
|
|
|
|
|
[qw(Constant Mnemonic Definition)], |
158
|
|
|
|
|
|
|
[qw(Product)], |
159
|
|
|
|
|
|
|
$bittable[0]); |
160
|
0
|
0
|
|
|
|
|
defined $const_col or return $pack->warn ($flagref, "Enum table is missing column headed 'Constant'\n"); |
161
|
0
|
0
|
|
|
|
|
defined $mnem_col or return $pack->warn ($flagref, "Enum table is missing column headed 'Mnemonic'\n"); |
162
|
0
|
0
|
|
|
|
|
defined $def_col or return $pack->warn ($flagref, "Enum table is missing column headed 'Definition'\n"); |
163
|
|
|
|
|
|
|
|
164
|
0
|
|
|
|
|
|
my $classref = new SystemC::Vregs::Enum |
165
|
|
|
|
|
|
|
(pack => $pack, |
166
|
|
|
|
|
|
|
name => $classname, |
167
|
|
|
|
|
|
|
at => $flagref->{at}, |
168
|
|
|
|
|
|
|
); |
169
|
|
|
|
|
|
|
|
170
|
0
|
|
0
|
|
|
|
my $attr = $flagref->{Attributes}||""; |
171
|
0
|
|
|
|
|
|
while ($attr =~ s/-(\w+)//) { |
172
|
0
|
|
|
|
|
|
$classref->{attributes}{$1} = 1; |
173
|
|
|
|
|
|
|
} |
174
|
0
|
0
|
|
|
|
|
($attr =~ /^\s*$/) or $pack->warn($flagref, "Strange attributes $attr\n"); |
175
|
|
|
|
|
|
|
|
176
|
0
|
|
|
|
|
|
foreach my $row (@bittable) { |
177
|
0
|
0
|
|
|
|
|
print " Row:\n" if $Debug; |
178
|
0
|
|
|
|
|
|
foreach my $col (@$row) { |
179
|
0
|
0
|
|
|
|
|
print " Ent:$col\n" if $Debug; |
180
|
0
|
0
|
|
|
|
|
if (!defined $col) { |
181
|
0
|
|
|
|
|
|
$pack->warn ($flagref, "Column ".($col+1)." is empty\n"); |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
} |
184
|
0
|
0
|
|
|
|
|
next if $row eq $bittable[0]; # Ignore header |
185
|
|
|
|
|
|
|
|
186
|
0
|
|
|
|
|
|
my $val_mnem = _cleanup_column($row->[$mnem_col]); |
187
|
0
|
|
|
|
|
|
my $desc = _cleanup_column($row->[$def_col]); |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# Skip blank/reserved values |
190
|
0
|
0
|
0
|
|
|
|
next if ($val_mnem eq "" && ($desc eq "" || $desc =~ /^reserved/i)); |
|
|
|
0
|
|
|
|
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
# Check for empty field |
193
|
0
|
|
|
|
|
|
my $valref = new SystemC::Vregs::Enum::Value |
194
|
|
|
|
|
|
|
(pack => $pack, |
195
|
|
|
|
|
|
|
name => $val_mnem, |
196
|
|
|
|
|
|
|
class => $classref, |
197
|
|
|
|
|
|
|
rst => _cleanup_column($row->[$const_col]), |
198
|
|
|
|
|
|
|
desc => $desc, |
199
|
|
|
|
|
|
|
at => $flagref->{at}, |
200
|
|
|
|
|
|
|
); |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# Take special user defined fields and add to table |
204
|
0
|
|
|
|
|
|
for (my $colnum=0; $colnum<=$#{$bittable[0]}; $colnum++) { |
|
0
|
|
|
|
|
|
|
205
|
0
|
|
|
|
|
|
my $col = $bittable[0][$colnum]; |
206
|
0
|
|
|
|
|
|
$col =~ s/\s+//; |
207
|
0
|
0
|
|
|
|
|
if ($col =~ /^\s*\(([a-zA-Z_0-9]+)\)\s*$/) { |
208
|
0
|
|
|
|
|
|
my $var = $1; |
209
|
0
|
|
0
|
|
|
|
my $val = _cleanup_column($row->[$colnum]||""); |
210
|
0
|
0
|
|
|
|
|
$valref->{attributes}{$var} = $val if $val =~ /^([][a-zA-Z._:0-9+]+)$/; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
sub new_register { |
217
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
218
|
0
|
|
|
|
|
|
my $bittableref = shift; my @bittable = @{$bittableref}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
219
|
0
|
|
|
|
|
|
my $flagref = shift; # Hash of {heading} = value_of_heading |
220
|
|
|
|
|
|
|
# Create a new register |
221
|
0
|
|
|
|
|
|
my $pack = $self->{pack}; |
222
|
|
|
|
|
|
|
|
223
|
0
|
|
0
|
|
|
|
my $classname = _cleanup_column($flagref->{Register} || $flagref->{Class}); |
224
|
0
|
0
|
|
|
|
|
(defined $classname) or die; |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
#print "new_register!\n",::Dumper(\$flagref,\@bittable); |
227
|
|
|
|
|
|
|
|
228
|
0
|
|
|
|
|
|
my $range = ""; |
229
|
0
|
0
|
|
|
|
|
$range = $1 if ($classname =~ s/(\[[^\]]+])//); |
230
|
0
|
|
|
|
|
|
$classname =~ s/\s+$//; |
231
|
|
|
|
|
|
|
|
232
|
0
|
|
0
|
|
|
|
my $is_register = ($flagref->{Register} || $flagref->{Address}); |
233
|
|
|
|
|
|
|
|
234
|
0
|
|
|
|
|
|
my $inherits = ""; |
235
|
0
|
0
|
|
|
|
|
if ($classname =~ s/\s*:\s*(\S+)$//) { |
236
|
0
|
|
|
|
|
|
$inherits = $1; |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
0
|
|
0
|
|
|
|
my $attr = $flagref->{Attributes}||""; |
240
|
0
|
0
|
|
|
|
|
return if $attr =~ /noimplementation/; |
241
|
|
|
|
|
|
|
|
242
|
0
|
|
|
|
|
|
my $typeref = new SystemC::Vregs::Type |
243
|
|
|
|
|
|
|
(pack => $pack, |
244
|
|
|
|
|
|
|
name => $classname, |
245
|
|
|
|
|
|
|
at => $flagref->{at}, |
246
|
|
|
|
|
|
|
is_register => $is_register, # Ok, perhaps I should have made a superclass |
247
|
|
|
|
|
|
|
); |
248
|
0
|
|
|
|
|
|
$typeref->inherits($inherits); |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
# See also $typeref->{attributes}{lcfirst}, below. |
251
|
0
|
|
|
|
|
|
while ($attr =~ s/-([a-zA-Z_0-9]+)\s*=?\s*([a-zA-Z._0-9+]+)?//) { |
252
|
0
|
0
|
|
|
|
|
$typeref->{attributes}{$1} = (defined $2 ? $2 : 1); |
253
|
|
|
|
|
|
|
} |
254
|
0
|
0
|
|
|
|
|
($attr =~ /^\s*$/) or $pack->warn($flagref, "Strange attributes $attr\n"); |
255
|
|
|
|
|
|
|
|
256
|
0
|
0
|
|
|
|
|
if ($is_register) { |
257
|
|
|
|
|
|
|
# Declare a register |
258
|
0
|
0
|
|
|
|
|
($classname =~ /^[R]_/) or return $pack->warn($flagref, "Strange mnemonic name, doesn't begin with R_"); |
259
|
|
|
|
|
|
|
|
260
|
0
|
|
|
|
|
|
my $addr = $flagref->{Address}; # Don't _cleanup_column, as we have (Add 0x) text |
261
|
0
|
|
|
|
|
|
my $spacingtext = 0; |
262
|
0
|
0
|
|
|
|
|
$spacingtext = $pack->{data_bytes} if $range; |
263
|
0
|
0
|
|
|
|
|
if (!$addr) { |
264
|
0
|
|
|
|
|
|
$pack->warn ($flagref, "No 'Address' Heading Found\n"); |
265
|
0
|
|
|
|
|
|
return; |
266
|
|
|
|
|
|
|
} |
267
|
0
|
|
|
|
|
|
$addr =~ s/[()]//g; |
268
|
0
|
|
|
|
|
|
$addr =~ s/\s*plus\s*base\s*address\s*//; |
269
|
0
|
|
|
|
|
|
$addr =~ s/\s*per\s+entry//g; |
270
|
0
|
0
|
|
|
|
|
if ($addr =~ s/\s*Add\s*(0x[a-f0-9_]+)\s*//i) { |
271
|
0
|
|
|
|
|
|
$spacingtext = $1; |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
0
|
|
|
|
|
|
my $regref = new SystemC::Vregs::Register |
275
|
|
|
|
|
|
|
(pack => $pack, |
276
|
|
|
|
|
|
|
typeref => $typeref, |
277
|
|
|
|
|
|
|
name => $classname, |
278
|
|
|
|
|
|
|
at => $flagref->{at}, |
279
|
|
|
|
|
|
|
addrtext => $addr, |
280
|
|
|
|
|
|
|
spacingtext => $spacingtext, |
281
|
|
|
|
|
|
|
range => $range, |
282
|
|
|
|
|
|
|
); |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
0
|
0
|
0
|
|
|
|
if (defined $bittable[0] || !$inherits) { |
286
|
0
|
|
|
|
|
|
my ($bit_col, $mnem_col, $type_col, $def_col, |
287
|
|
|
|
|
|
|
$acc_col, $rst_col, |
288
|
|
|
|
|
|
|
$const_col, |
289
|
|
|
|
|
|
|
$size_col) |
290
|
|
|
|
|
|
|
= $self->_choose_columns ($flagref, |
291
|
|
|
|
|
|
|
[qw(Bit Mnemonic Type Definition), |
292
|
|
|
|
|
|
|
qw(Access Reset), # Register decls |
293
|
|
|
|
|
|
|
qw(Constant), # Class declarations |
294
|
|
|
|
|
|
|
qw(Size), # Ignored Optionals |
295
|
|
|
|
|
|
|
], |
296
|
|
|
|
|
|
|
[qw(Product)], |
297
|
|
|
|
|
|
|
$bittable[0]); |
298
|
0
|
|
0
|
|
|
|
$rst_col ||= $const_col; |
299
|
0
|
0
|
|
|
|
|
defined $bit_col or return $pack->warn ($flagref, "Table is missing column headed 'Bit'\n"); |
300
|
0
|
0
|
|
|
|
|
defined $mnem_col or return $pack->warn ($flagref, "Table is missing column headed 'Mnemonic'\n"); |
301
|
0
|
0
|
|
|
|
|
defined $def_col or return $pack->warn ($flagref, "Table is missing column headed 'Definition'\n"); |
302
|
0
|
0
|
|
|
|
|
if ($is_register) { |
303
|
0
|
0
|
|
|
|
|
defined $rst_col or return $pack->warn ($flagref, "Table is missing column headed 'Reset'\n"); |
304
|
0
|
0
|
|
|
|
|
defined $acc_col or return $pack->warn ($flagref, "Table is missing column headed 'Access'\n"); |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
# Table by table, allow the field mnemonics to be either 'fooFlag' |
308
|
|
|
|
|
|
|
# (per our Coding Conventions) or 'FooFlag' (as in a Vregs ASCII file). |
309
|
|
|
|
|
|
|
|
310
|
0
|
|
|
|
|
|
my $allMnems_LCFirst = (@bittable > 1); |
311
|
0
|
|
|
|
|
|
foreach my $row (@bittable) { |
312
|
0
|
0
|
|
|
|
|
next if $row eq $bittable[0]; # Ignore header |
313
|
0
|
0
|
|
|
|
|
my $bit_mnem = $row->[$mnem_col] or next; |
314
|
0
|
|
|
|
|
|
my $c1 = substr($bit_mnem, 0, 1); |
315
|
0
|
0
|
0
|
|
|
|
if ($c1 ge 'A' && $c1 le 'Z') { $allMnems_LCFirst = 0; } |
|
0
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
} |
317
|
0
|
0
|
|
|
|
|
if ($allMnems_LCFirst) { |
318
|
0
|
0
|
|
|
|
|
print " Upcasing first letter of mnemonics.\n" if $Debug; |
319
|
0
|
|
|
|
|
|
foreach my $row (@bittable) { |
320
|
0
|
0
|
|
|
|
|
next if $row eq $bittable[0]; # Ignore header |
321
|
0
|
0
|
|
|
|
|
my $bit_mnem = $row->[$mnem_col] or next; |
322
|
0
|
|
|
|
|
|
$row->[$mnem_col] = ucfirst $bit_mnem; |
323
|
|
|
|
|
|
|
} |
324
|
0
|
|
|
|
|
|
$typeref->{attributes}{lcfirst} = 1; |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
0
|
|
|
|
|
|
foreach my $row (@bittable) { |
328
|
0
|
0
|
|
|
|
|
print " Row:\n" if $Debug; |
329
|
0
|
|
|
|
|
|
foreach my $col (@$row) { |
330
|
0
|
0
|
|
|
|
|
print " Ent:$col\n" if $Debug; |
331
|
0
|
0
|
|
|
|
|
if (!defined $col) { |
332
|
0
|
|
|
|
|
|
$pack->warn ($flagref, "Column ".($col+1)." is empty\n"); |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
} |
335
|
0
|
0
|
|
|
|
|
next if $row eq $bittable[0]; # Ignore header |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
# Check for empty field |
338
|
0
|
|
|
|
|
|
my $bit_mnem = $row->[$mnem_col]; |
339
|
0
|
|
|
|
|
|
$bit_mnem =~ s/^_//; |
340
|
0
|
|
|
|
|
|
my $desc = $row->[$def_col]; |
341
|
|
|
|
|
|
|
|
342
|
0
|
|
|
|
|
|
my $overlaps = ""; |
343
|
0
|
0
|
|
|
|
|
$overlaps = $1 if ($desc =~ /\boverlaps\s+([a-zA-Z0-9_]+)/i); |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
# Skip empty fields |
346
|
0
|
0
|
0
|
|
|
|
if (($bit_mnem eq "" || $bit_mnem eq '-') |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
347
|
|
|
|
|
|
|
&& ($desc eq "" || $desc =~ /Reserved/ || $desc=~/Hardwired/ |
348
|
|
|
|
|
|
|
|| $desc =~ /^(\/\/|\#)/)) { # Allow //Comment or #Comment |
349
|
0
|
|
|
|
|
|
next; |
350
|
|
|
|
|
|
|
} |
351
|
0
|
0
|
0
|
|
|
|
if ((!defined $bit_col || $row->[$bit_col] eq "") |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
352
|
|
|
|
|
|
|
&& (!defined $mnem_col || $row->[$mnem_col] eq "") |
353
|
|
|
|
|
|
|
&& (!defined $rst_col || $row->[$rst_col] eq "") |
354
|
|
|
|
|
|
|
) { |
355
|
0
|
|
|
|
|
|
next; # All blank lines (excl comment) are fine. |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
|
358
|
0
|
0
|
|
|
|
|
my $rst = _cleanup_column(defined $rst_col ? $row->[$rst_col] : ""); |
359
|
0
|
0
|
0
|
|
|
|
$rst = 'X' if ($rst eq "" && !$is_register); |
360
|
|
|
|
|
|
|
|
361
|
0
|
|
0
|
|
|
|
my $type = _cleanup_column(defined $type_col && $row->[$type_col]); |
362
|
|
|
|
|
|
|
|
363
|
0
|
0
|
|
|
|
|
my $acc = _cleanup_column(defined $acc_col ? $row->[$acc_col] : 'RW'); |
364
|
|
|
|
|
|
|
|
365
|
0
|
0
|
|
|
|
|
(!$typeref->{fields}{$bit_mnem}) or |
366
|
|
|
|
|
|
|
$pack->warn ($typeref->{fields}{$bit_mnem}, "Field defined twice in spec\n"); |
367
|
0
|
0
|
0
|
|
|
|
my $bitref = new SystemC::Vregs::Bit |
368
|
|
|
|
|
|
|
(pack => $pack, |
369
|
|
|
|
|
|
|
name => $bit_mnem, |
370
|
|
|
|
|
|
|
typeref => $typeref, |
371
|
|
|
|
|
|
|
bits => $row->[$bit_col], |
372
|
|
|
|
|
|
|
access => $acc, |
373
|
|
|
|
|
|
|
overlaps => $overlaps, |
374
|
|
|
|
|
|
|
rst => $rst, |
375
|
|
|
|
|
|
|
desc => $row->[$def_col], |
376
|
|
|
|
|
|
|
type => $type, |
377
|
|
|
|
|
|
|
expand => ($type && $desc =~ /expand class/i)?1:undef, |
378
|
|
|
|
|
|
|
at => $flagref->{at}, |
379
|
|
|
|
|
|
|
); |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
# Take special user defined fields and add to table |
382
|
0
|
|
|
|
|
|
for (my $colnum=0; $colnum<=$#{$bittable[0]}; $colnum++) { |
|
0
|
|
|
|
|
|
|
383
|
0
|
|
|
|
|
|
my $col = $bittable[0][$colnum]; |
384
|
0
|
|
|
|
|
|
$col =~ s/\s+//; |
385
|
0
|
0
|
|
|
|
|
if ($col =~ /^\s*\(([a-zA-Z_0-9]+)\)\s*$/) { |
386
|
0
|
|
|
|
|
|
my $var = $1; |
387
|
0
|
|
0
|
|
|
|
my $val = _cleanup_column($row->[$colnum]||""); |
388
|
0
|
0
|
|
|
|
|
$bitref->{attributes}{$var} = $val if $val =~ /^([][a-zA-Z._:0-9+]+)$/; |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
} |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
###################################################################### |
396
|
|
|
|
|
|
|
#### Parsing |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
sub _choose_columns { |
399
|
0
|
|
|
0
|
|
|
my $self = shift; |
400
|
0
|
|
|
|
|
|
my $flagref = shift; |
401
|
0
|
|
|
|
|
|
my $fieldref = shift; |
402
|
0
|
|
|
|
|
|
my $attrfieldref = shift; |
403
|
0
|
|
|
|
|
|
my $headref = shift; |
404
|
|
|
|
|
|
|
# Look for the columns with the given headings. Require them to exist. |
405
|
|
|
|
|
|
|
|
406
|
0
|
|
|
|
|
|
my @collist; |
407
|
0
|
|
|
|
|
|
my @colused = (); |
408
|
0
|
|
|
|
|
|
my @colheads; |
409
|
|
|
|
|
|
|
# The list is short, so this is faster than forming a hash. |
410
|
|
|
|
|
|
|
# If things get wide, this may change |
411
|
0
|
|
|
|
|
|
for (my $h=0; $h<=$#{$headref}; $h++) { |
|
0
|
|
|
|
|
|
|
412
|
0
|
|
|
|
|
|
$colheads[$h] = $headref->[$h]; |
413
|
0
|
|
|
|
|
|
$colheads[$h] =~ s/\s*\(.*\)\s*//; # Ignore comments in the header |
414
|
0
|
0
|
|
|
|
|
$colused[$h] = 1 if $colheads[$h] eq ""; |
415
|
|
|
|
|
|
|
} |
416
|
0
|
|
|
|
|
|
headchk: |
417
|
0
|
|
|
|
|
|
foreach my $fld (@{$fieldref}) { |
418
|
0
|
|
|
|
|
|
for (my $h=0; $h<=$#{$headref}; $h++) { |
|
0
|
|
|
|
|
|
|
419
|
0
|
0
|
|
|
|
|
if ($fld eq $colheads[$h]) { |
420
|
0
|
|
|
|
|
|
push @collist, $h; |
421
|
0
|
|
|
|
|
|
$colused[$h] = 1; |
422
|
0
|
|
|
|
|
|
next headchk; |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
} |
425
|
0
|
|
|
|
|
|
push @collist, undef; |
426
|
|
|
|
|
|
|
} |
427
|
0
|
|
|
|
|
|
foreach my $fld (@{$attrfieldref}) { |
|
0
|
|
|
|
|
|
|
428
|
0
|
|
|
|
|
|
for (my $h=0; $h<=$#{$headref}; $h++) { |
|
0
|
|
|
|
|
|
|
429
|
0
|
0
|
|
|
|
|
if ($fld eq $colheads[$h]) { |
430
|
|
|
|
|
|
|
# Convert to a attribute |
431
|
0
|
|
|
|
|
|
$headref->[$h] = "(".$headref->[$h].")"; |
432
|
0
|
|
|
|
|
|
$colused[$h] = 1; |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
|
437
|
0
|
|
|
|
|
|
my $ncol = 0; |
438
|
0
|
|
|
|
|
|
for (my $h=0; $h<=$#{$headref}; $h++) { |
|
0
|
|
|
|
|
|
|
439
|
0
|
0
|
|
|
|
|
$ncol = $h+1 if !$colused[$h]; |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
|
442
|
0
|
0
|
|
|
|
|
if ($ncol) { |
443
|
0
|
|
|
|
|
|
SystemC::Vregs::Subclass::warn ($flagref, "Column ".($ncol-1)." found with unknown header.\n"); |
444
|
0
|
|
|
|
|
|
print "Desired column headers: '",join("' '",@{$fieldref}),"'\n"; |
|
0
|
|
|
|
|
|
|
445
|
0
|
|
|
|
|
|
print "Found column headers: '",join("' '",@{$headref}),"'\n"; |
|
0
|
|
|
|
|
|
|
446
|
0
|
0
|
|
|
|
|
print "Defined:("; foreach (@collist) { print (((defined $_)?$_:'-'),' '); } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
447
|
0
|
|
|
|
|
|
print ")\n"; |
448
|
0
|
0
|
|
|
|
|
print "Used: ("; foreach (@colused) { print ((($_)?'Y':'-'),' '); } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
449
|
0
|
|
|
|
|
|
print ")\n"; |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
|
452
|
0
|
|
|
|
|
|
return (@collist); |
453
|
|
|
|
|
|
|
} |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
sub _cleanup_column { |
456
|
0
|
|
|
0
|
|
|
my $text = shift; |
457
|
0
|
0
|
|
|
|
|
return undef if !defined $text; |
458
|
0
|
|
|
|
|
|
while ($text =~ s/\s*\([^\(\)]*\)//) {} # Strip (comment) Leave trailing space "foo (bar) x" becomes "foo x" |
459
|
0
|
|
|
|
|
|
$text =~ s/\s+$//; |
460
|
0
|
|
|
|
|
|
$text =~ s/^\s+//; |
461
|
0
|
|
|
|
|
|
return $text; |
462
|
|
|
|
|
|
|
} |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
###################################################################### |
465
|
|
|
|
|
|
|
###################################################################### |
466
|
|
|
|
|
|
|
#### Package return |
467
|
|
|
|
|
|
|
1; |
468
|
|
|
|
|
|
|
__END__ |