Internals: Convert vlcovgen to python3. No functional change.

This commit is contained in:
Wilson Snyder 2020-12-23 16:54:05 -05:00
parent b8b9170f9d
commit 93476a7372
2 changed files with 91 additions and 151 deletions

View File

@ -29,17 +29,17 @@
#define VLCOVGEN_ITEM(string_parsed_by_vlcovgen)
// clang-format off
VLCOVGEN_ITEM("name=>'column', short=>'n', group=>1, default=>0, descr=>'Column number for the item. Used to disambiguate multiple coverage points on the same line number'")
VLCOVGEN_ITEM("name=>'filename', short=>'f', group=>1, default=>undef, descr=>'Filename of the item'")
VLCOVGEN_ITEM("name=>'linescov', short=>'S', group=>1, default=>'', descr=>'List of comma-separated lines covered'")
VLCOVGEN_ITEM("name=>'per_instance',short=>'P', group=>1, default=>0, descr=>'True if every hierarchy is independently counted; otherwise all hierarchies will be combined into a single count'")
VLCOVGEN_ITEM("name=>'thresh', short=>'s', group=>1, default=>undef, descr=>'Number of hits to consider covered (aka at_least)'")
VLCOVGEN_ITEM("name=>'type', short=>'t', group=>1, default=>'', descr=>'Type of coverage (block, line, fsm, etc)'")
VLCOVGEN_ITEM("'name':'column', 'short':'n', 'group':1, 'default':0, 'descr':'Column number for the item. Used to disambiguate multiple coverage points on the same line number'")
VLCOVGEN_ITEM("'name':'filename', 'short':'f', 'group':1, 'default':None, 'descr':'Filename of the item'")
VLCOVGEN_ITEM("'name':'linescov', 'short':'S', 'group':1, 'default':'', 'descr':'List of comma-separated lines covered'")
VLCOVGEN_ITEM("'name':'per_instance','short':'P', 'group':1, 'default':0, 'descr':'True if every hierarchy is independently counted; otherwise all hierarchies will be combined into a single count'")
VLCOVGEN_ITEM("'name':'thresh', 'short':'s', 'group':1, 'default':None, 'descr':'Number of hits to consider covered (aka at_least)'")
VLCOVGEN_ITEM("'name':'type', 'short':'t', 'group':1, 'default':'', 'descr':'Type of coverage (block, line, fsm, etc)'")
// Bin attributes
VLCOVGEN_ITEM("name=>'comment', short=>'o', group=>0, default=>'', descr=>'Textual description for the item'")
VLCOVGEN_ITEM("name=>'hier', short=>'h', group=>0, default=>'', descr=>'Hierarchy path name for the item'")
VLCOVGEN_ITEM("name=>'lineno', short=>'l', group=>0, default=>0, descr=>'Line number for the item'")
VLCOVGEN_ITEM("name=>'weight', short=>'w', group=>0, default=>undef, descr=>'For totaling items, weight of this item'")
VLCOVGEN_ITEM("'name':'comment', 'short':'o', 'group':0, 'default':'', 'descr':'Textual description for the item'")
VLCOVGEN_ITEM("'name':'hier', 'short':'h', 'group':0, 'default':'', 'descr':'Hierarchy path name for the item'")
VLCOVGEN_ITEM("'name':'lineno', 'short':'l', 'group':0, 'default':0, 'descr':'Line number for the item'")
VLCOVGEN_ITEM("'name':'weight', 'short':'w', 'group':0, 'default':None, 'descr':'For totaling items, weight of this item'")
// clang-format on
// VLCOVGEN_CIK_AUTO_EDIT_BEGIN

View File

@ -1,169 +1,109 @@
#!/usr/bin/env perl
# See copyright, etc in below POD section.
#!/usr/bin/env python3
######################################################################
use warnings;
use Getopt::Long;
use IO::File;
use Pod::Usage;
use strict;
use vars qw($Debug);
import argparse
import re
import os
import sys
from pprint import pprint
our @Items;
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=>0, -output=>\*STDOUT);
exit(1); # Unreachable
}
#######################################################################
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}}) {
die "%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__
def read_keys(filename):
with open(filename) as fh:
for line in fh:
line = re.sub(r'\/\/.*$', '', line)
if re.match(r'^\s*$', line):
continue
if re.search(r'^\s*VLCOVGEN_ITEM', line):
match = re.search(r'^\s*VLCOVGEN_ITEM *\( *"([^"]+)" *\)',
line)
if not match:
sys.exit("%Error: " + filename +
": vlcovgen misformed VLCOVGEN_ITEM line")
code = "{" + match.group(1) + "}"
data = eval(code)
# pprint(data)
Items.append(data)
=pod
=head1 NAME
######################################################################
vlcovgen - Generate verilated_cov headers to reduce C++ code duplication
=head1 SYNOPSIS
def lint():
shorts = {}
for item in Items:
if item['short'] in shorts:
sys.exit("%Error: vlcovgen duplicate short code: " + item['short'])
shorts[item['short']] = True
(called from make rules)
vlcovgen
=head1 DESCRIPTION
def write_keys(filename):
orig = []
out = []
Generates several files for Verilator compilations.
with open(filename) as fh:
deleting = False
for line in fh:
orig.append(line)
if re.search(r'VLCOVGEN_CIK_AUTO_EDIT_BEGIN', line):
deleting = True
out.append(line)
for keyref in sorted(Items, key=lambda a: a['name']):
out.append(
"#define VL_CIK_%s \"%s\"\n" %
(keyref['name'].upper(), keyref['short']))
elif re.search(r'VLCOVGEN_SHORT_AUTO_EDIT_BEGIN', line):
deleting = True
out.append(line)
for keyref in sorted(Items, key=lambda a: a['name']):
out.append(
" if (key == \"%s\") return VL_CIK_%s;\n" %
(keyref['name'], keyref['name'].upper()))
elif re.search(r'VLCOVGEN_.*AUTO_EDIT_END', line):
deleting = False
out.append(line)
elif deleting:
None
else:
out.append(line)
=head1 ARGUMENTS
ok = "".join(out) == "".join(orig)
if not ok:
with open(filename, "w") as fhw:
fhw.write("".join(out))
=over 4
=item --help
######################################################################
######################################################################
Displays this message and program version and exits.
=back
=head1 DISTRIBUTION
Copyright 2002-2020 by Wilson Snyder. This program is free software; you
parser = argparse.ArgumentParser(
allow_abbrev=False,
formatter_class=argparse.RawDescriptionHelpFormatter,
description=
"""Generate verilated_cov headers to reduce C++ code duplication.""",
epilog=
"""Copyright 2002-2020 by Wilson Snyder. This program 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.
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""")
=head1 AUTHORS
parser.add_argument('--srcdir',
action='store',
help='directory containing Verilator sources')
Wilson Snyder <wsnyder@wsnyder.org>
parser.set_defaults(srcdir=".")
=head1 SEE ALSO
Args = parser.parse_args()
=cut
read_keys(Args.srcdir + "/../include/verilated_cov_key.h")
lint()
write_keys(Args.srcdir + "/../include/verilated_cov_key.h")
######################################################################
### Local Variables: