# Copyright lowRISC contributors. # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 '''Generate DV code for an IP block''' import logging as log import os from typing import List, Union import yaml from mako import exceptions # type: ignore from mako.lookup import TemplateLookup # type: ignore from pkg_resources import resource_filename from .ip_block import IpBlock from .multi_register import MultiRegister from .register import Register from .window import Window def bcname(esc_if_name: str) -> str: '''Get the name of the dv_base_reg_block subclass for this device interface''' return esc_if_name + "_reg_block" def rcname(esc_if_name: str, r: Union[Register, MultiRegister]) -> str: '''Get the name of the dv_base_reg subclass for this register''' return '{}_reg_{}'.format(esc_if_name, r.name.lower()) def mcname(esc_if_name: str, m: Window) -> str: '''Get the name of the dv_base_mem subclass for this memory''' return '{}_mem_{}'.format(esc_if_name, m.name.lower()) def miname(m: Window) -> str: '''Get the lower-case name of a memory block''' return m.name.lower() def gen_core_file(outdir: str, lblock: str, dv_base_prefix: str, paths: List[str]) -> None: depends = ["lowrisc:dv:dv_base_reg"] if dv_base_prefix and dv_base_prefix != "dv_base": depends.append("lowrisc:dv:{}_reg".format(dv_base_prefix)) # Generate a fusesoc core file that points at the files we've just # generated. core_data = { 'name': "lowrisc:dv:{}_ral_pkg".format(lblock), 'filesets': { 'files_dv': { 'depend': depends, 'files': paths, 'file_type': 'systemVerilogSource' }, }, 'targets': { 'default': { 'filesets': [ 'files_dv', ], }, }, } core_file_path = os.path.join(outdir, lblock + '_ral_pkg.core') with open(core_file_path, 'w') as core_file: core_file.write('CAPI=2:\n') yaml.dump(core_data, core_file, encoding='utf-8') def gen_dv(block: IpBlock, dv_base_prefix: str, outdir: str) -> int: '''Generate DV files for an IpBlock''' lookup = TemplateLookup(directories=[resource_filename('reggen', '.')]) uvm_reg_tpl = lookup.get_template('uvm_reg.sv.tpl') # Generate the RAL package(s). For a device interface with no name we # generate the package "_ral_pkg" (writing to _ral_pkg.sv). # In any other case, we also need the interface name, giving # __ral_pkg. generated = [] lblock = block.name.lower() for if_name, rb in block.reg_blocks.items(): hier_path = '' if block.hier_path is None else block.hier_path + '.' if_suffix = '' if if_name is None else '_' + if_name.lower() mod_base = lblock + if_suffix reg_block_path = hier_path + 'u_reg' + if_suffix file_name = mod_base + '_ral_pkg.sv' generated.append(file_name) reg_top_path = os.path.join(outdir, file_name) with open(reg_top_path, 'w', encoding='UTF-8') as fout: try: fout.write(uvm_reg_tpl.render(rb=rb, block=block, esc_if_name=mod_base, reg_block_path=reg_block_path, dv_base_prefix=dv_base_prefix)) except: # noqa F722 for template Exception handling log.error(exceptions.text_error_template().render()) return 1 gen_core_file(outdir, lblock, dv_base_prefix, generated) return 0