Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / n2 / lib / ras / bin / xml2reg
CommitLineData
920dae64
AT
1use XML::Simple;
2use FileHandle;
3use Getopt::Std;
4use Data::Dumper;
5use Storable qw( dclone );
6use strict;
7use vars qw( $opt_n $opt_S $opt_I $opt_h $opt_d $opt_v $opt_r $opt_o $opt_t
8 $opt_p);
9use vars qw( @ORIG_ARGS );
10use vars qw( $debug );
11
12$debug = 0;
13@ORIG_ARGS = @ARGV;
14getopts('n:S:I:hdvropt');
15# n - Additional namepaces separated by commas
16# S - source file destination path
17# I - include file destination path
18# h - help
19# d - dump internal representation, then quit
20# v - validate register, then quit
21# p - include pretty print routines, e.g. toString()
22# t - not to make the register a BL_ThinFieldObj-derived class
23
24main();
25
26####################################################################
27####################################################################
28####################################################################
29
30sub print_debug
31{
32 if( $debug ){
33 print @_;
34 }
35}
36
37####################################################################
38####################################################################
39####################################################################
40
41sub main
42{
43 if( defined $opt_h ){
44 $0 =~ s#.*/##;
45 print "usage: $0 [-h|d|v] [-I include path] [-S source path] [-n csv namespace list] <xml file names>\n";
46 exit 0;
47 }
48
49 for my $xml_file ( @ARGV ){
50 gen_regs( $xml_file );
51 }
52
53 return 0;
54}
55
56####################################################################
57####################################################################
58####################################################################
59
60sub get_xml_hash
61{
62 my ( $xml_file, $leaf ) = @_;
63 my $xs = XML::Simple->new();
64 my $xml_hash = $xs->XMLin( $xml_file );
65
66 # If the register has only one entry, fix it up.
67 # This is a consequence of using the XML::Simple library.
68 if( defined $xml_hash->{register}->{field}->{name} ){
69 # copy the single field to the single field's name. Then remove
70 # all of the other key's using fix_hash.
71 $xml_hash->{register}->{field}->{$xml_hash->{register}->{field}->{name}} = dclone( $xml_hash->{register}->{field} );
72 fix_hash( $xml_hash->{register} );
73 }
74
75 if ( defined $xml_hash->{register}->{inherits} ){
76 my $parent_xml_hash;
77 my $parent_file = $xml_hash->{register}->{inherits};
78 #$parent_file = $opt_S . "/" . $parent_file if defined $opt_S;
79 $parent_xml_hash = get_xml_hash( $parent_file, 0 );
80 $xml_hash = merge_parent_child( $parent_xml_hash, $xml_hash, $leaf );
81 $xml_hash->{register}->{inheritance_info}->{other_ancestor} = 1;
82 $xml_hash->{register}->{inheritance_info}->{ancestor_xml} = $parent_file;
83 } elsif ( $leaf ) {
84 for my $field_name ( keys (%{$xml_hash->{register}->{field}}) ){
85 $xml_hash->{register}->{field}->{$field_name}->{generate_data} = 1;
86 }
87 }
88
89 if( $leaf && defined $xml_hash->{register}->{inheritance_info}->{other_ancestor} ){
90 my $inh_xml_file = $xml_hash->{register}->{inheritance_info}->{ancestor_xml};
91 my $inh_include_file = $inh_xml_file;
92
93 #$inh_include_file =~ s/\.xml$/.h/;
94 my $inh_class_name;
95 if( $inh_xml_file =~ m#\b(\w[\w\d]*)\.xml$# ){
96 $inh_class_name = $1;
97 $inh_include_file = $1.".h";
98 } else {
99 die "$0: couldn't extract class name from \"$inh_xml_file\"\n";
100 }
101
102 $xml_hash->{register}->{inheritance_info}->{include_file} = $inh_include_file;
103 $xml_hash->{register}->{inheritance_info}->{ancestor_class} = $inh_class_name;
104
105 }
106
107 return $xml_hash;
108}
109
110####################################################################
111####################################################################
112####################################################################
113
114sub location_match
115{
116 my ( $p, $start_o, $end_o ) = @_;
117
118 for my $field ( keys (%{$p->{field}}) ){
119 return $field if ( $p->{field}->{$field}->{start_offset} == $start_o &&
120 $p->{field}->{$field}->{end_offset} == $end_o );
121 }
122
123 return -1;
124}
125
126####################################################################
127####################################################################
128####################################################################
129
130sub merge_parent_child
131{
132 my ( $parent_h, $child_h, $leaf ) = @_;
133 my ( $p, $c ) = ( $parent_h->{register}, $child_h->{register} );
134
135 print_debug "Merging $p->{class_name} into $c->{class_name}\n";
136 my $old_class_name = $p->{class_name};
137 my $new_class_name = $c->{class_name};
138 # top-level informational tags
139 $p->{class_name} = $c->{class_name};
140 $p->{name} = $c->{name} if defined $c->{name};
141 $p->{submodule} = $c->{submodule} if defined $c->{submodule};
142 $p->{priv} = $c->{priv} if defined $c->{priv};
143 $p->{comment} .= $c->{comment} if defined $c->{comment};
144 $p->{base_address} .= $c->{base_address} if defined $c->{base_address};
145 $p->{count} .= $c->{count} if defined $c->{count};
146 $p->{stride} .= $c->{stride} if defined $c->{stride};
147 delete $p->{public};
148 $p->{public} .= $c->{public} if defined $c->{public};
149 delete $p->{protected};
150 $p->{protected} .= $c->{protected} if defined $c->{protected};
151 delete $p->{private};
152 $p->{private} .= $c->{private} if defined $c->{private};
153
154 # copy any new aggregations that are in the child
155 if( defined $c->{aggregate} ){
156 for my $agg ( keys (%{$c->{aggregate}}) ){
157 $p->{aggregate}->{$agg} = dclone( $c->{aggregate}->{$agg} );
158 }
159 }
160
161
162 # don't generate any fields by default.
163 for my $field ( keys (%{$p->{field}}) ){
164 $p->{field}->{$field}->{generate_data} = 0;
165 }
166
167
168 for my $field ( keys (%{$c->{field}}) ){
169 my $field_name = location_match(
170 $p,
171 $c->{field}->{$field}->{start_offset},
172 $c->{field}->{$field}->{end_offset} );
173
174 # there's a field in the parent that matches the child's location
175 if( $field_name != -1 ){
176 print_debug "Merging field '$field_name'\n";
177 if( defined $c->{field}->{$field}->{comment} ){
178 print_debug " Merged comment from $old_class_name.$field_name to $new_class_name.$field\n";
179 $p->{field}->{$field_name}->{comment} = $c->{field}->{$field}->{comment};
180 }
181 if( defined $c->{field}->{$field}->{base_address} ){
182 print_debug " Merged base_address from $old_class_name.$field_name to $new_class_name.$field\n";
183 $p->{field}->{$field_name}->{base_address} = $c->{field}->{$field}->{base_address};
184 }
185 if( defined $c->{field}->{$field}->{count} ){
186 print_debug " Merged count from $old_class_name.$field_name to $new_class_name.$field\n";
187 $p->{field}->{$field_name}->{count} = $c->{field}->{$field}->{count};
188 }
189 if( defined $c->{field}->{$field}->{stride} ){
190 print_debug " Merged stride from $old_class_name.$field_name to $new_class_name.$field\n";
191 $p->{field}->{$field_name}->{stride} = $c->{field}->{$field}->{stride};
192 }
193 if( defined $c->{field}->{$field}->{protection} ){
194 print_debug " Merged protection from $old_class_name.$field_name to $new_class_name.$field ";
195 print_debug "(old = $p->{field}->{$field_name}->{protection}, new = $c->{field}->{$field}->{protection})\n";
196 $p->{field}->{$field_name}->{protection} = $c->{field}->{$field}->{protection};
197 }
198 if( defined $c->{field}->{$field}->{field_type} ){
199 print_debug " Merged field_type from $old_class_name.$field_name to $new_class_name.$field ";
200 print_debug "(old=$p->{field}->{$field_name}->{field_type} new=$c->{field}->{$field}->{field_type})\n";
201 $p->{field}->{$field_name}->{field_type} = $c->{field}->{$field}->{field_type} ;
202 }
203 if( defined $c->{field}->{$field}->{initial_value} ){
204 print_debug " Merged intial_value from $old_class_name.$field_name to $new_class_name.$field ";
205 print_debug "(old=$p->{field}->{$field_name}->{initial_value} new=$c->{field}->{$field}->{initial_value})\n";
206 $p->{field}->{$field_name}->{initial_value} = $c->{field}->{$field}->{initial_value} ;
207 }
208 if( defined $c->{field}->{$field}->{format} ){
209 print_debug "Merged format from $old_class_name.$field_name to $new_class_name.$field\n";
210 $p->{field}->{$field_name}->{format} = dclone( $c->{field}->{$field}->{format} );
211 }
212
213 # If this statement is true, then the field has been renamed in the child
214 # Since we've merged everything into the parent, then we'll need clone the
215 # parent's field (containing the merged data) and assign it to the new name.
216 # Then we can remove copy under the old field name
217 if( $field ne $field_name ){
218 $p->{field}->{$field} = dclone( $p->{field}->{$field_name} );
219 delete( $p->{field}->{$field_name} );
220 $p->{field}->{$field}->{generate_data} = $leaf;
221 }
222 } else {
223 print_debug "Adding new field '$field' from child\n";
224 # no field matches child's location, so we add it.
225 $p->{field}->{$field} = dclone( $c->{field}->{$field} );
226 $p->{field}->{$field}->{generate_data} = $leaf;
227 }
228 }
229
230
231 return $parent_h;
232}
233
234####################################################################
235####################################################################
236####################################################################
237
238sub gen_regs
239{
240 my( $xml_file ) = @_;
241
242 my $xml_hash = get_xml_hash( $xml_file, 1 );
243
244 if( defined $opt_d ){
245 print Dumper( $xml_hash );
246 my $register_ref = $xml_hash->{register};
247 print Dumper( $register_ref );
248 exit 0;
249 }
250
251 my $register_ref = $xml_hash->{register};
252 if( defined $register_ref->{name} ){
253 # single register
254 gen_cpp( $xml_file, $register_ref->{name}, $register_ref );
255
256 } else {
257 foreach my $reg_name ( keys (%{$register_ref}) ){
258 $register_ref->{$reg_name}->{name} = $reg_name;
259 gen_cpp( $xml_file, $reg_name, $register_ref->{$reg_name} );
260 }
261 }
262
263}
264
265####################################################################
266####################################################################
267####################################################################
268
269sub gen_cpp
270{
271 my ( $xml_file, $name, $register_ref ) = @_;
272 my( $h_file_name, $cc_file_name );
273
274 calculate_sizes( $register_ref );
275
276 if( !validate( $register_ref ) ){
277 exit 1;
278 }
279 return if defined $opt_v;
280
281 my $include_path = ".";
282 my $source_path = ".";
283 $include_path = $opt_I if defined $opt_I;
284 $source_path = $opt_S if defined $opt_S;
285 if( ! -d $include_path ){
286 system( "mkdir -p $include_path" );
287 }
288 if( ! -d $source_path ){
289 system( "mkdir -p $source_path" );
290 }
291
292 $h_file_name = xlate_path( $register_ref->{class_name}, $include_path, "h" );
293 $cc_file_name = xlate_path( $register_ref->{class_name}, $source_path, "cc" );
294
295
296 open DOT_H_FILE, ">$h_file_name" or die "couldn't create $h_file_name";
297 open DOT_CC_FILE, ">$cc_file_name" or die "couldn't create $cc_file_name"
298 if !$opt_t;
299
300 print "$xml_file -> $h_file_name\n";
301 write_include_file( *DOT_H_FILE, $xml_file, $register_ref, $register_ref->{name} );
302 if( !$opt_t ) {
303 print "$xml_file -> $cc_file_name\n";
304 write_impl_file ( *DOT_CC_FILE, $xml_file, $register_ref, $register_ref->{name} );
305 }
306}
307
308####################################################################
309####################################################################
310####################################################################
311
312sub calculate_sizes
313{
314 my ( $reg_ref ) = @_;
315
316 for my $field_name ( keys (%{$reg_ref->{field}} ) ){
317 $reg_ref->{field}->{$field_name}->{size} = $reg_ref->{field}->{$field_name}->{end_offset} -
318 $reg_ref->{field}->{$field_name}->{start_offset} + 1;
319 }
320}
321
322####################################################################
323####################################################################
324####################################################################
325
326sub xlate_path
327{
328 my ( $file, $path, $suffix ) = @_;
329 my $new_file = $file;
330
331 if( $path ne "" ){
332 $new_file = $path . "/" . $new_file;
333 }
334
335 return $new_file . "." . $suffix;
336}
337
338####################################################################
339####################################################################
340####################################################################
341
342sub get_size
343{
344 my( $reg_hash ) = @_;
345 my $bits;
346
347 for my $field_name ( keys (%{$reg_hash->{field}} ) ){
348 $bits += $reg_hash->{field}->{$field_name}->{size};
349 }
350
351
352 return $bits;
353}
354
355####################################################################
356####################################################################
357####################################################################
358
359sub get_native_type
360{
361 my ( $nr_bits ) = @_;
362 my %sz_hash = ( 8 => "uint8_t",
363 16 => "uint16_t",
364 32 => "uint32_t",
365 64 => "uint64_t" );
366
367 for my $k ( sort { $a <=> $b } keys %sz_hash ){
368 return ( $sz_hash{$k}, $k ) if $nr_bits <= $k;
369 }
370
371 print "ERROR: size $nr_bits cannot be represented in an integral type\n";
372 return ("ERROR", "ERROR");
373}
374
375####################################################################
376####################################################################
377####################################################################
378
379sub build_aggregate_include_string
380{
381 my ( $reg_ref ) = @_;
382 my $agg_ref = $reg_ref->{aggregate};
383 my $field_ref = $reg_ref->{field};
384 my $str;
385
386 for my $agg ( keys (%{$agg_ref} ) ){
387 my $size = 0;
388 for my $field ( keys (%{$agg_ref->{$agg}->{field}}) ){
389 $size += $field_ref->{$field}->{end_offset} - $field_ref->{$field}->{start_offset} + 1;
390 }
391 my ( $native_type, $bits ) = get_native_type( $size );
392$str .= <<EOTEXT
393 $native_type get${agg}();
394 void set${agg}( $native_type );
395EOTEXT
396;
397 }
398 return $str;
399}
400
401####################################################################
402####################################################################
403####################################################################
404
405sub build_aggregate_impl_string
406{
407 my ( $reg_ref, $class_name ) = @_;
408 my $agg_ref = $reg_ref->{aggregate};
409 my $field_ref = $reg_ref->{field};
410 my $str;
411
412 for my $agg ( keys (%{$agg_ref} ) ){
413 my $size = 0;
414 my %field_data;
415 for my $field ( keys (%{$agg_ref->{$agg}->{field}}) ){
416 my $sz = $field_ref->{$field}->{end_offset} - $field_ref->{$field}->{start_offset} + 1;
417 $size += $sz;
418 $field_data{$agg_ref->{$agg}->{field}->{$field}->{'pos'}}->{name} = $field;
419 $field_data{$agg_ref->{$agg}->{field}->{$field}->{'pos'}}->{size} = $sz;
420 }
421 my ( $native_type, $bits ) = get_native_type( $size );
422
423 my ( $get_str, $set_str ) = ( "", "" );
424
425 my $offset = 0;
426
427 for my $pos ( sort { $a <=> $b } keys %field_data ){
428 my $var_name = uc $field_data{$pos}->{name};
429 my $mask = (2 ** $field_data{$pos}->{size}) - 1;
430 $mask = sprintf "0x0%lx", $mask;
431 $get_str .= "(get$var_name() << $offset) |\n ";
432 $set_str .= " set$var_name((____d >> $offset) & $mask);\n";
433 $offset += $field_data{$pos}->{size};
434 }
435 $get_str .= "0";
436
437$str .= <<EOTEXT
438$native_type ${class_name}::get${agg}()
439{
440 return $get_str;
441}
442
443void ${class_name}::set${agg}( $native_type ____d )
444{
445$set_str
446}
447EOTEXT
448;
449
450 }
451 return $str;
452}
453
454####################################################################
455####################################################################
456####################################################################
457
458sub calc_constructors
459{
460 my( $reg_ref ) = @_;
461
462 my ( $constructor_mask, $constructor_init, $constructor_bits,
463 $constructor_rw1c ) = ( "0\n", "0\n", "0\n", "0\n" );
464
465 my $register_size = 0;
466 my @tmpList;
467 my $fn;
468 my %fields;
469 for my $field_name ( keys (%{$reg_ref->{field}} ) ){
470 $register_size += $reg_ref->{field}->{$field_name}->{size};
471 if( $reg_ref->{field}->{$field_name}->{field_type} eq "NORMAL" ){
472 push @tmpList, $field_name;
473 }
474 $fields{ $reg_ref->{field}->{$field_name}->{start_offset}} =
475 $field_name;
476 }
477 while( ($fn = pop @tmpList) ){
478 my $ha_field_mask = "(~uint64_t(0) >> (64 - $reg_ref->{field}->{$fn}->{size}))";
479 my $ha_field_shft = "$reg_ref->{field}->{$fn}->{start_offset}";
480
481 if( defined $reg_ref->{field}->{$fn}->{initial_value} ){
482 $constructor_init .= " | (($reg_ref->{field}->{$fn}->{initial_value} & $ha_field_mask) << $ha_field_shft)\n";
483 }
484 if( $reg_ref->{field}->{$fn}->{field_type} eq "NORMAL" ){
485 if( $reg_ref->{field}->{$fn}->{protection} eq "RW" ){
486 $constructor_mask .= " | ($ha_field_mask << $ha_field_shft)\n";
487 }
488 if( $reg_ref->{field}->{$fn}->{protection} eq "RW1C" ){
489 $constructor_rw1c .= " | ($ha_field_mask << $ha_field_shft)\n";
490 }
491 $constructor_bits .= " | ($ha_field_mask << $ha_field_shft)\n";
492 }
493 }
494
495 return ( $constructor_mask, $constructor_init, $constructor_bits,
496 $constructor_rw1c );
497}
498
499####################################################################
500####################################################################
501####################################################################
502
503sub write_include_file
504{
505 my( @save_args ) = @_;
506 my( $file_handle, $xml_file, $reg_ref, $reg_name ) = @_;
507 my $sz = 0;
508 my $reg_name_uc = uc $reg_name;
509 my $nr_fields = 0;
510 my $class_name = $reg_ref->{class_name};
511 my $class_name_ref = "${class_name}&";
512 my $class_name_const_ref = "const ${class_name}&";
513 my ( $get_string, $set_string );
514 my $field_type_struct;
515 my ( $extra_namespace_header, $extra_namespace_footer );
516
517 my $field_type_enum = "enum { ";
518 my $field_string_array = "static const FieldObject::FieldInfo fieldData[] = {";
519 my %fields;
520 my $agg_string;
521
522 my $base_address;
523 my $count;
524 my $stride;
525 my $public;
526 my $protected;
527 my $private;
528 my $pretty_print_includes;
529
530 my ( $constructor_mask, $constructor_init, $constructor_bits,
531 $constructor_rw1c ) = &calc_constructors($reg_ref);
532 my $constructor_list =
533 "$constructor_mask, $constructor_init, $constructor_bits, $constructor_rw1c";
534 if (defined $reg_ref->{base_address}) {
535 $base_address = "static const uint64_t BaseAddress = $reg_ref->{base_address};";
536 }
537 if (defined $reg_ref->{count}) {
538 $count = "static const uint64_t Count = $reg_ref->{count};";
539 }
540 if (defined $reg_ref->{stride}) {
541 $stride = "static const uint64_t Stride = $reg_ref->{stride};";
542 }
543 if (defined $reg_ref->{public}) {
544 $public = "$reg_ref->{public}";
545 }
546 if (defined $reg_ref->{protected}) {
547 $protected = "$reg_ref->{protected}";
548 }
549 if (defined $reg_ref->{private}) {
550 $private = "$reg_ref->{private}";
551 }
552
553 $agg_string = build_aggregate_include_string( $reg_ref ) if defined $reg_ref->{aggregate};
554
555 # Get count of total register size and field count
556 for my $field_name ( keys (%{$reg_ref->{field}} ) ){
557 # maps field start_offset to field name
558 $fields{$reg_ref->{field}->{$field_name}->{start_offset}} = $field_name;
559 $sz += $reg_ref->{field}->{$field_name}->{size};
560 ++$nr_fields;
561 }
562
563
564 my $field_count = $nr_fields;
565 for my $o ( reverse sort { $a <=> $b } keys %fields ){
566 $field_count--;
567 my $field_name = $fields{$o};
568 $field_type_enum .= uc $field_name;
569 $field_type_enum .= ",";
570
571 if($reg_ref->{field}->{$field_name}->{field_type} eq "NORMAL" ){
572 my ($data_type, $foo) = get_native_type( $reg_ref->{field}->{$field_name}->{size} );
573# $field_type_struct .= " $data_type ". lc $field_name . ";\n" if $reg_ref->{field}->{$field_name}->{generate_data};
574 $get_string .= create_get_fn_decl( $reg_name, $field_name, $reg_ref->{field}->{$field_name}->{size}, $reg_ref->{field}->{$field_name}->{start_offset} );
575 $set_string .= create_set_fn_decl( $reg_name, $field_name, $reg_ref->{field}->{$field_name}->{size}, $reg_ref->{field}->{$field_name}->{start_offset}, $reg_ref->{field}->{$field_name}->{protection});
576 }
577 $set_string .= create_bitsize_decl( $reg_name, $field_name, $reg_ref->{field}->{$field_name}->{size}, $reg_ref->{field}->{$field_name}->{start_offset}, $reg_ref->{field}->{$field_name}->{protection}); }
578
579 $field_type_enum =~ s/,\s*$//; # chop off the comma from the last entry
580 $field_type_enum .= " }";
581
582 my $include_guard = "RIESLING_" . uc $class_name . "_H";
583 my $comment_str = get_comment_string( $0, $xml_file );
584
585 foreach my $ns ( split /,/, $opt_n ){
586 $extra_namespace_header .= "namespace $ns {\n";
587 $extra_namespace_footer .= "} /* namespace $ns */\n";
588 }
589
590 ##
591 ## Frontend registration handling
592 ##
593 my $extra_ancestors;
594 my $reg_declarations;
595 my $to_string_fn = "std::string toString() const;";
596 my $set_native_fn = "void setNative( uint64_t value ) { FieldObject::setNative(value); }";
597 $set_native_fn = "void setNative( uint64_t value ) { BL_ThinFieldObj<$constructor_list>::setNative(value); }" if $opt_t;
598 my $set_nativeHW_fn = "void setNativeHW( uint64_t value ) { FieldObject::setNativeHW(value); }";
599 $set_nativeHW_fn = "void setNativeHW( uint64_t value ) { BL_ThinFieldObj<$constructor_list>::setNativeHW(value); }" if $opt_t;
600 my $get_native_fn = "uint64_t getNative() const { return FieldObject::getNative(); }";
601 $get_native_fn = "uint64_t getNative() const { return BL_ThinFieldObj<$constructor_list>::getNative(); }" if $opt_t;
602 my $default_ctor = "$class_name();";
603
604 my $ancestor_include = $opt_t ? '#include "BL_ThinFieldObj.h"' :
605 '#include "FieldObject.h"';
606 my $ancestor_class = "FieldObject";
607 $ancestor_class = "BL_ThinFieldObj<$constructor_list>" if $opt_t;
608 if( defined $reg_ref->{inheritance_info}->{other_ancestor} ){
609 $ancestor_include = '#include "' . $reg_ref->{inheritance_info}->{include_file} . '"';
610 $ancestor_class = $reg_ref->{inheritance_info}->{ancestor_class};
611 # TODO This should really find out of RegisteredObject was already inherited by its # ancestor
612 $extra_ancestors = "";
613 # base class aready has these so no need to duplicate/confuse people
614 $set_native_fn = "";
615 $set_nativeHW_fn = "";
616 $get_native_fn = "";
617 }
618
619$pretty_print_includes = "#include <iostream>\n#include <string>\n" if $ opt_p;
620
621if ($opt_t) {
622print $file_handle <<EOHFILE0
623#ifndef $include_guard
624#define $include_guard
625$comment_str
626
627$pretty_print_includes
628
629#include "BL_ThinFieldObj.h"
630$ancestor_include
631
632$extra_namespace_header
633EOHFILE0
634;
635 }
636 else {
637print $file_handle <<EOHFILE1
638#ifndef $include_guard
639#define $include_guard
640$comment_str
641
642#include "DataTypes.h"
643$ancestor_include
644#include "StdMacros.h"
645#include "Interface/RegisteredObject.h"
646#include <iostream>
647#include <string>
648
649$extra_namespace_header
650EOHFILE1
651;
652 }
653
654#################################
655## Produce html for doxygen
656#################################
657print $file_handle "/**\n<pre>\n";
658print_field_table_doc( $file_handle, $reg_name_uc, \%fields, $reg_ref );
659print $file_handle "\n</pre>\n*/\n";
660
661print $file_handle <<EOHFILE1
662class $class_name : public $ancestor_class $extra_ancestors {
663EOHFILE1
664;
665
666print $file_handle <<EOHFILE4
667
668 public:
669
670 $base_address
671 $count
672 $stride
673 $public
674
675EOHFILE4
676;
677
678if (! $opt_t) {
679print $file_handle <<EOHFILE5
680
681 /**
682 * An enumeration that represent each accessable field. Use these types
683 * as inputs for accessors and mutators for fields.
684 */
685 typedef $field_type_enum FieldT;
686EOHFILE5
687;
688}
689
690print $file_handle <<EOHFILE6
691
692 $default_ctor
693 $class_name( $class_name_const_ref obj );
694 ~$class_name();
695EOHFILE6
696if ! $opt_t;
697
698print $file_handle <<EOHFILE60
699 $class_name_const_ref operator=( $class_name_const_ref obj ) { return ($class_name_const_ref)$ancestor_class ::operator=(obj); }
700 bool operator==( $class_name_const_ref obj ) const { return $ancestor_class ::operator==(obj); }
701
702 /**
703 * Get a copy of the register's native representation
704 *
705 * \@param data A pointer to a chunk of memory large enough
706 * to hold the register's native representaion
707 * \@see getSize()
708 */
709 $get_native_fn
710
711 $set_native_fn
712
713 $set_nativeHW_fn
714EOHFILE60
715;
716
717if (! $opt_t) {
718print $file_handle <<EOHFILE7
719 /**
720 * Return the register's size in bits
721 *
722 * \@return The register size in bits
723 * \@see ${class_name}::FieldT
724 */
725 uint32_t getSize() const;
726
727 /**
728 * Return the field's size in bits
729 *
730 * \@param field The number of this field
731 * \@return The field's size in bits
732 * \@see ${class_name}::FieldT
733 */
734 virtual uint32_t getSize( uint_t field ) const;
735
736 /**
737 * Return the field's offset in the register
738 *
739 * \@param field The number of this field
740 * \@return The field's offset
741 * \@see ${class_name}::FieldT
742 */
743 virtual uint32_t getOffset( uint_t field ) const;
744
745 /**
746 * Return the field's protection. That is, can the field be
747 * read, written, or both.
748 *
749 * \@param field The number of this field
750 * \@return The field's protection
751 * \@see FieldObject::ProtectionT
752 * \@see ${class_name}::FieldT
753 */
754 FieldObject::Protection getProtection( uint_t field ) const;
755
756 /**
757 * Return a string representation of the field name
758 *
759 * \@param field The number of this field
760 * \@return The name of the field
761 * \@see ${class_name}::FieldT
762 */
763 virtual const char* getName() const;
764
765 /**
766 * Return a string representation of the field name
767 *
768 * \@param field The number of this field
769 * \@return The name of the field
770 * \@see ${class_name}::FieldT
771 */
772 virtual const char* getName( uint_t field ) const;
773
774EOHFILE7
775;
776}
777
778print $file_handle <<EOHFILE80
779 $reg_declarations
780
781$get_string
782$set_string
783$agg_string
784
785EOHFILE80
786;
787
788if ( $opt_t ) {
789 my( $file_handle, $xml_file, $reg_ref, $reg_name ) = @save_args;
790 write_impl_file( $file_handle, $xml_file, $reg_ref, $reg_name );
791}
792else {
793 print $file_handle <<EOHFILE8
794
795 /**
796 * Return the string representaton of this register.
797 *
798 */
799 $to_string_fn
800
801 /**
802 * Print this Register to an output stream
803 *
804 * \@param os The output stream to which the register should be
805 * printed. Omitting this parameter will print the std::cout
806 */
807 virtual void print( std::ostream& os = std::cout ) const;
808EOHFILE8
809;
810}
811
812print $file_handle <<EOHFILE85
813
814 protected:
815
816 $protected
817EOHFILE85
818;
819
820if (! $opt_t) {
821print $file_handle <<EOHFILE9
822 //! How many fields the register has.
823 static const int NR_FIELDS = $nr_fields;
824 static const FieldObject::FieldInfo fieldData[];
825EOHFILE9
826;
827}
828
829print $file_handle <<EOHFILE10
830 private:
831
832};
833
834$extra_namespace_footer
835
836
837#endif /* $include_guard */
838
839EOHFILE10
840;
841
842print $file_handle "\n";
843}
844
845####################################################################
846####################################################################
847####################################################################
848
849sub write_impl_file
850{
851 my( $file_handle, $xml_file, $reg_ref, $reg_name ) = @_;
852 my $ifile_name = $reg_ref->{class_name} . ".h";
853 if( defined $reg_ref->{submodule} ){
854 $ifile_name = $reg_ref->{submodule} . "/" . $ifile_name;
855 }
856 my $class_name = $reg_ref->{class_name};
857 my $class_name_ref = "${class_name}&";
858 my $class_name_const_ref = "const ${class_name}&";
859 my $class_scope = $class_name . '::';
860
861 my $equal_string;
862 my ( $get_string, $set_string );
863 my $printing_string;
864 my $str_string;
865 my @tmpList;
866 my $fn;
867 my ( $copy_constructor_string, $constructor_string );
868 my ( $constructor_mask, $constructor_init, $constructor_bits,
869 $constructor_rw1c ) = &calc_constructors($reg_ref);
870 my ( $get_native_string, $set_native_string, $set_nativeHW_string );
871 my $register_size = 0;
872 my %fields;
873 my $agg_string;
874 $agg_string = build_aggregate_impl_string( $reg_ref, $class_name ) if defined $reg_ref->{aggregate};
875
876 my $field_string_array = "const FieldObject::FieldInfo ${class_scope}fieldData[] = {";
877
878 for my $field_name ( keys (%{$reg_ref->{field}} ) ){
879 $register_size += $reg_ref->{field}->{$field_name}->{size};
880 if( $reg_ref->{field}->{$field_name}->{field_type} eq "NORMAL" ){
881 push @tmpList, $field_name;
882 }
883 $fields{ $reg_ref->{field}->{$field_name}->{start_offset}} = $field_name;
884 }
885 for my $o ( reverse sort { $a <=> $b } keys %fields ){
886 my $field_name = $fields{$o};
887 if ( $reg_ref->{field}->{$field_name}->{protection} eq "RWH") {
888 $field_string_array .= "\n { FieldObject::RO, ";
889 }
890
891 else {
892 $field_string_array .= "\n { FieldObject::$reg_ref->{field}->{$field_name}->{protection}, ";
893 }
894 $field_string_array .= " $reg_ref->{field}->{$field_name}->{start_offset},";
895 $field_string_array .= " $reg_ref->{field}->{$field_name}->{size},";
896 $field_string_array .= " FieldObject::$reg_ref->{field}->{$field_name}->{field_type},";
897 $field_string_array .= " \"$field_name\" }";
898 $field_string_array .= ",";
899
900 if( $reg_ref->{field}->{$field_name}->{field_type} eq "NORMAL" ){
901 # build impl for getNative method
902 $get_native_string .= " |\n" if $get_native_string ne "";
903 $get_native_string .= " ( (0ULL |" . lc $field_name . ") << " .
904 $reg_ref->{field}->{$field_name}->{start_offset} . ")";
905
906 # build impl for setNative method
907 if( $reg_ref->{field}->{$field_name}->{protection} eq "RW" ){
908 my $mask = "(~0ULL >> (64 - $reg_ref->{field}->{$field_name}->{size}))";
909 $set_native_string .= " " . lc $field_name .
910 " = (____d >> $reg_ref->{field}->{$field_name}->{start_offset}) & $mask;\n";
911 }
912 elsif($reg_ref->{field}->{$field_name}->{protection} eq "RW1C"){
913 my $mask = "(~0ULL >> (64 - $reg_ref->{field}->{$field_name}->{size}))";
914 $set_native_string .= " " . lc $field_name .
915 " &= ~((____d >> $reg_ref->{field}->{$field_name}->{start_offset}) & $mask);\n";
916 }
917
918
919 # build impl for setNativeHW method
920 if( $reg_ref->{field}->{$field_name}->{protection} ne "RO" ){
921 my $mask = "(~0ULL >> (64 - $reg_ref->{field}->{$field_name}->{size}))";
922 $set_nativeHW_string .= " " . lc $field_name .
923 " = (____d >> $reg_ref->{field}->{$field_name}->{start_offset}) & $mask;\n";
924 }
925 }
926
927 }
928
929 $field_string_array =~ s/,\s*$//; # chop off the comma from the last entry
930 $field_string_array .= " }";
931
932 my ( $get_case_body, $set_case_body );
933 while( ($fn = pop @tmpList) ){
934 my $lc_fn = lc $fn;
935 my $uc_fn = uc $fn;
936 $equal_string .= " $lc_fn == rhs.$lc_fn";
937 $equal_string .= " &&\n" if @tmpList;
938
939 $printing_string .= " \"" . uc( $fn ) . "=\" << get$uc_fn() << \" \"";
940 $printing_string .= " <<\n" if @tmpList;
941
942 $get_case_body .=
943<<EO_GET_CASE
944 case $uc_fn:
945 return get$uc_fn();
946 break;
947EO_GET_CASE
948;
949 $set_case_body .=
950<<EO_SET_CASE
951 case $uc_fn:
952 set$uc_fn( value );
953 break;
954EO_SET_CASE
955;
956
957 }
958
959 my $comment_str = get_comment_string( $0, $xml_file );
960
961 # construct using declarations for each additional namespace
962 my $using_ns;
963 my $extra_ns_accum = "Riesling";
964 foreach my $ns ( split /,/, $opt_n ){
965 $extra_ns_accum .= "::$ns";
966 $using_ns .= "using namespace $extra_ns_accum;\n";
967 }
968
969
970print $file_handle <<EO_CCFILE
971$comment_str
972#include "$ifile_name"
973#include <sstream>
974
975using namespace std;
976using namespace Riesling;
977$using_ns
978EO_CCFILE
979if ! $opt_t;
980
981if (! $opt_t) {
982print $file_handle <<EO_CCFILE1
983
984const int ${class_scope}NR_FIELDS;
985$field_string_array;
986EO_CCFILE1
987;
988}
989
990if ($opt_t) {
991print $file_handle <<EO_CCFILE6
992
993$class_name()
994{
995 data = get_init();
996}
997
998~$class_name()
999{}
1000
1001$class_name( const $class_name& obj )
1002{
1003 data = obj.data;
1004}
1005EO_CCFILE6
1006}
1007else {
1008print $file_handle <<EO_CCFILE6
1009
1010${class_scope}$class_name()
1011{
1012 mask = $constructor_mask ;
1013 init = $constructor_init ;
1014 bits = $constructor_bits ;
1015 rw1c = $constructor_rw1c ;
1016 data = init;
1017}
1018
1019${class_scope}~$class_name()
1020{}
1021
1022${class_scope}$class_name( const $class_name& obj )
1023{
1024 data = obj.data;
1025 mask = obj.mask;
1026 rw1c = obj.rw1c;
1027 init = obj.init;
1028 bits = obj.bits;
1029}
1030EO_CCFILE6
1031;
1032}
1033
1034if (! $opt_t) {
1035
1036print $file_handle <<EO_CCFILE7
1037
1038$get_string
1039
1040$set_string
1041
1042uint32_t ${class_scope}getSize() const
1043{
1044 return $register_size;
1045}
1046
1047uint32_t ${class_scope}getSize( uint_t field ) const
1048{
1049 if( field >= NR_FIELDS ){
1050 RIESLING_THROW_INVALID_ARGUMENT( "Invalid field specifier." );
1051 }
1052 return ${class_scope}fieldData[ field ].size;
1053}
1054
1055uint32_t ${class_scope}getOffset( uint_t field ) const
1056{
1057 if( field >= NR_FIELDS ){
1058 RIESLING_THROW_INVALID_ARGUMENT( "Invalid field specifier." );
1059 }
1060 return ${class_scope}fieldData[ field ].offset;
1061}
1062
1063FieldObject::Protection ${class_scope}getProtection( uint_t field ) const
1064{
1065 if( field >= NR_FIELDS ){
1066 RIESLING_THROW_INVALID_ARGUMENT( "Invalid field specifier." );
1067 }
1068 return ${class_scope}fieldData[ field ].prot;
1069}
1070
1071const char* ${class_scope}getName() const
1072{
1073 return "$reg_ref->{name}";
1074}
1075
1076const char* ${class_scope}getName( uint_t field ) const
1077{
1078 if( field >= NR_FIELDS ){
1079 RIESLING_THROW_INVALID_ARGUMENT( "Invalid field specifier." );
1080 }
1081 return ${class_scope}fieldData[ field ].name;
1082}
1083
1084EO_CCFILE7
1085;
1086}
1087
1088print $file_handle <<EO_CCFILE8
1089
1090std::string ${class_scope}toString() const
1091{
1092 std::ostringstream os;
1093 os << std::hex << $printing_string;
1094 return os.str();
1095}
1096
1097void ${class_scope}print( std::ostream& os ) const
1098{
1099 os << toString();
1100}
1101EO_CCFILE8
1102if $opt_p;
1103
1104
1105print $file_handle "$agg_string\n;";
1106}
1107
1108####################################################################
1109####################################################################
1110####################################################################
1111
1112sub create_set_fn_decl
1113{
1114 my ( $class_name, $field_name, $field_size, $field_start, $prot) = @_;
1115 my ( $sz_type, $sz ) = get_native_type( $field_size );
1116 my $field_name_uc = uc $field_name;
1117 my $field_name_lc = lc $field_name;
1118
1119 my $rvalue = "(value << $field_start)";
1120 my $mask = "uint64_t field_mask = (~uint64_t(0) >> (64 - $field_size)) << $field_start;";
1121 $rvalue = "(data & ~field_mask) | ((value << $field_start) & field_mask)";
1122
1123 ## This is a little painful. Long time ago Riesling decided to make itself public, very public
1124 ## and that means that all registers are visible and accessable, including the set field methods.
1125 ## This is a grieving mistake. It should have been hidden, awell, now we have a problem ...
1126 ## If someone sets a field of a register and internally there is some side effect associated with that
1127 ## then we need to call a function or method that handles the side effect ... thank god for pointers
1128 ## to functions or methods ha style. All because the rshell allows for statements like
1129 ## $hpstate.HPRIV=1 ... and that needs a call ... and I don't know what the jshell does.
1130
1131 my $decl_string = "void set$field_name_uc( uint64_t value ) { $mask data=$rvalue; }\n";
1132 $decl_string .= "void set${field_name_uc}_Notify( uint64_t value ) { $mask call->call(this,$rvalue); }" if ! $opt_t;
1133
1134 if( $opt_o ){
1135 $decl_string = "virtual $decl_string";
1136 }
1137
1138<<EODECL
1139 //! set the value of $class_name.$field_name_uc
1140 $decl_string
1141EODECL
1142;
1143}
1144
1145####################################################################
1146####################################################################
1147####################################################################
1148
1149sub create_get_fn_decl
1150{
1151 my ( $class_name, $field_name, $field_size, $field_start ) = @_;
1152 my ( $sz_type, $sz ) = get_native_type( $field_size );
1153 my $field_name_uc = uc $field_name;
1154 my $field_name_lc = lc $field_name;
1155
1156 my $decl_string = "uint64_t get$field_name_uc( ) const { return (data >> $field_start) & (~uint64_t(0) >> (64 - $field_size));}";
1157
1158 if( $opt_o ){
1159 $decl_string = "virtual $decl_string";
1160 }
1161
1162<<EODECL
1163 //! return the value of $class_name.$field_name_uc
1164 $decl_string
1165EODECL
1166;
1167}
1168
1169####################################################################
1170####################################################################
1171####################################################################
1172
1173sub create_bitsize_decl
1174{
1175 my ( $class_name, $field_name, $field_size, $field_start ) = @_;
1176 my ( $sz_type, $sz ) = get_native_type( $field_size );
1177 my $field_name_uc = uc $field_name;
1178 my $field_name_lc = lc $field_name;
1179
1180 my $decl_string = "static const bitSize$field_name_uc = $field_size;";
1181
1182<<EODECL
1183 //! return the value of $class_name.$field_name_uc
1184 $decl_string
1185EODECL
1186;
1187}
1188
1189####################################################################
1190####################################################################
1191####################################################################
1192
1193sub get_comment_string
1194{
1195 my ( $generator, $source_file ) = @_;
1196 my $today = `date`;
1197 chomp $today;
1198 my $id_str = `id`;
1199 $id_str =~ /uid=(\d+)/;
1200 my( $user_login_name,$passwd,$uid,$gid,$quota,$comment,$user_full_name, @foo ) = getpwuid( $1 );
1201 my $short_gen = $generator;
1202 $short_gen =~ s#.*/##;
1203 my $pwd = `pwd`;
1204 chomp $pwd;
1205 $source_file = resolve_path( $pwd, $source_file );
1206
1207<<EOCOMMENT
1208/************************************************************************
1209**
1210**
1211** ****** MACHINE-GENERATED FILE ******
1212** ****** DO NOT EDIT BY HAND ******
1213**
1214** Generated from $source_file
1215** using $generator
1216** File created on $today by $user_full_name ($user_login_name)
1217**
1218** Command Line Used to Generate File:
1219** $short_gen @ORIG_ARGS
1220**
1221** Copyright (C) 2002, Sun Microsystems, Inc.
1222**
1223** Sun considers its source code as an unpublished, proprietary
1224** trade secret and it is available only under strict license provisions.
1225** This copyright notice is placed here only to protect Sun in the event
1226** the source is deemed a published work. Disassembly, decompilation,
1227** or other means of reducing the object code to human readable form
1228** is prohibited by the license agreement under which this code is
1229** provided to the user or company in possession of this copy.
1230*************************************************************************/
1231EOCOMMENT
1232;
1233}
1234
1235####################################################################
1236####################################################################
1237####################################################################
1238
1239sub resolve_path
1240{
1241 my ( $pwd, $path ) = @_;
1242 my $result;
1243 while( $path =~ s#\.\./## ){
1244 $pwd =~ s#/[^/]+$##;
1245 }
1246
1247 if( $path !~ m#^/# && $pwd !~ m#/$# ){
1248 $pwd .= '/';
1249 }
1250
1251 return $pwd . $path;
1252}
1253
1254
1255####################################################################
1256####################################################################
1257####################################################################
1258
1259sub get_register_documentation_string
1260{
1261 #my() = @_;
1262
1263
1264<<EOCOMMENT
1265EOCOMMENT
1266;
1267}
1268
1269####################################################################
1270####################################################################
1271####################################################################
1272
1273
1274sub print_field_table_doc
1275{
1276 my ( $file_handle, $reg_name, $field_ref, $reg_ref ) = @_;
1277 #################################
1278 ## Produce the table of register fields.
1279 #################################
1280 my @comments;
1281 my $orig_name = $~;
1282print $file_handle <<EOHEAD
1283$reg_name Field Specification
1284
1285Offset Size Name Description
1286------------------------------------------------------------------------------------------------
1287EOHEAD
1288;
1289 for my $o ( sort { $a <=> $b } keys %{$field_ref} ){
1290 my ($FMT_offset,$FMT_size,$FMT_name, $FMT_description);
1291 my $field_name = $field_ref->{$o};
1292
1293format COMMENT_INIT =
1294@>> @>> @<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
1295$FMT_offset,$FMT_size,$FMT_name, $FMT_description
1296 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~
1297$FMT_description
1298.
1299
1300 ( $FMT_description, @comments ) = split /\\n/, $reg_ref->{field}->{$field_name}->{comment};
1301 $FMT_offset = $reg_ref->{field}->{$field_name}->{start_offset};
1302 $FMT_size = $reg_ref->{field}->{$field_name}->{size};
1303 $FMT_name = $field_name;
1304 $file_handle->format_name( "COMMENT_INIT" );
1305
1306 write $file_handle;
1307
1308 while( @comments ){
1309 my $FMT_cont = shift @comments;
1310format COMMENT_CONT =
1311 ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~
1312$FMT_cont
1313.
1314 $file_handle->format_name( "COMMENT_CONT" );
1315 write $file_handle;
1316 }
1317
1318 }
1319 $~ = $orig_name;
1320}
1321
1322####################################################################
1323####################################################################
1324####################################################################
1325
1326sub fix_hash
1327{
1328 my ( $reg_ref ) = @_;
1329
1330 delete( $reg_ref->{field}->{field_type});
1331 delete( $reg_ref->{field}->{name} );
1332 delete( $reg_ref->{field}->{format} );
1333 delete( $reg_ref->{field}->{comment} );
1334 delete( $reg_ref->{field}->{start_offset} );
1335 delete( $reg_ref->{field}->{end_offset} );
1336 delete( $reg_ref->{field}->{protection} );
1337 delete( $reg_ref->{field}->{size} );
1338 delete( $reg_ref->{field}->{initial_value} );
1339}
1340
1341####################################################################
1342####################################################################
1343####################################################################
1344
1345sub validate
1346{
1347 my( $reg_ref ) = @_;
1348 my (%names, @bits);
1349 my $size = 0;
1350 my $max_offset = 0;
1351 for my $field_name ( keys (%{$reg_ref->{field}} ) ){
1352 $size += $reg_ref->{field}->{$field_name}->{size};
1353 $max_offset = $reg_ref->{field}->{$field_name}->{end_offset}
1354 if $max_offset < $reg_ref->{field}->{$field_name}->{end_offset};
1355 }
1356
1357 if( $size != $max_offset + 1 ){
1358 print STDERR "VALIDATION ERROR: Max end_offset is $max_offset but is size is $size\n.";
1359 return 0;
1360 }
1361
1362 for( my $i = 0; $i < $size; $i++ ){
1363 $bits[$i] = 0;
1364 }
1365
1366 for my $field_name ( keys (%{$reg_ref->{field}} ) ){
1367 # Duplicated name check
1368 if( defined $names{ $field_name } ){
1369 print STDERR "VALIDATION ERROR: duplicate field: $field_name\n";
1370 return 0;
1371 } else {
1372 $names{$field_name} = 1;
1373 }
1374
1375 if( $field_name =~ /^\W/ ){
1376 print STDERR "VALIDATION ERROR: $field_name must start with a letter or and underscore.\n";
1377 return 0;
1378 }
1379
1380 if( $field_name =~ /([^\w\d])/ ){
1381 print STDERR "VALIDATION ERROR: $field_name cannot contain the character $1.\n";
1382 return 0;
1383 }
1384
1385 # Check for offsets that are negative or too large.
1386 my $offset = $reg_ref->{field}->{$field_name}->{start_offset};
1387 if( $offset < 0 ){
1388 print STDERR "VALIDATION ERROR: $field_name.offset is negative\n";
1389 return 0;
1390 }
1391 if( $offset >= $size ){
1392 print STDERR "VALIDATION ERROR: $field_name.offset = $offset is greater than size = $size\n";
1393 return 0;
1394 }
1395
1396 my $field_size = $reg_ref->{field}->{$field_name}->{size};
1397 # Check for correct size
1398 if( $field_size < 1 ){
1399 print STDERR "VALIDATION ERROR: $field_name.size is less than one.\n";
1400 return 0;
1401 }
1402 if( $offset + $field_size - 1 >= $size ){
1403 print STDERR "VALIDATION ERROR: $field_name.offset ($offset) + $field_name.size ($field_size) is \
1404 greater than size ($size)\n";
1405 return 0;
1406 }
1407
1408 # Check for overlapping bits
1409 for( my $i = $offset; $i < ($offset + $field_size); $i++ ){
1410 if( $bits[$i] != 0 ){
1411 print STDERR "VALIDATION ERROR: $field_name overlaps with $bits[$i] at bit $i\n";
1412 return 0;
1413 } else {
1414 $bits[$i] = $field_name;
1415 }
1416 }
1417
1418 # Initial value check.
1419 my $initial_value = $reg_ref->{field}->{$field_name}->{initial_value};
1420 my $max_size = ( 2 ** $size ) - 1;
1421 if( $initial_value > $max_size ){
1422 print STDERR "WARNING: $field_name.intial_value is greater than maximum representable value for\n";
1423 print STDERR " $field_name. This value will be truncated.\n";
1424 $reg_ref->{field}->{$field_name}->{initial_value} &= $max_size;
1425 }
1426
1427 my $prot = $reg_ref->{field}->{$field_name}->{protection};
1428 if( $prot ne "RO" && $prot ne "RW" && $prot ne "WO" && $prot ne "RWH" && $prot ne "RW1C"){
1429 # RWH is used to indicate a field that is read-only by software,
1430 # but is writable by hardware, we need this to create setNativeHW,
1431 # to be used by (N2) testbench to force a value into an otherwise
1432 # read-only field.
1433 print STDERR "VALIDATION ERROR: $field_name.protection is not RO, RW, or WO [$prot]\n";
1434 return 0;
1435 }
1436 if ($prot eq "RWH"){
1437 print STDERR "IMPLEMENTATION CHANGE: RWH behaviour is available through setNativeHW which treats RO fields as RW\n";
1438 }
1439
1440 my $type = $reg_ref->{field}->{$field_name}->{field_type};
1441 if( $type ne "NORMAL" && $type ne "DONT_CARE" && $type ne "ZERO" ){
1442 print STDERR "VALIDATION ERROR: $field_name.field_type is not NORMAL, DONT_CARE, or ZERO.\n";
1443 return 0;
1444 }
1445
1446 my $comment = $reg_ref->{field}->{$field_name}->{comment};
1447 if( $type ne "NORMAL" && $comment != /\w/ ){
1448 print STDERR "VALIDATION WARNING: $field_name.comment appears to be blank\n";
1449 }
1450
1451 }
1452
1453 my @uncounted_bits;
1454 for( my $i = 0; $i < $size; $i++ ){
1455 if( $bits[$i] eq "0" ){
1456 push @uncounted_bits, $i;
1457 }
1458 }
1459
1460 if( @uncounted_bits > 0 ){
1461 print STDERR "VALIDATION ERROR: Bits @uncounted_bits are not part of any field.\n";
1462 return 0;
1463 }
1464
1465 return 1;
1466}
1467
1468
1469
1470
1471
1472__END__
1473
1474####################################################################
1475####################################################################
1476####################################################################
1477
1478
1479# POD documentation
1480
1481=head1 NAME
1482
1483xml2reg - Build a C++ implementation of a register from an XML specification.
1484
1485=head1 SYNOPSYS
1486
1487xml2reg [-hdrv] [ -n namespaces] [ -I path] [ -S path ] xml file ...
1488
1489=head1 DESCRIPTION
1490
1491xml2reg takes an XML file containing a specification for a register as input and generates the
1492corresponding C++ implemenation of that specification. All xml2reg-generated registers
1493implement the FieldObject interface. xml2reg documents the C++ files with appropriate
1494doxygen-compatible comments.
1495
1496=head1 OPTIONS
1497
1498=item B<-h>
1499
1500Print a usage summary.
1501
1502=item B<-d>
1503
1504Dump out the internal represenation (parse tree) of the XML file. This option is useful
1505for developers who wish to modify xml2reg.
1506
1507=item B<-v>
1508
1509Validate the XML file and then exit without generating any C++ output. This option is used
1510to ensure the correctness of the your XML register file specification. xml2reg performs a
1511number of sanity checks on your XML file. When an error in your XML file is discovered,
1512xml2reg will report the error to stderr an then exit with a nonzero status. Some problems with your
1513XML will generate warnings. A warning will be reported to stderr, but will not cause xml2reg to
1514exit. xml2reg will exit with zero status if your file has no errors but does generate warnings.
1515
1516=item B<-n> I<namespace list>
1517
1518Enclose the C++ implemenation in additional namespaces. By default, the C++ code generated by
1519xml2reg is placed in the Riesling namespace. This option is used to specify additional enclosing
1520namespaces. The namespaces are specified as a comma-separated list of namespaces with no intervening
1521whitespace. The the namespaces should be specified from in outermost to innermost order.
1522
1523=item B<-r>
1524
1525Generate code to make this register accessble from the object registry. Classes generated with this
1526can be instantiated and their instances manipulated Riesling's frontend.
1527
1528
1529=item B<-I> I<path>
1530
1531Specify the directory to which the generated header file (.h file) should be written.
1532
1533=item B<-S> I<path>
1534
1535Specify the directory to which the generated implemenation file (.cc file) should be written.
1536
1537=head1 EXAMPLES
1538
1539 xml2reg myreg.xml
1540
1541Generate C++ code for a single xml file. The resulting C++ files will be names myreg.h and myreg.cc.
1542The files will be written to the current working directory.
1543
1544 xml2reg *.xml
1545
1546Process all the XML files in the current directory. A .h and .cc file will be generated for each
1547XML file processed.
1548
1549 xml2reg -n Mmu -I /src/Riesling/include/mmu -S /src/Riesling/src/mmu MmuConfigReg.xml
1550
1551Generates C++ code for the XML file MmuConfigReg.xml. The the class is enclosed in the Mmu namespace.
1552The .h file is written to /src/Riesling/include/mmu/MmuConfigReg.h. The .cc file is written to
1553 /src/Riesling/include/mmu/MmuConfigReg.cc.
1554
1555
1556=head1 SEE ALSO
1557
1558XML::Simple, FileHandle, process_xml(1)
1559
1560=head1 BUGS
1561
1562Errors parsing the XML file will be reported by XML::Simple, and these errors can be cryptic.
1563
1564
1565=head1 NOTES
1566
1567See the document I<Riesling Register Specification> for a complete discussion
1568of the XML specification.