1#!/usr/bin/env python3
2# pylint: disable=C0103,C0114,C0116,eval-used
3######################################################################
4
5import argparse
6import re
7import sys
8# from pprint import pprint
9
10Items = []
11
12######################################################################
13
14
15def read_keys(filename):
16    with open(filename) as fh:
17        for line in fh:
18            line = re.sub(r'\/\/.*$', '', line)
19            if re.match(r'^\s*$', line):
20                continue
21            if re.search(r'^\s*VLCOVGEN_ITEM', line):
22                match = re.search(r'^\s*VLCOVGEN_ITEM *\( *"([^"]+)" *\)',
23                                  line)
24                if not match:
25                    sys.exit("%Error: " + filename +
26                             ": vlcovgen misformed VLCOVGEN_ITEM line")
27                code = "{" + match.group(1) + "}"
28                data = eval(code)
29                # pprint(data)
30                Items.append(data)
31
32
33######################################################################
34
35
36def lint():
37    shorts = {}
38    for item in Items:
39        if item['short'] in shorts:
40            sys.exit("%Error: vlcovgen duplicate short code: " + item['short'])
41        shorts[item['short']] = True
42
43
44def write_keys(filename):
45    orig = []
46    out = []
47
48    with open(filename) as fh:
49        deleting = False
50        for line in fh:
51            orig.append(line)
52            if re.search(r'VLCOVGEN_CIK_AUTO_EDIT_BEGIN', line):
53                deleting = True
54                out.append(line)
55                for keyref in sorted(Items, key=lambda a: a['name']):
56                    out.append("#define VL_CIK_%s \"%s\"\n" %
57                               (keyref['name'].upper(), keyref['short']))
58            elif re.search(r'VLCOVGEN_SHORT_AUTO_EDIT_BEGIN', line):
59                deleting = True
60                out.append(line)
61                for keyref in sorted(Items, key=lambda a: a['name']):
62                    out.append(
63                        "        if (key == \"%s\") return VL_CIK_%s;\n" %
64                        (keyref['name'], keyref['name'].upper()))
65            elif re.search(r'VLCOVGEN_.*AUTO_EDIT_END', line):
66                deleting = False
67                out.append(line)
68            elif not deleting:
69                out.append(line)
70
71    ok = "".join(out) == "".join(orig)
72    if not ok:
73        with open(filename, "w") as fhw:
74            fhw.write("".join(out))
75
76
77######################################################################
78######################################################################
79
80parser = argparse.ArgumentParser(
81    allow_abbrev=False,
82    formatter_class=argparse.RawDescriptionHelpFormatter,
83    description=
84    """Generate verilated_cov headers to reduce C++ code duplication.""",
85    epilog=
86    """Copyright 2002-2021 by Wilson Snyder. This program is free software; you
87can redistribute it and/or modify it under the terms of either the GNU
88Lesser General Public License Version 3 or the Perl Artistic License
89Version 2.0.
90
91SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0""")
92
93parser.add_argument('--srcdir',
94                    action='store',
95                    help='directory containing Verilator sources')
96
97parser.set_defaults(srcdir=".")
98
99Args = parser.parse_args()
100
101read_keys(Args.srcdir + "/../include/verilated_cov_key.h")
102lint()
103write_keys(Args.srcdir + "/../include/verilated_cov_key.h")
104
105######################################################################
106# Local Variables:
107# compile-command: "./vlcovgen --srcdir ."
108# End:
109