blob: 2c0072d3e7329f1ab1a9cbbdeb1f6788c5ca789c [file] [log] [blame]
#!/usr/bin/env python3
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
r"""Command-line tool to validate and convert register hjson
"""
import argparse
import logging as log
import re
import sys
from pathlib import PurePath
import hjson
from reggen import (gen_cheader, gen_ctheader, gen_dv, gen_html, gen_json,
gen_rtl, gen_fpv, gen_selfdoc, validate, version)
DESC = """regtool, generate register info from Hjson source"""
USAGE = '''
regtool [options]
regtool [options] <input>
regtool (-h | --help)
regtool (-V | --version)
'''
def main():
format = 'hjson'
verbose = 0
parser = argparse.ArgumentParser(
prog="regtool",
formatter_class=argparse.RawDescriptionHelpFormatter,
usage=USAGE,
description=DESC)
parser.add_argument('input',
nargs='?',
metavar='file',
type=argparse.FileType('r'),
default=sys.stdin,
help='input file in Hjson type')
parser.add_argument('-d',
action='store_true',
help='Output register documentation (html)')
parser.add_argument('--cdefines',
'-D',
action='store_true',
help='Output C defines header')
parser.add_argument('--ctdefines',
'-T',
action='store_true',
help='Output C defines header (Titan style)')
parser.add_argument('--doc',
action='store_true',
help='Output source file documentation (gfm)')
parser.add_argument('-j',
action='store_true',
help='Output as formatted JSON')
parser.add_argument('-c', action='store_true', help='Output as JSON')
parser.add_argument('-r',
action='store_true',
help='Output as SystemVerilog RTL')
parser.add_argument('-s',
action='store_true',
help='Output as UVM Register class')
parser.add_argument('-f',
action='store_true',
help='Output as FPV CSR rw assertion module')
parser.add_argument('--outdir',
'-t',
help='Target directory for generated RTL; '
'tool uses ../rtl if blank.')
parser.add_argument('--outfile',
'-o',
type=argparse.FileType('w'),
default=sys.stdout,
help='Target filename for json, html, gfm.')
parser.add_argument('--verbose',
'-v',
action='store_true',
help='Verbose and run validate twice')
parser.add_argument('--param',
'-p',
type=str,
default="",
help='''Change the Parameter values.
Only integer value is supported.
You can add multiple param arguments.
Format: ParamA=ValA;ParamB=ValB
''')
parser.add_argument('--version',
'-V',
action='store_true',
help='Show version')
parser.add_argument('--novalidate',
action='store_true',
help='Skip validate, just output json')
args = parser.parse_args()
if args.version:
version.show_and_exit(__file__, ["Hjson", "Mako"])
verbose = args.verbose
if args.j:
format = 'json'
elif args.c:
format = 'compact'
elif args.d:
format = 'html'
elif args.doc:
format = 'doc'
elif args.r:
format = 'rtl'
elif args.s:
format = 'dv'
elif args.f:
format = 'fpv'
elif args.cdefines:
format = 'cdh'
elif args.ctdefines:
format = 'cth'
if (verbose):
log.basicConfig(format="%(levelname)s: %(message)s", level=log.DEBUG)
else:
log.basicConfig(format="%(levelname)s: %(message)s")
outfile = args.outfile
infile = args.input
params = args.param.split(';')
if format == 'rtl':
if args.outdir:
outdir = args.outdir
elif infile != sys.stdin:
outdir = str(PurePath(infile.name).parents[1].joinpath("rtl"))
else:
# Using sys.stdin. not possible to generate RTL
log.error("-r option cannot be used with pipe or stdin")
elif format == 'dv':
if args.outdir:
outdir = args.outdir
elif infile != sys.stdin:
outdir = str(PurePath(infile.name).parents[1].joinpath("dv"))
else:
# Using sys.stdin. not possible to generate RTL
log.error("-s option cannot be used with pipe or stdin")
elif format == 'fpv':
if args.outdir:
outdir = args.outdir
elif infile != sys.stdin:
outdir = str(PurePath(infile.name).parents[1].joinpath("fpv/vip"))
else:
# Using sys.stdin. not possible to generate RTL
log.error("-s option cannot be used with pipe or stdin")
else:
# Ignore
outdir = "."
if format == 'doc':
with outfile:
gen_selfdoc.document(outfile)
exit(0)
with infile:
try:
srcfull = infile.read()
obj = hjson.loads(srcfull,
use_decimal=True,
object_pairs_hook=validate.checking_dict)
except ValueError:
raise SystemExit(sys.exc_info()[1])
if args.novalidate:
with outfile:
gen_json.gen_json(obj, outfile, format)
outfile.write('\n')
elif (validate.validate(obj, params=params) == 0):
if (verbose):
log.info("Second validate pass (should show added optional keys)")
validate.validate(obj, params=params)
if format == 'rtl':
gen_rtl.gen_rtl(obj, outdir)
return 0
if format == 'dv':
gen_dv.gen_dv(obj, outdir)
return 0
if format == 'fpv':
gen_fpv.gen_fpv(obj, outdir)
return 0
src_lic = None
src_copy = ''
found_spdx = None
found_lunder = None
copy = re.compile(r'.*(copyright.*)|(.*\(c\).*)', re.IGNORECASE)
spdx = re.compile(r'.*(SPDX-License-Identifier:.+)')
lunder = re.compile(r'.*(Licensed under.+)', re.IGNORECASE)
for line in srcfull.splitlines():
mat = copy.match(line)
if mat is not None:
src_copy += mat.group(1)
mat = spdx.match(line)
if mat is not None:
found_spdx = mat.group(1)
mat = lunder.match(line)
if mat is not None:
found_lunder = mat.group(1)
if found_lunder:
src_lic = found_lunder
if found_spdx:
src_lic += '\n' + found_spdx
with outfile:
if format == 'html':
gen_html.gen_html(obj, outfile)
elif format == 'cdh':
gen_cheader.gen_cdefines(obj, outfile, src_lic, src_copy)
elif format == 'cth':
gen_ctheader.gen_cdefines(obj, outfile, src_lic, src_copy)
else:
gen_json.gen_json(obj, outfile, format)
outfile.write('\n')
if __name__ == '__main__':
main()