# See copyright, etc in below POD section.
######################################################################
package SystemC::Vregs::Output::Class;
use SystemC::Vregs::File;
use SystemC::Vregs::Number;
use SystemC::Vregs::Language;
use Carp;
use strict;
use vars qw($VERSION);
$VERSION = '1.470';
######################################################################
# CONSTRUCTOR
sub new {
my $class = shift;
my $self = {@_};
bless $self, $class;
return $self;
}
######################################################################
######################################################################
######################################################################
######################################################################
sub enum_write {
my $self = shift;
my $typeref = shift;
my $pack = shift;
my $fl = shift;
my $clname = $typeref->{name} || "x";
$pack->{rules}->execute_rule ('enum_begin_before', $clname, $typeref);
$fl->print ("class $clname {\n");
$fl->print ("public:\n");
$pack->{rules}->execute_rule ('enum_begin_after', $clname, $typeref);
$fl->print (" enum en {\n");
$self->_enum_write_center($typeref,$pack,$fl);
$fl->print (" };\n");
$pack->{rules}->execute_rule ('enum_end_before', $clname, $typeref);
$fl->print (" };\n");
$pack->{rules}->execute_rule ('enum_end_after', $clname, $typeref);
$fl->print ("\n");
}
sub enum_struct_write {
my $self = shift;
my $typeref = shift;
my $pack = shift;
my $fl = shift;
my $clname = $typeref->{typedef_name} || $typeref->{name} || "x";
$fl->print ("typedef enum {\n");
$self->_enum_write_center($typeref,$pack,$fl);
$fl->print ("} $clname;\n");
$fl->print ("\n");
}
sub _enum_write_center {
my $self = shift;
my $typeref = shift;
my $pack = shift;
my $fl = shift;
my $c = $fl->{C}; # Not C++
my $cClname = $c ? ($typeref->{typedef_name} || $typeref->{name})."_":"";
my $width = 13;
foreach my $fieldref ($typeref->fields_sorted()) {
$width = length($fieldref->{name}) if length($fieldref->{name})>$width;
}
foreach my $fieldref ($typeref->fields_sorted()) {
$fl->printf ("\t${cClname}%-${width}s = 0x%x,"
,$fieldref->{name},$fieldref->{rst_val});
if ($pack->{comments}) {
$fl->printf ("\t");
$fl->comment_post ($fieldref->{desc});
}
$fl->printf ("\n");
}
# Perhaps this should just be added to the data structures?
# note no comma to make C happy
if ($typeref->{bits}==32) {
# Can't put out 1_0000_0000 or C won't fit it into a enum
# We'll be weedy and subtract one. We'll check no value of the users would collide
# with our little lie.
$fl->printf("\t${cClname}%-${width}s = 0x%x\t","MAX", ((1<<$typeref->{bits})-1));
$fl->comment_post ("MAXIMUM (-1 adjusted so will fit in 32-bits)");
foreach my $fieldref ($typeref->fields_sorted()) {
if ($fieldref->{rst_val} >= ((1<<$typeref->{bits})-1)) {
$fieldref->warn ("0xffffffff isn't representable in 32-bit enum, as MAX won't fit.\n");
}
}
} else {
$fl->printf("\t${cClname}%-${width}s = 0x%x\t","MAX", (1<<$typeref->{bits}));
$fl->comment_post ("MAXIMUM+1");
}
$fl->print ("\n");
}
sub enum_cpp_write {
my $self = shift;
my $typeref = shift;
my $pack = shift;
my $fl = shift;
my $clname = $typeref->{name} || "x";
$fl->print("//${clname}\n",);
$pack->{rules}->execute_rule ('enum_cpp_before', $clname, $typeref);
for my $desc (0..1) {
next if $desc && !$typeref->attribute_value('descfunc');
$fl->printf ("const char* ${clname}::%s () const {\n",
($desc ? 'description':'ascii'));
$fl->print (" switch (m_e) {\n");
my %did_values;
foreach my $fieldref ($typeref->fields_sorted()) {
next if $desc && $fieldref->{omit_description};
if ($did_values{$fieldref->{rst_val}}) {
$fl->printf ("\t//DUPLICATE: ");
} else {
$fl->printf ("\t");
}
$fl->printf ("case %s: return(\"%s\");\n"
,$fieldref->{name}
,($desc ? $fieldref->{desc} : $fieldref->{name}));
$did_values{$fieldref->{rst_val}} = 1;
}
$fl->print ("\tdefault: return (\"?E\");\n");
$fl->print (" }\n");
$fl->print ("}\n\n");
}
{
$fl->printf ("${clname}::iterator ${clname}::iterator::operator++() {\n");
$fl->print (" switch (m_e) {\n");
my %next_values;
my $last;
foreach my $fieldref ($typeref->fields_sorted()) {
if (!defined $last || $fieldref->{rst_val} ne $last->{rst_val}) {
if ($last) {
if ($fieldref->{rst_val} == $last->{rst_val}+1) {
$next_values{inc}{$last->{name}} = "${clname}(m_e + 1)";
} else {
$next_values{expr}{$last->{name}} = $fieldref->{name};
}
}
$last = $fieldref;
}
}
# Note final value isn't in next_values; the default will catch it.
foreach my $inc ("inc", "expr") {
my @fields = (sort keys %{$next_values{$inc}});
for (my $i=0; $i<=$#fields; ++$i) {
my $field = $fields[$i];
my $next_field = $fields[$i+1];
$fl->printf ("\tcase %s:",$field);
if ($next_field && $next_values{$inc}{$field} eq $next_values{$inc}{$next_field}) {
$fl->printf (" /*FALLTHRU*/\n");
} else {
$fl->printf (" m_e=%s; return *this;\n"
,$next_values{$inc}{$field});
}
}
}
$fl->print ("\tdefault: m_e=MAX; return *this;\n");
$fl->print (" }\n");
$fl->print ("}\n\n");
}
$pack->{rules}->execute_rule ('enum_cpp_after', $clname, $typeref);
}
######################################################################
######################################################################
######################################################################
#### Saving
sub _class_h_write_dw {
my $self = shift;
my $typeref = shift;
my $pack = shift;
my $fl = shift;
my $wget = $fl->call_str($typeref->{name},"","w(");
my $wset = $fl->call_str($typeref->{name},"set","w(");
if (($typeref->{words}||0) > 1) {
# make full dw accessors if the type is >32 bits
$fl->fn($typeref->{name},"","inline uint64_t dw(int b) const",
,"{\n"
."\tunion {uint64_t udw; uint32_t lw[2];} u;\n"
."\tu.lw[0]=${wget}b*2+0); u.lw[1]=${wget}b*2+1); return u.udw; }\n");
$fl->fn($typeref->{name},"set","inline void dw(int b, uint64_t val)"
,"{\n"
."\tunion {uint64_t udw; uint32_t lw[2];} u;\n"
."\tu.udw=val; ${wset}b*2+0,u.lw[0]); ${wset}b*2+1,u.lw[1]); }\n");
} else {
# still make dw accessors, but don't read or write w[1] because
# it doesn't exist.
$fl->fn($typeref->{name},"","inline uint64_t dw(int b) const"
,"{\n"
."\tunion {uint64_t udw; uint32_t lw[2];} u;\n"
."\tu.lw[0]=${wget}b*2+0); u.lw[1]=0; return u.udw; }\n");
$fl->fn($typeref->{name},"set","inline void dw(int b, uint64_t val)"
,"{\n"
."\tunion {uint64_t udw; uint32_t lw[2];} u;\n"
."\tu.udw=val; ${wset}b*2+0,u.lw[0]); }\n");
}
}
sub _class_h_write {
my $self = shift;
my $typeref = shift;
my $pack = shift;
my $fl = shift;
my $clname = $typeref->{name} || "x";
my $c = $fl->{C}; # Not C++
my $cClname = $c ? "${clname}_":"";
my $cThis = $c ? "thisp->":"";
my $cForInt = $c ? "int i; for (" : "for (int ";
my $wget = $fl->call_str($clname,"","w(");
my $wset = $fl->call_str($clname,"set","w(");
my $netorder = $typeref->attribute_value('netorder') || 0;
my $stretchable = $typeref->attribute_value('stretchable') || 0;
my $ntohl = ($netorder ? "ntohl" : "");
my $htonl = ($netorder ? "htonl" : "");
my $uint = ($netorder ? "nint32_t" : "uint32_t");
my $uint64 = ($netorder ? "nint64_t" : "uint64_t");
my $uchar = ($netorder ? "nint8_t" : "uint8_t");
my $toBytePtr = ($netorder ? "castNBytep" : "castHBytep");
my $inh = "";
$inh = " : $typeref->{inherits}" if $typeref->{inherits};
$inh = "" if $c;
my $words = $typeref->{words};
if ($c) {
$fl->print("typedef struct {\n");
$fl->print(" ${uint} m_w[${words}];"
.($stretchable ? " // Attr '-stretchable'\n" : "\n")
."} $clname;\n");
} else {
$pack->{rules}->execute_rule ('class_begin_before', $clname, $typeref);
$fl->print("struct $clname$inh {\n");
$fl->set_private(0); # struct implies public:
$pack->{rules}->execute_rule ('class_begin_after', $clname, $typeref);
}
$fl->set_private(0); # struct implies public:
if ($inh ne "") {
my $inhType = $typeref->{inherits_typeref} or
die "%Error: Missing typeref for inherits${inh}.\n";
# Verify same byte ordering.
my $inh_netorder = $inhType->attribute_value('netorder') || 0;
if ($inh_netorder ne $netorder) {
die ("%Error: $clname netorder=$netorder doesn't match $inh_netorder"
." inherited from $inhType->{name}.\n");
}
$fl->print(" // w() and $toBytePtr() inherited from $typeref->{inherits}::\n");
# Correct for any size difference
(defined $inhType->{words}) or die "%Error: Missed words compute()\n";
if (($typeref->{words}||0) > $inhType->{words}) {
# Ensure the parent type disabled array bounds checking.
my $inh_stretchable = $inhType->attribute_value('stretchable') || 0;
if (! $inh_stretchable) {
die sprintf("%%Error: Base class %s (%d words) needs '-stretchable'"
." since %s has %d words.\n",
$inhType->{name}, $inhType->{words},
$clname, $typeref->{words});
}
$fl->printf(" protected: uint32_t m_wStretch[%d]; // Bring base size up\n"
." public:\n",
$typeref->{words} - $typeref->{inherits_typeref}->{words});
}
} else {
if (!$c) {
$fl->print(" protected: ${uint} m_w[${words}];"
.($stretchable ? " // Attr '-stretchable'\n" : "\n")
." public:\n");
}
$fl->fn($clname, "", "inline uint32_t w(int b) const"
,"{ return (${ntohl}(${cThis}m_w[b])); }\n");
$fl->fn($clname, "set", "inline void w(int b, uint32_t val)"
,"{");
if (! $stretchable) {
$fl->print(" VREGS_WORDIDX_CHK($clname, $words, b)\n"
."\t\t\t\t\t");
}
$fl->print(" ${cThis}m_w[b] = ${htonl}(val); }\n");
_class_h_write_dw($self,$typeref,$pack,$fl);
if (!$c) {
$fl->fn($clname, "", "inline ${uchar}* ${toBytePtr}()"
,"{\n"
,"\treturn reinterpret_cast<${uchar}*>(&m_w[0]); }\n");
$fl->fn($clname, "", "inline const ${uchar}* ${toBytePtr}() const"
,"{\n"
,"\treturn reinterpret_cast<const ${uchar}*>(&m_w[0]); }\n");
}
}
if ($clname =~ /^R_/) {
# Write only those bits that are marked access writable
my @wr_masks;
for (my $word=0; $word<$typeref->{words}; $word++) {
$wr_masks[$word] = 0;
for (my $bit=$word*$typeref->{pack}->{word_bits};
$bit<(($word+1)*$typeref->{pack}->{word_bits});
$bit++) {
my $bitent = $typeref->{bitarray}[$bit];
next if !$bitent;
$wr_masks[$word] |= (1<<($bit & ($typeref->{pack}->{word_bits}-1)))
if ($bitent->{write});
}
}
if ($typeref->{words}>0 && $typeref->{words}<2 && !$c) {
$fl->printf(" static const uint32_t BITMASK_WRITABLE = 0x%08x;\n", $wr_masks[0]);
$fl->fn($clname, "", "inline void wWritable(int b, uint32_t val)"
,"{ ${wset}b,(val&BITMASK_WRITABLE)|(${wget}b)&~BITMASK_WRITABLE)); }\n");
} else {
# Grrr, Greenhills Compilers don't allow
# static const uint32_t BITMASK_WRITABLE[] = {...};
$fl->fn($clname,"","inline uint32_t wBitMaskWritable(int b)"
,"{\n");
for (my $word=0; $word<$typeref->{words}; $word++) {
$fl->printf("\tif (b==$word) return 0x%08x;\n", $wr_masks[$word]);
}
$fl->printf("\treturn 0; }\n");
my $fwritable = $fl->call_str($clname,"","wBitMaskWritable(b)");
$fl->fn($clname,"","inline void wWritable(int b, uint32_t val)"
,"{ ${wset}b,(val&${fwritable})|(${wget}b)&~${fwritable})); }\n");
}
}
my @resets=();
if ($typeref->{inherits}) {
if ($c) {
my $call = $fl->call_str($typeref->{inherits},"","fieldsReset();\n");
$call =~ s/\(/(($typeref->{inherits}*)/; # Need a cast
push @resets, "\t".$call;
} else {
push @resets, "\t".$typeref->{inherits}."::fieldsReset();\n";
}
}
my @dumps = ();
$fl->printf("\n");
my @fields = $c ? ($typeref->fields_sorted_inherited()) : ($typeref->fields_sorted());
foreach my $bitref (@fields) {
next if $bitref->ignore;
(my $lc_mnem = $bitref->{name}) =~ s/^(.)/lc $1/xe;
my $typecast = "";
$typecast = $bitref->{type} if $bitref->{cast_needed};
$typecast = "($typecast)" if $c && $typecast ne "";
$typecast = "(void*)" if $bitref->{type} eq 'void*'; # Damn C++
my $L = ($bitref->{numbits}>32)?'LL':'';
my $extract = "";
my $deposit = "";
if ($bitref->{numbits} < 32 && $bitref->{numbits} > 1) {
# Don't bother adding code to check boolean fields.
$deposit .=
sprintf(" VREGS_SETFIELD_CHK%s(\"%s.%s\", b, 0x%xU)\n\t\t\t\t\t\t",
($L ? "_$L" : ""), $clname, $lc_mnem,
(1 << $bitref->{numbits})-1);
}
foreach my $bitrange (@{$bitref->{bitlist_range_32}}) {
my ($msb,$lsb,$nbits,$srcbit) = @{$bitrange};
my $low_mod = $lsb % 32;
my $high_mod = $msb % 32;
my $word = int($lsb/32);
(int($msb/32)==$word) or die "%Error: One _range cannot span two words\n";
my $deposit_mask = (1<<$nbits)-1;
$deposit_mask = 0xffffffff if $nbits==32;
my $mask = $deposit_mask << $low_mod;
$mask = 0xffffffff if $high_mod==31 && $low_mod==0;
$extract .= " |" if $extract ne "";
if ($high_mod==31 && $low_mod==0 && $srcbit==0) {
# Whole word, skip the B.S.
$extract .= " ${wget}${word})";
$deposit .= " ${wset}${word}, (uint32_t)(b));";
} else {
my $tobit = "<<$srcbit)";
$tobit = "" if $srcbit==0;
my $frombit = ">>$srcbit)";
$frombit = "" if $srcbit==0;
$extract .= sprintf " %s(${wget}${word})>>${low_mod} & 0x%x$L)$tobit"
, ($tobit?"(":""), $deposit_mask;
my $b = "b";
$b = "(".$b.$frombit if $frombit;
$b = "((uint32_t)($b))" if $bitref->{type} ne 'uint32_t';
$deposit .= sprintf " ${wset}${word}, (${wget}${word})&0x%08x$L)"
." | ((%s&0x%x$L)<<${low_mod}));"
, (~$mask&0xffffffff),
, $b
, $deposit_mask;
}
}
# Mask after shifting on reads, so the mask is a smaller constant.
$fl->private_not_public (!$bitref->{access_read}, $pack);
my $typEnd = 11 + length $bitref->{type};
$fl->fn($clname,"",sprintf("inline %s%s%-13s () const",
$bitref->{type}, ($typEnd < 16 ? "\t\t" : $typEnd < 24 ? "\t" : " "),
$lc_mnem)
,"{ return ${typecast}(${extract} ); }\n");
if ($typeref->attribute_value('public_rdwr_accessors') && $fl->{private} && $fl->{CPP}) {
$fl->private_not_public(0);
$fl->fn($clname,"",sprintf("inline %s%s%-13s () const",
$bitref->{type}, ($typEnd < 16 ? "\t\t" : $typEnd < 24 ? "\t" : " "),
$lc_mnem."_private")
,"{ return $lc_mnem(); }\n");
}
$fl->private_not_public (!$bitref->{access_write}, $pack);
$fl->fn($clname,"set",sprintf("inline void\t\t%-13s (%s b)", $lc_mnem, $bitref->{type})
,"{${deposit} }\n");
if ($typeref->attribute_value('public_rdwr_accessors') && $fl->{private} && $fl->{CPP}) {
$fl->private_not_public(0);
$fl->fn($clname,"set",sprintf("inline void\t\t%-13s (%s b)", $lc_mnem."_private", $bitref->{type})
,"{ ${lc_mnem}(b); }\n");
}
push @dumps, "\"$bitref->{name}=\"<<$lc_mnem()";
if ($bitref->{rst} ne 'X') {
my $rst = $bitref->{rst};
$rst = 0 if ($rst =~ /^FW-?0$/);
if ($rst =~ /^[a-z]/i && $bitref->{type}) { # Probably a enum value
if ($c) {
$rst = "$bitref->{type}_$rst";
} else {
$rst = "$bitref->{type}::$rst";
}
} elsif ($rst =~ /^0x([0-9a-f_]+)$/i) { # May need ULLs added
$rst = $fl->sprint_hex_value($1,$bitref->{numbits});
}
#$fl->printf("\tstatic const %s %s = %s;\n", $bitref->{type},
# uc($lc_mnem)."_RST", $rst);
push @resets, $fl->call_str($clname,"set",sprintf("\t%s(%s);\n", $lc_mnem, $rst));
}
}
$fl->printf("\n");
$fl->private_not_public (0, $pack);
if (!$c) {
$fl->printf(" VREGS_STRUCT_DEF_CTOR(%s, %s)\t// (typeName, numWords)\n",
$clname, $words);
}
$fl->fn($clname,"","inline void fieldsZero()"
,"{\n");
if ($words>=8) {
$fl->print("\t${cForInt}i=0; i<${words}; i++) ${wset}i,0);\n");
} else {
$fl->print("\t");
for (my $i=0; $i<$words; $i++) {
$fl->print(" ") if $i!=0;
$fl->print("${wset}$i,0);");
}
$fl->print("\n");
}
$fl->print(" }\n");
$fl->fn($clname,"","inline void fieldsReset()"
,"{\n"
,"\t",$fl->call_str($clname,"","fieldsZero();\n")
,@resets
," }\n");
if (!$c) {
$fl->fn($clname,"","inline bool operator== (const ${clname}& rhs) const"
,"{\n"
,"\t${cForInt}i=0; i<${words}; i++) { if (m_w[i]!=rhs.m_w[i]) return false; }\n"
,"\treturn true;\n"
," }\n");
# The dump functions are in a .cpp file (no inline), as there was too much code
# bloat, and it was taking a lot of compile time.
$fl->print(" typedef VregsOstream<${clname}> DumpOstream;\n",
" DumpOstream dump(const char* prefix=\"\\n\\t\") const;\n",
" OStream& _dump(OStream& lhs, const char* pf) const;\n",
" void dumpCout() const; // For GDB\n",);
# Put const's last to avoid GDB stupidity
$fl->private_not_public (0, $pack);
$fl->printf(" static const size_t SIZE = %d;\n", $words*4);
$pack->{rules}->execute_rule ('class_end_before', $clname, $typeref);
$fl->print("};\n");
$pack->{rules}->execute_rule ('class_end_after', $clname, $typeref);
$fl->print(" OStream& operator<< (OStream& lhs, const ${clname}::DumpOstream rhs);\n",);
}
$fl->print("\n");
}
######################################################################
######################################################################
######################################################################
sub _class_cpp_write {
my $self = shift;
my $typeref = shift;
my $pack = shift;
my $fl = shift;
my $clname = $typeref->{name} || "x";
my @dumps = ();
my $fields_lcFirst = $typeref->attribute_value('lcfirst') || 0;
foreach my $bitref ($typeref->fields_sorted()) {
next if $bitref->ignore;
(my $lc_mnem = $bitref->{name}) =~ s/^(.)/lc $1/xe;
if ($typeref->{inherits_typeref}
&& $typeref->{inherits_typeref}->find_bit($bitref->{name})) {
# It's printed by the base class.
} elsif ($fields_lcFirst) {
push @dumps, "\"$lc_mnem=\"<<$lc_mnem()";
} else {
push @dumps, "\"$bitref->{name}=\"<<$lc_mnem()";
}
}
$fl->print("//${clname}\n",);
$pack->{rules}->execute_rule ('class_cpp_before', $clname, $typeref);
my $dumpName = $SystemC::Vregs::Dump_Routine_Name || "_dump";
$fl->print("${clname}::DumpOstream ${clname}::dump(const char* prefix) const {\n",
" return DumpOstream(this,prefix);\n",
"}\n");
$fl->print("OStream& operator<< (OStream& lhs, const ${clname}::DumpOstream rhs) {\n",
" return ((${clname}*)rhs.obj())->${dumpName}(lhs,rhs.prefix());\n",
"}\n");
$SystemC::Vregs::Do_Dump = 0;
$pack->{rules}->execute_rule ('class_dump_before', $clname, $typeref);
if ($SystemC::Vregs::Do_Dump) {
$fl->printf("OStream& ${clname}::_dump (OStream& lhs, const char*%s) const {\n",
((($#dumps>0) || $typeref->{inherits}) ? ' pf':''));
$pack->{rules}->execute_rule ('class_dump_after', $clname, $typeref, \@dumps);
$fl->print(" return lhs;\n"
."}\n");
}
# For usage in GDB
$fl->print("void ${clname}::dumpCout () const { COUT<<this->dump(\"\\n\\t\")<<endl; }\n",);
$pack->{rules}->execute_rule ('class_cpp_after', $clname, $typeref);
$fl->print("\n");
}
######################################################################
######################################################################
######################################################################
sub write_class_h {
# Dump type definitions
my $self = shift;
my %params = (pack => $self->{pack},
@_);
my $pack = $params{pack} or croak "%Error: No pack=> parameter passed,";
my $fl = SystemC::Vregs::File->open(rules => $pack->{rules},
language=>'CPP', @_);
$fl->include_guard();
$fl->print("\n");
$fl->comment("package $pack->{name}\n");
$fl->print("\n");
$pack->{rules}->execute_rule ('file_body_before', 'file_body', $pack);
$fl->print("// Vregs library Files:\n");
foreach my $packref (@{$pack->{libraries}}) {
$fl->print("#include \"$packref->{name}_class.h\"\n");
}
$fl->print("\n\n");
foreach my $typeref ($pack->enums_sorted) {
enum_write ($self, $typeref, $pack, $fl);
}
$fl->print("\n\n");
# Bitbashing done verbosely to avoid slow preprocess time
# We could use bit structures, but they don't work on non-contiguous fields
# Sorted first does base classes, then children
foreach my $typeref ($pack->types_sorted) {
next if $typeref->attribute_value('nofielddefines');
_class_h_write($self,$typeref,$pack, $fl);
}
$pack->{rules}->execute_rule ('file_body_after', 'file_body', $pack);
$fl->close();
}
sub write_struct_h {
# Dump type definitions
my $self = shift;
my %params = (pack => $self->{pack},
@_);
my $pack = $params{pack} or croak "%Error: No pack=> parameter passed,";
my $fl = SystemC::Vregs::File->open(rules => $pack->{rules},
language=>'C', @_);
$fl->include_guard();
$fl->print("\n");
$fl->comment("package $pack->{name}\n");
$fl->print("\n");
$pack->{rules}->execute_rule ('file_body_before', 'file_body', $pack);
$fl->print("// Vregs library Files:\n");
foreach my $packref (@{$pack->{libraries}}) {
$fl->print("#include \"$packref->{name}_struct.h\"\n");
}
$fl->print("\n\n");
foreach my $typeref ($pack->enums_sorted) {
enum_struct_write ($self, $typeref, $pack, $fl);
}
$fl->print("\n\n");
# Bitbashing done verbosely to avoid slow preprocess time
# We could use bit structures, but they don't work on non-contiguous fields
# Sorted first does base classes, then children
foreach my $typeref ($pack->types_sorted) {
next if $typeref->attribute_value('nofielddefines');
_class_h_write($self,$typeref,$pack, $fl);
}
$pack->{rules}->execute_rule ('file_body_after', 'file_body', $pack);
$fl->close();
}
sub write_class_cpp {
my $self = shift;
my %params = (pack => $self->{pack},
@_);
my $pack = $params{pack} or croak "%Error: No pack=> parameter passed,";
# Dump type definitions
my $fl = SystemC::Vregs::File->open(rules => $pack->{rules},
language=>'CPP', @_);
$fl->print("\n");
$fl->print("#include \"$pack->{name}_class.h\"\n");
$fl->print("\n");
$pack->{rules}->execute_rule ('class_cpp_file_before', 'file_body', $pack);
foreach my $typeref ($pack->enums_sorted) {
$self->enum_cpp_write ($typeref, $pack, $fl);
}
# Sorted first does base classes, then children
foreach my $typeref ($pack->types_sorted) {
next if $typeref->attribute_value('nofielddefines');
$self->_class_cpp_write($typeref,$pack, $fl);
}
$fl->close();
}
######################################################################
#### Package return
1;
__END__
=pod
=head1 NAME
SystemC::Vregs::Output::Class - Outputting Vregs Code
=head1 SYNOPSIS
SystemC::Vregs::Output::Class->new->write_class_h(pack=>$VregsPackageObject, filename=>$fn);
=head1 DESCRIPTION
This package contains additional SystemC::Vregs methods. These methods are
used to output various types of files.
=head1 METHODS
=over 4
=item write_class_h
Creates a C++ header file with class definitions.
=item write_class_cpp
Creates a C++ implementation file to correspond with write_class_h.
=item write_struct_h
Creates a C header file with structs for class definitions.
=back
=head1 DISTRIBUTION
Vregs is part of the L<http://www.veripool.org/> free Verilog software tool
suite. The latest version is available from CPAN and from
L<http://www.veripool.org/vregs>. /www.veripool.org/>.
Copyright 2001-2010 by Wilson Snyder. This package is free software; you
can redistribute it and/or modify it under the terms of either the GNU
Lesser General Public License Version 3 or the Perl Artistic License Version 2.0.
=head1 AUTHORS
Wilson Snyder <wsnyder@wsnyder.org>
=head1 SEE ALSO
L<vreg>,
L<SystemC::Vregs>
=cut