File Coverage

blib/lib/SystemC/Vregs/Output/Class.pm
Criterion Covered Total %
statement 46 379 12.1
branch 4 176 2.2
condition 2 83 2.4
subroutine 8 17 47.0
pod 3 7 42.8
total 63 662 9.5


line stmt bran cond sub pod time code
1             # See copyright, etc in below POD section.
2             ######################################################################
3              
4             package SystemC::Vregs::Output::Class;
5 1     1   474 use SystemC::Vregs::File;
  1         3  
  1         25  
6 1     1   7 use SystemC::Vregs::Number;
  1         2  
  1         31  
7 1     1   5 use SystemC::Vregs::Language;
  1         2  
  1         14  
8 1     1   4 use Carp;
  1         1  
  1         44  
9 1     1   4 use strict;
  1         1  
  1         23  
10 1     1   4 use vars qw($VERSION);
  1         2  
  1         5298  
11              
12             $VERSION = '1.470';
13              
14             ######################################################################
15             # CONSTRUCTOR
16              
17             sub new {
18 0     0 0 0 my $class = shift;
19 0         0 my $self = {@_};
20 0         0 bless $self, $class;
21 0         0 return $self;
22             }
23              
24             ######################################################################
25             ######################################################################
26             ######################################################################
27             ######################################################################
28              
29             sub enum_write {
30 0     0 0 0 my $self = shift;
31 0         0 my $typeref = shift;
32 0         0 my $pack = shift;
33 0         0 my $fl = shift;
34              
35 0   0     0 my $clname = $typeref->{name} || "x";
36 0         0 $pack->{rules}->execute_rule ('enum_begin_before', $clname, $typeref);
37 0         0 $fl->print ("class $clname {\n");
38 0         0 $fl->print ("public:\n");
39 0         0 $pack->{rules}->execute_rule ('enum_begin_after', $clname, $typeref);
40              
41 0         0 $fl->print (" enum en {\n");
42 0         0 $self->_enum_write_center($typeref,$pack,$fl);
43 0         0 $fl->print (" };\n");
44 0         0 $pack->{rules}->execute_rule ('enum_end_before', $clname, $typeref);
45 0         0 $fl->print (" };\n");
46 0         0 $pack->{rules}->execute_rule ('enum_end_after', $clname, $typeref);
47 0         0 $fl->print ("\n");
48             }
49              
50             sub enum_struct_write {
51 2     2 0 3 my $self = shift;
52 2         3 my $typeref = shift;
53 2         6 my $pack = shift;
54 2         3 my $fl = shift;
55              
56 2   50     23 my $clname = $typeref->{typedef_name} || $typeref->{name} || "x";
57 2         9 $fl->print ("typedef enum {\n");
58 2         13 $self->_enum_write_center($typeref,$pack,$fl);
59 2         11 $fl->print ("} $clname;\n");
60 2         8 $fl->print ("\n");
61             }
62              
63             sub _enum_write_center {
64 2     2   2 my $self = shift;
65 2         4 my $typeref = shift;
66 2         3 my $pack = shift;
67 2         4 my $fl = shift;
68              
69 2         5 my $c = $fl->{C}; # Not C++
70 2 50 33     15 my $cClname = $c ? ($typeref->{typedef_name} || $typeref->{name})."_":"";
71              
72 2         3 my $width = 13;
73 2         12 foreach my $fieldref ($typeref->fields_sorted()) {
74 15 50       38 $width = length($fieldref->{name}) if length($fieldref->{name})>$width;
75             }
76 2         6 foreach my $fieldref ($typeref->fields_sorted()) {
77 15         85 $fl->printf ("\t${cClname}%-${width}s = 0x%x,"
78             ,$fieldref->{name},$fieldref->{rst_val});
79 15 50       50 if ($pack->{comments}) {
80 15         36 $fl->printf ("\t");
81 15         60 $fl->comment_post ($fieldref->{desc});
82             }
83 15         45 $fl->printf ("\n");
84             }
85             # Perhaps this should just be added to the data structures?
86             # note no comma to make C happy
87 2 50       10 if ($typeref->{bits}==32) {
88             # Can't put out 1_0000_0000 or C won't fit it into a enum
89             # We'll be weedy and subtract one. We'll check no value of the users would collide
90             # with our little lie.
91 0         0 $fl->printf("\t${cClname}%-${width}s = 0x%x\t","MAX", ((1<<$typeref->{bits})-1));
92 0         0 $fl->comment_post ("MAXIMUM (-1 adjusted so will fit in 32-bits)");
93 0         0 foreach my $fieldref ($typeref->fields_sorted()) {
94 0 0       0 if ($fieldref->{rst_val} >= ((1<<$typeref->{bits})-1)) {
95 0         0 $fieldref->warn ("0xffffffff isn't representable in 32-bit enum, as MAX won't fit.\n");
96             }
97             }
98             } else {
99 2         13 $fl->printf("\t${cClname}%-${width}s = 0x%x\t","MAX", (1<<$typeref->{bits}));
100 2         7 $fl->comment_post ("MAXIMUM+1");
101             }
102 2         8 $fl->print ("\n");
103             }
104              
105             sub enum_cpp_write {
106 0     0 0   my $self = shift;
107 0           my $typeref = shift;
108 0           my $pack = shift;
109 0           my $fl = shift;
110              
111 0   0       my $clname = $typeref->{name} || "x";
112              
113 0           $fl->print("//${clname}\n",);
114 0           $pack->{rules}->execute_rule ('enum_cpp_before', $clname, $typeref);
115              
116 0           for my $desc (0..1) {
117 0 0 0       next if $desc && !$typeref->attribute_value('descfunc');
118              
119 0 0         $fl->printf ("const char* ${clname}::%s () const {\n",
120             ($desc ? 'description':'ascii'));
121 0           $fl->print (" switch (m_e) {\n");
122 0           my %did_values;
123 0           foreach my $fieldref ($typeref->fields_sorted()) {
124 0 0 0       next if $desc && $fieldref->{omit_description};
125 0 0         if ($did_values{$fieldref->{rst_val}}) {
126 0           $fl->printf ("\t//DUPLICATE: ");
127             } else {
128 0           $fl->printf ("\t");
129             }
130 0 0         $fl->printf ("case %s: return(\"%s\");\n"
131             ,$fieldref->{name}
132             ,($desc ? $fieldref->{desc} : $fieldref->{name}));
133 0           $did_values{$fieldref->{rst_val}} = 1;
134             }
135 0           $fl->print ("\tdefault: return (\"?E\");\n");
136 0           $fl->print (" }\n");
137 0           $fl->print ("}\n\n");
138             }
139              
140             {
141 0           $fl->printf ("${clname}::iterator ${clname}::iterator::operator++() {\n");
  0            
142 0           $fl->print (" switch (m_e) {\n");
143 0           my %next_values;
144             my $last;
145 0           foreach my $fieldref ($typeref->fields_sorted()) {
146 0 0 0       if (!defined $last || $fieldref->{rst_val} ne $last->{rst_val}) {
147 0 0         if ($last) {
148 0 0         if ($fieldref->{rst_val} == $last->{rst_val}+1) {
149 0           $next_values{inc}{$last->{name}} = "${clname}(m_e + 1)";
150             } else {
151 0           $next_values{expr}{$last->{name}} = $fieldref->{name};
152             }
153             }
154 0           $last = $fieldref;
155             }
156             }
157             # Note final value isn't in next_values; the default will catch it.
158 0           foreach my $inc ("inc", "expr") {
159 0           my @fields = (sort keys %{$next_values{$inc}});
  0            
160 0           for (my $i=0; $i<=$#fields; ++$i) {
161 0           my $field = $fields[$i];
162 0           my $next_field = $fields[$i+1];
163 0           $fl->printf ("\tcase %s:",$field);
164 0 0 0       if ($next_field && $next_values{$inc}{$field} eq $next_values{$inc}{$next_field}) {
165 0           $fl->printf (" /*FALLTHRU*/\n");
166             } else {
167 0           $fl->printf (" m_e=%s; return *this;\n"
168             ,$next_values{$inc}{$field});
169             }
170             }
171             }
172 0           $fl->print ("\tdefault: m_e=MAX; return *this;\n");
173 0           $fl->print (" }\n");
174 0           $fl->print ("}\n\n");
175             }
176              
177 0           $pack->{rules}->execute_rule ('enum_cpp_after', $clname, $typeref);
178             }
179              
180             ######################################################################
181             ######################################################################
182             ######################################################################
183             #### Saving
184              
185             sub _class_h_write_dw {
186 0     0     my $self = shift;
187 0           my $typeref = shift;
188 0           my $pack = shift;
189 0           my $fl = shift;
190              
191 0           my $wget = $fl->call_str($typeref->{name},"","w(");
192 0           my $wset = $fl->call_str($typeref->{name},"set","w(");
193              
194 0 0 0       if (($typeref->{words}||0) > 1) {
195             # make full dw accessors if the type is >32 bits
196 0           $fl->fn($typeref->{name},"","inline uint64_t dw(int b) const",
197             ,"{\n"
198             ."\tunion {uint64_t udw; uint32_t lw[2];} u;\n"
199             ."\tu.lw[0]=${wget}b*2+0); u.lw[1]=${wget}b*2+1); return u.udw; }\n");
200 0           $fl->fn($typeref->{name},"set","inline void dw(int b, uint64_t val)"
201             ,"{\n"
202             ."\tunion {uint64_t udw; uint32_t lw[2];} u;\n"
203             ."\tu.udw=val; ${wset}b*2+0,u.lw[0]); ${wset}b*2+1,u.lw[1]); }\n");
204             } else {
205             # still make dw accessors, but don't read or write w[1] because
206             # it doesn't exist.
207 0           $fl->fn($typeref->{name},"","inline uint64_t dw(int b) const"
208             ,"{\n"
209             ."\tunion {uint64_t udw; uint32_t lw[2];} u;\n"
210             ."\tu.lw[0]=${wget}b*2+0); u.lw[1]=0; return u.udw; }\n");
211 0           $fl->fn($typeref->{name},"set","inline void dw(int b, uint64_t val)"
212             ,"{\n"
213             ."\tunion {uint64_t udw; uint32_t lw[2];} u;\n"
214             ."\tu.udw=val; ${wset}b*2+0,u.lw[0]); }\n");
215             }
216             }
217              
218              
219             sub _class_h_write {
220 0     0     my $self = shift;
221 0           my $typeref = shift;
222 0           my $pack = shift;
223 0           my $fl = shift;
224 0   0       my $clname = $typeref->{name} || "x";
225              
226 0           my $c = $fl->{C}; # Not C++
227 0 0         my $cClname = $c ? "${clname}_":"";
228 0 0         my $cThis = $c ? "thisp->":"";
229 0 0         my $cForInt = $c ? "int i; for (" : "for (int ";
230 0           my $wget = $fl->call_str($clname,"","w(");
231 0           my $wset = $fl->call_str($clname,"set","w(");
232              
233 0   0       my $netorder = $typeref->attribute_value('netorder') || 0;
234 0   0       my $stretchable = $typeref->attribute_value('stretchable') || 0;
235 0 0         my $ntohl = ($netorder ? "ntohl" : "");
236 0 0         my $htonl = ($netorder ? "htonl" : "");
237 0 0         my $uint = ($netorder ? "nint32_t" : "uint32_t");
238 0 0         my $uint64 = ($netorder ? "nint64_t" : "uint64_t");
239 0 0         my $uchar = ($netorder ? "nint8_t" : "uint8_t");
240 0 0         my $toBytePtr = ($netorder ? "castNBytep" : "castHBytep");
241              
242 0           my $inh = "";
243 0 0         $inh = " : $typeref->{inherits}" if $typeref->{inherits};
244 0 0         $inh = "" if $c;
245 0           my $words = $typeref->{words};
246              
247 0 0         if ($c) {
248 0           $fl->print("typedef struct {\n");
249 0 0         $fl->print(" ${uint} m_w[${words}];"
250             .($stretchable ? " // Attr '-stretchable'\n" : "\n")
251             ."} $clname;\n");
252             } else {
253 0           $pack->{rules}->execute_rule ('class_begin_before', $clname, $typeref);
254 0           $fl->print("struct $clname$inh {\n");
255 0           $fl->set_private(0); # struct implies public:
256 0           $pack->{rules}->execute_rule ('class_begin_after', $clname, $typeref);
257             }
258 0           $fl->set_private(0); # struct implies public:
259              
260 0 0         if ($inh ne "") {
261 0 0         my $inhType = $typeref->{inherits_typeref} or
262             die "%Error: Missing typeref for inherits${inh}.\n";
263             # Verify same byte ordering.
264 0   0       my $inh_netorder = $inhType->attribute_value('netorder') || 0;
265 0 0         if ($inh_netorder ne $netorder) {
266 0           die ("%Error: $clname netorder=$netorder doesn't match $inh_netorder"
267             ." inherited from $inhType->{name}.\n");
268             }
269 0           $fl->print(" // w() and $toBytePtr() inherited from $typeref->{inherits}::\n");
270             # Correct for any size difference
271 0 0         (defined $inhType->{words}) or die "%Error: Missed words compute()\n";
272 0 0 0       if (($typeref->{words}||0) > $inhType->{words}) {
273             # Ensure the parent type disabled array bounds checking.
274 0   0       my $inh_stretchable = $inhType->attribute_value('stretchable') || 0;
275 0 0         if (! $inh_stretchable) {
276 0           die sprintf("%%Error: Base class %s (%d words) needs '-stretchable'"
277             ." since %s has %d words.\n",
278             $inhType->{name}, $inhType->{words},
279             $clname, $typeref->{words});
280             }
281 0           $fl->printf(" protected: uint32_t m_wStretch[%d]; // Bring base size up\n"
282             ." public:\n",
283             $typeref->{words} - $typeref->{inherits_typeref}->{words});
284             }
285             } else {
286 0 0         if (!$c) {
287 0 0         $fl->print(" protected: ${uint} m_w[${words}];"
288             .($stretchable ? " // Attr '-stretchable'\n" : "\n")
289             ." public:\n");
290             }
291 0           $fl->fn($clname, "", "inline uint32_t w(int b) const"
292             ,"{ return (${ntohl}(${cThis}m_w[b])); }\n");
293 0           $fl->fn($clname, "set", "inline void w(int b, uint32_t val)"
294             ,"{");
295 0 0         if (! $stretchable) {
296 0           $fl->print(" VREGS_WORDIDX_CHK($clname, $words, b)\n"
297             ."\t\t\t\t\t");
298             }
299 0           $fl->print(" ${cThis}m_w[b] = ${htonl}(val); }\n");
300 0           _class_h_write_dw($self,$typeref,$pack,$fl);
301              
302 0 0         if (!$c) {
303 0           $fl->fn($clname, "", "inline ${uchar}* ${toBytePtr}()"
304             ,"{\n"
305             ,"\treturn reinterpret_cast<${uchar}*>(&m_w[0]); }\n");
306 0           $fl->fn($clname, "", "inline const ${uchar}* ${toBytePtr}() const"
307             ,"{\n"
308             ,"\treturn reinterpret_cast(&m_w[0]); }\n");
309             }
310             }
311 0 0         if ($clname =~ /^R_/) {
312             # Write only those bits that are marked access writable
313 0           my @wr_masks;
314 0           for (my $word=0; $word<$typeref->{words}; $word++) {
315 0           $wr_masks[$word] = 0;
316 0           for (my $bit=$word*$typeref->{pack}->{word_bits};
317             $bit<(($word+1)*$typeref->{pack}->{word_bits});
318             $bit++) {
319 0           my $bitent = $typeref->{bitarray}[$bit];
320 0 0         next if !$bitent;
321 0 0         $wr_masks[$word] |= (1<<($bit & ($typeref->{pack}->{word_bits}-1)))
322             if ($bitent->{write});
323             }
324             }
325 0 0 0       if ($typeref->{words}>0 && $typeref->{words}<2 && !$c) {
      0        
326 0           $fl->printf(" static const uint32_t BITMASK_WRITABLE = 0x%08x;\n", $wr_masks[0]);
327 0           $fl->fn($clname, "", "inline void wWritable(int b, uint32_t val)"
328             ,"{ ${wset}b,(val&BITMASK_WRITABLE)|(${wget}b)&~BITMASK_WRITABLE)); }\n");
329             } else {
330             # Grrr, Greenhills Compilers don't allow
331             # static const uint32_t BITMASK_WRITABLE[] = {...};
332 0           $fl->fn($clname,"","inline uint32_t wBitMaskWritable(int b)"
333             ,"{\n");
334 0           for (my $word=0; $word<$typeref->{words}; $word++) {
335 0           $fl->printf("\tif (b==$word) return 0x%08x;\n", $wr_masks[$word]);
336             }
337 0           $fl->printf("\treturn 0; }\n");
338 0           my $fwritable = $fl->call_str($clname,"","wBitMaskWritable(b)");
339 0           $fl->fn($clname,"","inline void wWritable(int b, uint32_t val)"
340             ,"{ ${wset}b,(val&${fwritable})|(${wget}b)&~${fwritable})); }\n");
341             }
342             }
343              
344 0           my @resets=();
345 0 0         if ($typeref->{inherits}) {
346 0 0         if ($c) {
347 0           my $call = $fl->call_str($typeref->{inherits},"","fieldsReset();\n");
348 0           $call =~ s/\(/(($typeref->{inherits}*)/; # Need a cast
349 0           push @resets, "\t".$call;
350             } else {
351 0           push @resets, "\t".$typeref->{inherits}."::fieldsReset();\n";
352             }
353             }
354 0           my @dumps = ();
355 0           $fl->printf("\n");
356              
357 0 0         my @fields = $c ? ($typeref->fields_sorted_inherited()) : ($typeref->fields_sorted());
358              
359 0           foreach my $bitref (@fields) {
360 0 0         next if $bitref->ignore;
361 0           (my $lc_mnem = $bitref->{name}) =~ s/^(.)/lc $1/xe;
  0            
362              
363 0           my $typecast = "";
364 0 0         $typecast = $bitref->{type} if $bitref->{cast_needed};
365 0 0 0       $typecast = "($typecast)" if $c && $typecast ne "";
366 0 0         $typecast = "(void*)" if $bitref->{type} eq 'void*'; # Damn C++
367 0 0         my $L = ($bitref->{numbits}>32)?'LL':'';
368              
369 0           my $extract = "";
370 0           my $deposit = "";
371 0 0 0       if ($bitref->{numbits} < 32 && $bitref->{numbits} > 1) {
372             # Don't bother adding code to check boolean fields.
373 0 0         $deposit .=
374             sprintf(" VREGS_SETFIELD_CHK%s(\"%s.%s\", b, 0x%xU)\n\t\t\t\t\t\t",
375             ($L ? "_$L" : ""), $clname, $lc_mnem,
376             (1 << $bitref->{numbits})-1);
377             }
378 0           foreach my $bitrange (@{$bitref->{bitlist_range_32}}) {
  0            
379 0           my ($msb,$lsb,$nbits,$srcbit) = @{$bitrange};
  0            
380 0           my $low_mod = $lsb % 32;
381 0           my $high_mod = $msb % 32;
382 0           my $word = int($lsb/32);
383 0 0         (int($msb/32)==$word) or die "%Error: One _range cannot span two words\n";
384 0           my $deposit_mask = (1<<$nbits)-1;
385 0 0         $deposit_mask = 0xffffffff if $nbits==32;
386 0           my $mask = $deposit_mask << $low_mod;
387 0 0 0       $mask = 0xffffffff if $high_mod==31 && $low_mod==0;
388              
389 0 0         $extract .= " |" if $extract ne "";
390 0 0 0       if ($high_mod==31 && $low_mod==0 && $srcbit==0) {
      0        
391             # Whole word, skip the B.S.
392 0           $extract .= " ${wget}${word})";
393 0           $deposit .= " ${wset}${word}, (uint32_t)(b));";
394             } else {
395 0           my $tobit = "<<$srcbit)";
396 0 0         $tobit = "" if $srcbit==0;
397 0           my $frombit = ">>$srcbit)";
398 0 0         $frombit = "" if $srcbit==0;
399 0 0         $extract .= sprintf " %s(${wget}${word})>>${low_mod} & 0x%x$L)$tobit"
400             , ($tobit?"(":""), $deposit_mask;
401 0           my $b = "b";
402 0 0         $b = "(".$b.$frombit if $frombit;
403 0 0         $b = "((uint32_t)($b))" if $bitref->{type} ne 'uint32_t';
404 0           $deposit .= sprintf " ${wset}${word}, (${wget}${word})&0x%08x$L)"
405             ." | ((%s&0x%x$L)<<${low_mod}));"
406             , (~$mask&0xffffffff),
407             , $b
408             , $deposit_mask;
409             }
410             }
411              
412             # Mask after shifting on reads, so the mask is a smaller constant.
413 0           $fl->private_not_public (!$bitref->{access_read}, $pack);
414 0           my $typEnd = 11 + length $bitref->{type};
415 0 0         $fl->fn($clname,"",sprintf("inline %s%s%-13s () const",
    0          
416             $bitref->{type}, ($typEnd < 16 ? "\t\t" : $typEnd < 24 ? "\t" : " "),
417             $lc_mnem)
418             ,"{ return ${typecast}(${extract} ); }\n");
419 0 0 0       if ($typeref->attribute_value('public_rdwr_accessors') && $fl->{private} && $fl->{CPP}) {
      0        
420 0           $fl->private_not_public(0);
421 0 0         $fl->fn($clname,"",sprintf("inline %s%s%-13s () const",
    0          
422             $bitref->{type}, ($typEnd < 16 ? "\t\t" : $typEnd < 24 ? "\t" : " "),
423             $lc_mnem."_private")
424             ,"{ return $lc_mnem(); }\n");
425             }
426              
427 0           $fl->private_not_public (!$bitref->{access_write}, $pack);
428 0           $fl->fn($clname,"set",sprintf("inline void\t\t%-13s (%s b)", $lc_mnem, $bitref->{type})
429             ,"{${deposit} }\n");
430 0 0 0       if ($typeref->attribute_value('public_rdwr_accessors') && $fl->{private} && $fl->{CPP}) {
      0        
431 0           $fl->private_not_public(0);
432 0           $fl->fn($clname,"set",sprintf("inline void\t\t%-13s (%s b)", $lc_mnem."_private", $bitref->{type})
433             ,"{ ${lc_mnem}(b); }\n");
434             }
435              
436 0           push @dumps, "\"$bitref->{name}=\"<<$lc_mnem()";
437              
438 0 0         if ($bitref->{rst} ne 'X') {
439 0           my $rst = $bitref->{rst};
440 0 0         $rst = 0 if ($rst =~ /^FW-?0$/);
441 0 0 0       if ($rst =~ /^[a-z]/i && $bitref->{type}) { # Probably a enum value
    0          
442 0 0         if ($c) {
443 0           $rst = "$bitref->{type}_$rst";
444             } else {
445 0           $rst = "$bitref->{type}::$rst";
446             }
447             } elsif ($rst =~ /^0x([0-9a-f_]+)$/i) { # May need ULLs added
448 0           $rst = $fl->sprint_hex_value($1,$bitref->{numbits});
449             }
450             #$fl->printf("\tstatic const %s %s = %s;\n", $bitref->{type},
451             # uc($lc_mnem)."_RST", $rst);
452 0           push @resets, $fl->call_str($clname,"set",sprintf("\t%s(%s);\n", $lc_mnem, $rst));
453             }
454             }
455              
456 0           $fl->printf("\n");
457 0           $fl->private_not_public (0, $pack);
458 0 0         if (!$c) {
459 0           $fl->printf(" VREGS_STRUCT_DEF_CTOR(%s, %s)\t// (typeName, numWords)\n",
460             $clname, $words);
461             }
462              
463 0           $fl->fn($clname,"","inline void fieldsZero()"
464             ,"{\n");
465 0 0         if ($words>=8) {
466 0           $fl->print("\t${cForInt}i=0; i<${words}; i++) ${wset}i,0);\n");
467             } else {
468 0           $fl->print("\t");
469 0           for (my $i=0; $i<$words; $i++) {
470 0 0         $fl->print(" ") if $i!=0;
471 0           $fl->print("${wset}$i,0);");
472             }
473 0           $fl->print("\n");
474             }
475 0           $fl->print(" }\n");
476              
477 0           $fl->fn($clname,"","inline void fieldsReset()"
478             ,"{\n"
479             ,"\t",$fl->call_str($clname,"","fieldsZero();\n")
480             ,@resets
481             ," }\n");
482              
483 0 0         if (!$c) {
484 0           $fl->fn($clname,"","inline bool operator== (const ${clname}& rhs) const"
485             ,"{\n"
486             ,"\t${cForInt}i=0; i<${words}; i++) { if (m_w[i]!=rhs.m_w[i]) return false; }\n"
487             ,"\treturn true;\n"
488             ," }\n");
489             # The dump functions are in a .cpp file (no inline), as there was too much code
490             # bloat, and it was taking a lot of compile time.
491 0           $fl->print(" typedef VregsOstream<${clname}> DumpOstream;\n",
492             " DumpOstream dump(const char* prefix=\"\\n\\t\") const;\n",
493             " OStream& _dump(OStream& lhs, const char* pf) const;\n",
494             " void dumpCout() const; // For GDB\n",);
495              
496             # Put const's last to avoid GDB stupidity
497 0           $fl->private_not_public (0, $pack);
498 0           $fl->printf(" static const size_t SIZE = %d;\n", $words*4);
499              
500 0           $pack->{rules}->execute_rule ('class_end_before', $clname, $typeref);
501 0           $fl->print("};\n");
502 0           $pack->{rules}->execute_rule ('class_end_after', $clname, $typeref);
503              
504 0           $fl->print(" OStream& operator<< (OStream& lhs, const ${clname}::DumpOstream rhs);\n",);
505             }
506              
507 0           $fl->print("\n");
508             }
509              
510             ######################################################################
511             ######################################################################
512             ######################################################################
513              
514             sub _class_cpp_write {
515 0     0     my $self = shift;
516 0           my $typeref = shift;
517 0           my $pack = shift;
518 0           my $fl = shift;
519 0   0       my $clname = $typeref->{name} || "x";
520              
521 0           my @dumps = ();
522              
523 0   0       my $fields_lcFirst = $typeref->attribute_value('lcfirst') || 0;
524 0           foreach my $bitref ($typeref->fields_sorted()) {
525 0 0         next if $bitref->ignore;
526 0           (my $lc_mnem = $bitref->{name}) =~ s/^(.)/lc $1/xe;
  0            
527 0 0 0       if ($typeref->{inherits_typeref}
    0          
528             && $typeref->{inherits_typeref}->find_bit($bitref->{name})) {
529             # It's printed by the base class.
530             } elsif ($fields_lcFirst) {
531 0           push @dumps, "\"$lc_mnem=\"<<$lc_mnem()";
532             } else {
533 0           push @dumps, "\"$bitref->{name}=\"<<$lc_mnem()";
534             }
535             }
536              
537 0           $fl->print("//${clname}\n",);
538 0           $pack->{rules}->execute_rule ('class_cpp_before', $clname, $typeref);
539 0   0       my $dumpName = $SystemC::Vregs::Dump_Routine_Name || "_dump";
540 0           $fl->print("${clname}::DumpOstream ${clname}::dump(const char* prefix) const {\n",
541             " return DumpOstream(this,prefix);\n",
542             "}\n");
543 0           $fl->print("OStream& operator<< (OStream& lhs, const ${clname}::DumpOstream rhs) {\n",
544             " return ((${clname}*)rhs.obj())->${dumpName}(lhs,rhs.prefix());\n",
545             "}\n");
546              
547 0           $SystemC::Vregs::Do_Dump = 0;
548 0           $pack->{rules}->execute_rule ('class_dump_before', $clname, $typeref);
549 0 0         if ($SystemC::Vregs::Do_Dump) {
550 0 0 0       $fl->printf("OStream& ${clname}::_dump (OStream& lhs, const char*%s) const {\n",
551             ((($#dumps>0) || $typeref->{inherits}) ? ' pf':''));
552 0           $pack->{rules}->execute_rule ('class_dump_after', $clname, $typeref, \@dumps);
553 0           $fl->print(" return lhs;\n"
554             ."}\n");
555             }
556              
557             # For usage in GDB
558 0           $fl->print("void ${clname}::dumpCout () const { COUT<dump(\"\\n\\t\")<
559 0           $pack->{rules}->execute_rule ('class_cpp_after', $clname, $typeref);
560              
561 0           $fl->print("\n");
562             }
563              
564             ######################################################################
565             ######################################################################
566             ######################################################################
567              
568             sub write_class_h {
569             # Dump type definitions
570 0     0 1   my $self = shift;
571 0           my %params = (pack => $self->{pack},
572             @_);
573 0 0         my $pack = $params{pack} or croak "%Error: No pack=> parameter passed,";
574              
575 0           my $fl = SystemC::Vregs::File->open(rules => $pack->{rules},
576             language=>'CPP', @_);
577              
578 0           $fl->include_guard();
579 0           $fl->print("\n");
580 0           $fl->comment("package $pack->{name}\n");
581 0           $fl->print("\n");
582              
583 0           $pack->{rules}->execute_rule ('file_body_before', 'file_body', $pack);
584              
585 0           $fl->print("// Vregs library Files:\n");
586 0           foreach my $packref (@{$pack->{libraries}}) {
  0            
587 0           $fl->print("#include \"$packref->{name}_class.h\"\n");
588             }
589              
590 0           $fl->print("\n\n");
591              
592 0           foreach my $typeref ($pack->enums_sorted) {
593 0           enum_write ($self, $typeref, $pack, $fl);
594             }
595              
596 0           $fl->print("\n\n");
597             # Bitbashing done verbosely to avoid slow preprocess time
598             # We could use bit structures, but they don't work on non-contiguous fields
599              
600             # Sorted first does base classes, then children
601 0           foreach my $typeref ($pack->types_sorted) {
602 0 0         next if $typeref->attribute_value('nofielddefines');
603 0           _class_h_write($self,$typeref,$pack, $fl);
604             }
605              
606 0           $pack->{rules}->execute_rule ('file_body_after', 'file_body', $pack);
607              
608 0           $fl->close();
609             }
610              
611             sub write_struct_h {
612             # Dump type definitions
613 0     0 1   my $self = shift;
614 0           my %params = (pack => $self->{pack},
615             @_);
616 0 0         my $pack = $params{pack} or croak "%Error: No pack=> parameter passed,";
617              
618 0           my $fl = SystemC::Vregs::File->open(rules => $pack->{rules},
619             language=>'C', @_);
620              
621 0           $fl->include_guard();
622 0           $fl->print("\n");
623 0           $fl->comment("package $pack->{name}\n");
624 0           $fl->print("\n");
625              
626 0           $pack->{rules}->execute_rule ('file_body_before', 'file_body', $pack);
627              
628 0           $fl->print("// Vregs library Files:\n");
629 0           foreach my $packref (@{$pack->{libraries}}) {
  0            
630 0           $fl->print("#include \"$packref->{name}_struct.h\"\n");
631             }
632              
633 0           $fl->print("\n\n");
634              
635 0           foreach my $typeref ($pack->enums_sorted) {
636 0           enum_struct_write ($self, $typeref, $pack, $fl);
637             }
638              
639 0           $fl->print("\n\n");
640             # Bitbashing done verbosely to avoid slow preprocess time
641             # We could use bit structures, but they don't work on non-contiguous fields
642              
643             # Sorted first does base classes, then children
644 0           foreach my $typeref ($pack->types_sorted) {
645 0 0         next if $typeref->attribute_value('nofielddefines');
646 0           _class_h_write($self,$typeref,$pack, $fl);
647             }
648              
649 0           $pack->{rules}->execute_rule ('file_body_after', 'file_body', $pack);
650              
651 0           $fl->close();
652             }
653              
654             sub write_class_cpp {
655 0     0 1   my $self = shift;
656 0           my %params = (pack => $self->{pack},
657             @_);
658 0 0         my $pack = $params{pack} or croak "%Error: No pack=> parameter passed,";
659             # Dump type definitions
660              
661 0           my $fl = SystemC::Vregs::File->open(rules => $pack->{rules},
662             language=>'CPP', @_);
663              
664 0           $fl->print("\n");
665 0           $fl->print("#include \"$pack->{name}_class.h\"\n");
666 0           $fl->print("\n");
667              
668 0           $pack->{rules}->execute_rule ('class_cpp_file_before', 'file_body', $pack);
669              
670 0           foreach my $typeref ($pack->enums_sorted) {
671 0           $self->enum_cpp_write ($typeref, $pack, $fl);
672             }
673              
674             # Sorted first does base classes, then children
675 0           foreach my $typeref ($pack->types_sorted) {
676 0 0         next if $typeref->attribute_value('nofielddefines');
677 0           $self->_class_cpp_write($typeref,$pack, $fl);
678             }
679              
680 0           $fl->close();
681             }
682              
683             ######################################################################
684             #### Package return
685             1;
686             __END__