#!/usr/bin/perl -w # See copyright, etc in below POD section. ###################################################################### #require 5.006_001; use Getopt::Long; use IO::File; use Pod::Usage; use strict; use vars qw ($Debug); our @Items; #====================================================================== # main $Debug = 0; my $Opt_Srcdir = "."; Getopt::Long::config ("pass_through", "no_auto_abbrev"); if (! GetOptions ( "help" => \&usage, "debug" => sub { $Debug = 1; }, "srcdir=s" => \$Opt_Srcdir, "<>" => sub { die "%Error: Unknown parameter: $_[0],"; }, )) { usage(); } read_keys("$Opt_Srcdir/../include/verilated_cov_key.h"); lint(); write_keys("$Opt_Srcdir/../include/verilated_cov_key.h"); #---------------------------------------------------------------------- sub usage { pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT); exit (1); } ####################################################################### sub read_keys { my $filename = shift; my $fh = IO::File->new("<$filename") or die "%Error: $! $filename,"; while (defined (my $line = $fh->getline())) { $line =~ s/\/\/.*$//; next if $line =~ /^\s*$/; if ($line =~ /^\s*VLCOVGEN_ITEM/) { $line =~ /^\s*VLCOVGEN_ITEM *\( *"([^"]+)" *\)/ or die "%Error: $filename:$.: Misformed VLCOVGEN_ITEM line,"; my @data; my $code = "\@data = ($1);"; eval $code; die "%Error: $filename:$.: Parsing '$code': $@," if $@; push @Items, {@data}; } } } ####################################################################### sub lint { my %shorts; my $ok = 1; foreach my $itemref (@Items) { if ($shorts{$itemref->{short}}) { warn "%Error: Duplicate short code: $itemref->{short},"; $ok = 0; } $shorts{$itemref->{short}} = 1; } return $ok; } sub write_keys { my $filename = shift; my $fh = IO::File->new("<$filename") or die "%Error: $! $filename\n"; my @in; my @out; my $deleting; while (defined(my $line = $fh->getline)) { push @in, $line; if ($line =~ /VLCOVGEN_CIK_AUTO_EDIT_BEGIN/) { $deleting = 1; push @out, $line; foreach my $keyref (sort {$a->{name} cmp $b->{name}} @Items) { push @out, sprintf("#define VL_CIK_%s \"%s\"\n", uc $keyref->{name}, $keyref->{short}); } } elsif ($line =~ /VLCOVGEN_SHORT_AUTO_EDIT_BEGIN/) { $deleting = 1; push @out, $line; foreach my $keyref (sort {$a->{name} cmp $b->{name}} @Items) { push @out, sprintf(" if (key == \"%s\") return VL_CIK_%s;\n", $keyref->{name}, uc $keyref->{name}); } } elsif ($line =~ /VLCOVGEN_.*AUTO_EDIT_END/) { $deleting = 0; push @out, $line; } elsif ($deleting) { } else { push @out, $line; } } $fh->close; my $ok = join("", @out) eq join("", @in); if (!$ok) { my $fh = IO::File->new(">$filename") or die "%Error: $! writing $filename\n"; $fh->print(join "", @out); $fh->close; } } ####################################################################### __END__ =pod =head1 NAME vlcovgen - Generate verilated_cov headers to reduce C++ code duplication =head1 SYNOPSIS (called from make rules) vlcovgen =head1 DESCRIPTION Generates several files for Verilator compilations. =head1 ARGUMENTS =over 4 =item --help Displays this message and program version and exits. =back =head1 DISTRIBUTION Copyright 2002-2019 by Wilson Snyder. Verilator 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. =head1 AUTHORS Wilson Snyder =head1 SEE ALSO =cut ###################################################################### ### Local Variables: ### compile-command: "./vlcovgen --srcdir ." ### End: