text: #!/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()
  