blob: e96da5978c1925cb65ab871376cd204a362f95da [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)
Eunchan Kim6ec3b892019-10-01 15:02:56 -070040 parser.add_argument('input',
41 nargs='?',
42 metavar='file',
43 type=argparse.FileType('r'),
44 default=sys.stdin,
45 help='input file in hjson type')
46 parser.add_argument('-d',
47 action='store_true',
48 help='Output register documentation (html)')
49 parser.add_argument('--cdefines',
50 '-D',
51 action='store_true',
52 help='Output C defines header')
53 parser.add_argument('--ctdefines',
54 '-T',
55 action='store_true',
56 help='Output C defines header (Titan style)')
57 parser.add_argument('--doc',
58 action='store_true',
59 help='Output source file documentation (gfm)')
60 parser.add_argument('-j',
61 action='store_true',
62 help='Output as formatted JSON')
lowRISC Contributors802543a2019-08-31 12:12:56 +010063 parser.add_argument('-c', action='store_true', help='Output as JSON')
Eunchan Kim6ec3b892019-10-01 15:02:56 -070064 parser.add_argument('-r',
65 action='store_true',
66 help='Output as SystemVerilog RTL')
67 parser.add_argument('-s',
68 action='store_true',
69 help='Output as UVM Register class')
lowRISC Contributors802543a2019-08-31 12:12:56 +010070 parser.add_argument('--outdir', '-t',
71 help='Target directory for generated RTL, '\
72 'tool uses ../rtl if blank.')
Eunchan Kim6ec3b892019-10-01 15:02:56 -070073 parser.add_argument('--outfile',
74 '-o',
75 type=argparse.FileType('w'),
76 default=sys.stdout,
77 help='Target filename for json, html, gfm.')
78 parser.add_argument('--verbose',
79 '-v',
80 action='store_true',
81 help='Verbose and run validate twice')
82 parser.add_argument('--param',
83 '-p',
84 type=str,
Eunchan Kim276af5e2019-10-01 17:02:46 -070085 default="",
Eunchan Kim6ec3b892019-10-01 15:02:56 -070086 help='''Change the Parameter values.
87 Only integer value is supported.
88 You can add multiple param arguments.
89
90 Format: ParamA=ValA;ParamB=ValB
91 ''')
92 parser.add_argument('--version',
93 '-V',
94 action='store_true',
95 help='Show version')
96 parser.add_argument('--novalidate',
97 action='store_true',
98 help='Skip validate, just output json')
lowRISC Contributors802543a2019-08-31 12:12:56 +010099
100 args = parser.parse_args()
101
102 if args.version:
103 version.show_and_exit(__file__, ["Hjson", "Mako"])
104
105 verbose = args.verbose
106
107 if args.j: format = 'json'
108 elif args.c: format = 'compact'
109 elif args.d: format = 'html'
110 elif args.doc: format = 'doc'
111 elif args.r: format = 'rtl'
112 elif args.s: format = 'dv'
113 elif args.cdefines: format = 'cdh'
114 elif args.ctdefines: format = 'cth'
115
116 if (verbose):
117 log.basicConfig(format="%(levelname)s: %(message)s", level=log.DEBUG)
118 else:
119 log.basicConfig(format="%(levelname)s: %(message)s")
120
121 outfile = args.outfile
122
123 infile = args.input
124
Eunchan Kim6ec3b892019-10-01 15:02:56 -0700125 params = args.param.split(';')
126
lowRISC Contributors802543a2019-08-31 12:12:56 +0100127 if format == 'rtl':
128 if args.outdir:
129 outdir = args.outdir
130 elif infile != sys.stdin:
131 outdir = str(PurePath(infile.name).parents[1].joinpath("rtl"))
132 else:
133 # Using sys.stdin. not possible to generate RTL
134 log.error("-r option cannot be used with pipe or stdin")
135 elif format == 'dv':
136 if args.outdir:
137 outdir = args.outdir
138 elif infile != sys.stdin:
139 outdir = str(PurePath(infile.name).parents[1].joinpath("dv"))
140 else:
141 # Using sys.stdin. not possible to generate RTL
142 log.error("-s option cannot be used with pipe or stdin")
143 else:
144 # Ignore
145 outdir = "."
146
147 if format == 'doc':
148 with outfile:
149 gen_selfdoc.document(outfile)
150 exit(0)
151
152 with infile:
153 try:
154 srcfull = infile.read()
Eunchan Kim6ec3b892019-10-01 15:02:56 -0700155 obj = hjson.loads(srcfull,
156 use_decimal=True,
157 object_pairs_hook=validate.checking_dict)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100158 except ValueError:
159 raise SystemExit(sys.exc_info()[1])
160
161 if args.novalidate:
162 with outfile:
163 gen_json.gen_json(obj, outfile, format)
164 outfile.write('\n')
Eunchan Kim6ec3b892019-10-01 15:02:56 -0700165 elif (validate.validate(obj, params=params) == 0):
lowRISC Contributors802543a2019-08-31 12:12:56 +0100166 if (verbose):
167 log.info("Second validate pass (should show added optional keys)")
Eunchan Kim6ec3b892019-10-01 15:02:56 -0700168 validate.validate(obj, params=params)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100169
170 if format == 'rtl':
171 gen_rtl.gen_rtl(obj, outdir)
172 return 0
173 if format == 'dv':
174 gen_dv.gen_dv(obj, outdir)
175 return 0
176
177 src_lic = None
178 src_copy = ''
179 found_spdx = None
180 found_lunder = None
181 copy = re.compile(r'.*(copyright.*)|(.*\(c\).*)', re.IGNORECASE)
182 spdx = re.compile(r'.*(SPDX-License-Identifier:.+)')
183 lunder = re.compile(r'.*(Licensed under.+)', re.IGNORECASE)
184 for line in srcfull.splitlines():
185 mat = copy.match(line)
186 if mat != None:
187 src_copy += mat.group(1)
188 mat = spdx.match(line)
189 if mat != None:
190 found_spdx = mat.group(1)
191 mat = lunder.match(line)
192 if mat != None:
193 found_lunder = mat.group(1)
194 if found_lunder:
195 src_lic = found_lunder
196 if found_spdx:
197 src_lic += '\n' + found_spdx
198
199 with outfile:
200 if format == 'html':
201 gen_html.gen_html(obj, outfile)
202 elif format == 'cdh':
203 gen_cheader.gen_cdefines(obj, outfile, src_lic, src_copy)
204 elif format == 'cth':
205 gen_ctheader.gen_cdefines(obj, outfile, src_lic, src_copy)
206 else:
207 gen_json.gen_json(obj, outfile, format)
208
209 outfile.write('\n')
210
211
212if __name__ == '__main__':
213 main()