Example #1
0
def generate_hardware_blocks():
    for hardware in config["hardware_definitions"]:
        hardware_file = open(str(SRCTREE_TOP.joinpath(hardware)))
        regs = hjson.load(hardware_file,
                          use_decimal=True,
                          object_pairs_hook=validate.checking_dict)
        if validate.validate(regs) == 0:
            logging.info("Parsed %s" % (hardware))
        else:
            logging.fatal("Failed to parse %s" % (hardware))

        base_path = config["outdir-generated"].joinpath(hardware)
        base_path.parent.mkdir(parents=True, exist_ok=True)

        regs_html = open(str(
            base_path.parent.joinpath(base_path.name + '.registers')),
                         mode='w')
        gen_html.gen_html(regs, regs_html)
        regs_html.close()

        hwcfg_html = open(str(
            base_path.parent.joinpath(base_path.name + '.hwcfg')),
                          mode='w')
        gen_cfg_html.gen_cfg_html(regs, hwcfg_html)
        hwcfg_html.close()
Example #2
0
def generate_hardware_blocks():
    for hardware in config["hardware_definitions"]:
        regs = IpBlock.from_path(str(SRCTREE_TOP.joinpath(hardware)), [])

        hw_path = config["outdir-generated"].joinpath(hardware)
        dst_path = hw_path.parent
        dst_path.mkdir(parents=True, exist_ok=True)

        regs_path = dst_path.joinpath(hw_path.name + '.registers')
        with open(regs_path, 'w') as regs_file:
            gen_html.gen_html(regs, regs_file)

        hwcfg_path = dst_path.joinpath(hw_path.name + '.hwcfg')
        with open(hwcfg_path, 'w') as hwcfg_file:
            gen_cfg_html.gen_cfg_html(regs, hwcfg_file)
