blob: 34bc935377e3884fbd79e7fc806b473afc509efc [file] [log] [blame]
lowRISC Contributors802543a2019-08-31 12:12:56 +01001#!/usr/bin/env python3
2# Copyright lowRISC contributors.
3# Licensed under the Apache License, Version 2.0, see LICENSE for details.
4# SPDX-License-Identifier: Apache-2.0
5r"""Command-line tool to validate and convert register hjson
6
7"""
8import argparse
9import logging as log
10import os
11import re
12import sys
13from pathlib import PurePath
14
15import hjson
16import pkg_resources
17
18from reggen import (gen_cheader, gen_ctheader, gen_dv, gen_html, gen_json,
19 gen_rtl, gen_selfdoc, validate, version)
20
21DESC = """regtool, generate register info from hjson source"""
22
23USAGE = '''
24 regtool [options]
25 regtool [options] <input>
26 regtool (-h | --help)
27 regtool (-V | --version)
28'''
29
30
31def main():
32 format = 'hjson'
33 verbose = 0
34
35 parser = argparse.ArgumentParser(
36 prog="regtool",
37 formatter_class=argparse.RawDescriptionHelpFormatter,
38 usage=USAGE,
39 description=DESC)
40 parser.add_argument(
41 'input',
42 nargs='?',
43 metavar='file',
44 type=argparse.FileType('r'),
45 default=sys.stdin,
46 help='input file in hjson type')
47 parser.add_argument(
48 '-d', action='store_true', help='Output register documentation (html)')
49 parser.add_argument(
50 '--cdefines',
51 '-D',
52 action='store_true',
53 help='Output C defines header')
54 parser.add_argument(
55 '--ctdefines',
56 '-T',
57 action='store_true',
58 help='Output C defines header (Titan style)')
59 parser.add_argument(
60 '--doc',
61 action='store_true',
62 help='Output source file documentation (gfm)')
63 parser.add_argument(
64 '-j', action='store_true', help='Output as formatted JSON')
65 parser.add_argument('-c', action='store_true', help='Output as JSON')
66 parser.add_argument(
67 '-r', action='store_true', help='Output as SystemVerilog RTL')
68 parser.add_argument(
69 '-s', action='store_true', help='Output as UVM Register class')
70 parser.add_argument('--outdir', '-t',
71 help='Target directory for generated RTL, '\
72 'tool uses ../rtl if blank.')
73 parser.add_argument(
74 '--outfile',
75 '-o',
76 type=argparse.FileType('w'),
77 default=sys.stdout,
78 help='Target filename for json, html, gfm.')
79 parser.add_argument(
80 '--verbose',
81 '-v',
82 action='store_true',
83 help='Verbose and run validate twice')
84 parser.add_argument(
85 '--version', '-V', action='store_true', help='Show version')
86 parser.add_argument(
87 '--novalidate',
88 action='store_true',
89 help='Skip validate, just output json')
90
91 args = parser.parse_args()
92
93 if args.version:
94 version.show_and_exit(__file__, ["Hjson", "Mako"])
95
96 verbose = args.verbose
97
98 if args.j: format = 'json'
99 elif args.c: format = 'compact'
100 elif args.d: format = 'html'
101 elif args.doc: format = 'doc'
102 elif args.r: format = 'rtl'
103 elif args.s: format = 'dv'
104 elif args.cdefines: format = 'cdh'
105 elif args.ctdefines: format = 'cth'
106
107 if (verbose):
108 log.basicConfig(format="%(levelname)s: %(message)s", level=log.DEBUG)
109 else:
110 log.basicConfig(format="%(levelname)s: %(message)s")
111
112 outfile = args.outfile
113
114 infile = args.input
115
116 if format == 'rtl':
117 if args.outdir:
118 outdir = args.outdir
119 elif infile != sys.stdin:
120 outdir = str(PurePath(infile.name).parents[1].joinpath("rtl"))
121 else:
122 # Using sys.stdin. not possible to generate RTL
123 log.error("-r option cannot be used with pipe or stdin")
124 elif format == 'dv':
125 if args.outdir:
126 outdir = args.outdir
127 elif infile != sys.stdin:
128 outdir = str(PurePath(infile.name).parents[1].joinpath("dv"))
129 else:
130 # Using sys.stdin. not possible to generate RTL
131 log.error("-s option cannot be used with pipe or stdin")
132 else:
133 # Ignore
134 outdir = "."
135
136 if format == 'doc':
137 with outfile:
138 gen_selfdoc.document(outfile)
139 exit(0)
140
141 with infile:
142 try:
143 srcfull = infile.read()
144 obj = hjson.loads(
145 srcfull,
146 use_decimal=True,
147 object_pairs_hook=validate.checking_dict)
148 except ValueError:
149 raise SystemExit(sys.exc_info()[1])
150
151 if args.novalidate:
152 with outfile:
153 gen_json.gen_json(obj, outfile, format)
154 outfile.write('\n')
155 elif (validate.validate(obj) == 0):
156 if (verbose):
157 log.info("Second validate pass (should show added optional keys)")
158 validate.validate(obj)
159
160 if format == 'rtl':
161 gen_rtl.gen_rtl(obj, outdir)
162 return 0
163 if format == 'dv':
164 gen_dv.gen_dv(obj, outdir)
165 return 0
166
167 src_lic = None
168 src_copy = ''
169 found_spdx = None
170 found_lunder = None
171 copy = re.compile(r'.*(copyright.*)|(.*\(c\).*)', re.IGNORECASE)
172 spdx = re.compile(r'.*(SPDX-License-Identifier:.+)')
173 lunder = re.compile(r'.*(Licensed under.+)', re.IGNORECASE)
174 for line in srcfull.splitlines():
175 mat = copy.match(line)
176 if mat != None:
177 src_copy += mat.group(1)
178 mat = spdx.match(line)
179 if mat != None:
180 found_spdx = mat.group(1)
181 mat = lunder.match(line)
182 if mat != None:
183 found_lunder = mat.group(1)
184 if found_lunder:
185 src_lic = found_lunder
186 if found_spdx:
187 src_lic += '\n' + found_spdx
188
189 with outfile:
190 if format == 'html':
191 gen_html.gen_html(obj, outfile)
192 elif format == 'cdh':
193 gen_cheader.gen_cdefines(obj, outfile, src_lic, src_copy)
194 elif format == 'cth':
195 gen_ctheader.gen_cdefines(obj, outfile, src_lic, src_copy)
196 else:
197 gen_json.gen_json(obj, outfile, format)
198
199 outfile.write('\n')
200
201
202if __name__ == '__main__':
203 main()