text: # 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
  
  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 .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: Register) -> 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 "<block>_ral_pkg" (writing to <block>_ral_pkg.sv).
      # In any other case, we also need the interface name, giving
      # <block>_<ifname>_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
  