def main():
    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('--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('--dv-base-prefix',
                        default='dv_base',
                        help='Prefix for the DV register classes from which '
                        'the register models are derived.')
    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 (verbose):
        log.basicConfig(format="%(levelname)s: %(message)s", level=log.DEBUG)
    else:
        log.basicConfig(format="%(levelname)s: %(message)s")

    # Entries are triples of the form (arg, (format, dirspec)).
    #
    # arg is the name of the argument that selects the format. format is the
    # name of the format. dirspec is None if the output is a single file; if
    # the output needs a directory, it is a default path relative to the source
    # file (used when --outdir is not given).
    arg_to_format = [('j', ('json', None)), ('c', ('compact', None)),
                     ('d', ('html', None)), ('doc', ('doc', None)),
                     ('r', ('rtl', 'rtl')), ('s', ('dv', 'dv')),
                     ('f', ('fpv', 'fpv/vip')), ('cdefines', ('cdh', None))]
    format = None
    dirspec = None
    for arg_name, spec in arg_to_format:
        if getattr(args, arg_name):
            if format is not None:
                log.error('Multiple output formats specified on '
                          'command line ({} and {}).'.format(format, spec[0]))
                sys.exit(1)
            format, dirspec = spec
    if format is None:
        format = 'hjson'

    infile = args.input

    # Split parameters into key=value pairs.
    raw_params = args.param.split(';') if args.param else []
    params = []
    for idx, raw_param in enumerate(raw_params):
        tokens = raw_param.split('=')
        if len(tokens) != 2:
            raise ValueError('Entry {} in list of parameter defaults to '
                             'apply is {!r}, which is not of the form '
                             'param=value.'.format(idx, raw_param))
        params.append((tokens[0], tokens[1]))

    # Define either outfile or outdir (but not both), depending on the output
    # format.
    outfile = None
    outdir = None
    if dirspec is None:
        if args.outdir is not None:
            log.error('The {} format expects an output file, '
                      'not an output directory.'.format(format))
            sys.exit(1)

        outfile = args.outfile
    else:
        if args.outfile is not sys.stdout:
            log.error('The {} format expects an output directory, '
                      'not an output file.'.format(format))
            sys.exit(1)

        if args.outdir is not None:
            outdir = args.outdir
        elif infile is not sys.stdin:
            outdir = str(PurePath(infile.name).parents[1].joinpath(dirspec))
        else:
            # We're using sys.stdin, so can't infer an output directory name
            log.error(
                'The {} format writes to an output directory, which '
                'cannot be inferred automatically if the input comes '
                'from stdin. Use --outdir to specify it manually.'.format(
                    format))
            sys.exit(1)

    if format == 'doc':
        with outfile:
            gen_selfdoc.document(outfile)
        exit(0)

    srcfull = infile.read()

    try:
        obj = IpBlock.from_text(srcfull, params, infile.name)
    except ValueError as err:
        log.error(str(err))
        exit(1)

    if args.novalidate:
        with outfile:
            gen_json.gen_json(obj, outfile, format)
            outfile.write('\n')
    else:
        if format == 'rtl':
            return gen_rtl.gen_rtl(obj, outdir)
        if format == 'dv':
            return gen_dv.gen_dv(obj, args.dv_base_prefix, outdir)
        if format == 'fpv':
            return gen_fpv.gen_fpv(obj, outdir)
        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':
                return gen_html.gen_html(obj, outfile)
            elif format == 'cdh':
                return gen_cheader.gen_cdefines(obj, outfile, src_lic,
                                                src_copy)
            else:
                return gen_json.gen_json(obj, outfile, format)

            outfile.write('\n')
    def render_lowrisc_escape(self, token):
        # plan eventually to allow lowrisc-doc-hdr=doctype
        if token.type[:15] == "lowrisc-doc-hdr":
            return html_data.lowrisc_title_head + token.text + \
                   html_data.lowrisc_title_tail
        if token.type == "toc":
            return html_data.toc_mark_head + token.text + \
                   html_data.toc_mark_tail
        if token.type == "regfile":
            regfile = open(path.join(self.basedir, token.text),
                           'r',
                           encoding='UTF-8')
            with regfile:
                try:
                    obj = hjson.load(regfile,
                                     use_decimal=True,
                                     object_pairs_hook=validate.checking_dict)
                except ValueError:
                    raise SystemExit(sys.exc_info()[1])
            if validate.validate(obj) == 0:
                log.info("Generated register object\n")
                self.regs = obj
            else:
                log.warn("Register import failed\n")
                self.regs = None
            return ""
        if token.type == "registers":
            if self.regs == None:
                return "<B>Errors parsing registers prevents insertion.</B>"
            outbuf = io.StringIO()
            # note for CSS need to escape the mdown class on the div
            outbuf.write("</div>" + html_data.register_header)
            gen_html.gen_html(self.regs, outbuf, toclist=self.toc, toclevel=3)
            outbuf.write(html_data.register_trailer + '<div class="mdown">')
            generated = outbuf.getvalue()
            outbuf.close()
            return generated
        if token.type == "cfgfile":
            log.error("Deprecated lowRISC token cfgfile ignored. Config is now"\
                      " in a single file with the registers!")
            return ""
        if token.type == "hwcfg":
            if self.regs == None:
                return "<B>Errors parsing configuration prevents insertion.</B>"
            outbuf = io.StringIO()
            # note for CSS need to escape the mdown class on the div
            outbuf.write("</div>" + html_data.hwcfg_header)
            gen_cfg_html.gen_cfg_html(self.regs, outbuf)
            outbuf.write(html_data.hwcfg_trailer + '<div class="mdown">')
            generated = outbuf.getvalue()
            outbuf.close()
            return generated
        if token.type == "section1":
            # TODO should token.text get parsed to allow markdown in it?
            id = self.id_from_inner(token.text)
            self.toc.append((2, token.text, id))
            return html_data.section_template.format(cls="section_heading",
                                                     id=id,
                                                     inner=token.text)
        if token.type == "section2":
            # TODO should token.text get parsed to allow markdown in it?
            id = self.id_from_inner(token.text)
            self.toc.append((3, token.text, id))
            return html_data.section_template.format(cls="subsection_heading",
                                                     id=id,
                                                     inner=token.text)
        if token.type == "doctree":
            md_paths = []
            return_string = ''
            subdirs = [path.join(self.basedir, s) for s in token.text.split()]
            for subdir in sorted(subdirs):
                md_paths.extend(sorted(Path(subdir).rglob('*.md')))
            for md_path in md_paths:
                rel_md_path = md_path.relative_to(self.basedir)
                return_string += html_data.doctree_template.format(
                    link=rel_md_path.with_suffix('.html'),
                    text=rel_md_path.with_suffix(''))
            return html_data.doctree_head + return_string + html_data.doctree_tail

        bad_tag = '{{% ' + token.type + ' ' + token.text + ' }}'
        log.warn("Unknown lowRISC tag " + bad_tag)
        return bad_tag
Example #5
0
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('--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.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")
    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

        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 != None:
                src_copy += mat.group(1)
            mat = spdx.match(line)
            if mat != None:
                found_spdx = mat.group(1)
            mat = lunder.match(line)
            if mat != 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')