// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

// UVM registers auto-generated by `reggen` containing UVM definitions for the entire top-level
<%!
  from topgen.gen_dv import sv_base_addr
  from reggen.gen_dv import bcname, mcname, miname
%>
##
## This template is used for chip-wide tests. It expects to be run with the
## following arguments
##
##    top              a Top object
##
##    dv_base_prefix   a string for the base register type. If it is FOO, then
##                     we will inherit from FOO_reg (assumed to be a subclass
##                     of uvm_reg).
##
## Like uvm_reg.sv.tpl, we use functions from uvm_reg_base.sv.tpl to define
## per-device-interface code.
##
<%namespace file="uvm_reg_base.sv.tpl" import="*"/>\
##
##
## Waive the package-filename check: we're going to be defining all sorts of
## packages in a single file.

// verilog_lint: waive-start package-filename
##
## Iterate over the device interfaces of blocks in Top, constructing a package
## for each. Sorting items like this guarantees we'll work alphabetically in
## block name.
% for block_name, block in sorted(top.blocks.items()):
%   for if_name, rb in block.reg_blocks.items():
<%
      if_suffix = '' if if_name is None else '_' + if_name
      esc_if_name = block_name.lower() + if_suffix
      if_desc = '' if if_name is None else '; interface {}'.format(if_name)
      reg_block_path = 'u_reg' + if_suffix
      reg_block_path = reg_block_path if block.hier_path is None else block.hier_path + "." + reg_block_path
%>\
// Block: ${block_name.lower()}${if_desc}
// TODO(issue #8204): a hack to allow 'real' AST register model to extend from ast_base_reg
//instead of extending directly from dv_base_reg.
//ast_base_reg is an extension of dv_base_reg that abstracts some of the AST specific features
//and that is only visible in Nuvoton's internal repo.
//In chip level register model all the blocks except AST extend from dv_base_reg class.
<%
  dv_base_my_prefix = dv_base_prefix
%>\
%if (block_name.lower() == "ast"):
<%
  dv_base_my_prefix = "ast_base"
%>\
%endif
${make_ral_pkg(dv_base_prefix, top.regwidth, reg_block_path, rb, esc_if_name)}
%   endfor
% endfor
##
##
## Now that we've made the block-level packages, re-instate the
## package-filename check. The only package left is chip_ral_pkg, which should
## match the generated filename.

// verilog_lint: waive-start package-filename

// Block: chip
package chip_ral_pkg;
<%
  if_packages = []
  for block_name, block in sorted(top.blocks.items()):
    for if_name in block.reg_blocks:
      if_suffix = '' if if_name is None else '_' + if_name
      if_packages.append('{}{}_ral_pkg'.format(block_name.lower(), if_suffix))

  windows = top.window_block.windows
%>\
${make_ral_pkg_hdr(dv_base_prefix, if_packages)}
${make_ral_pkg_fwd_decls('chip', [], windows)}
% for window in windows:

${make_ral_pkg_window_class(dv_base_prefix, 'chip', window)}
% endfor

  class chip_reg_block extends ${dv_base_prefix}_reg_block;
    // sub blocks
% for block_name, block in sorted(top.blocks.items()):
%   for inst_name in top.block_instances[block_name.lower()]:
%     for if_name, rb in block.reg_blocks.items():
<%
        if_suffix = '' if if_name is None else '_' + if_name
        esc_if_name = block_name.lower() + if_suffix
        if_inst = inst_name + if_suffix
%>\
    rand ${bcname(esc_if_name)} ${if_inst};
%     endfor
%   endfor
% endfor
% if windows:
    // memories
%   for window in windows:
    rand ${mcname('chip', window)} ${miname(window)};
%   endfor
% endif

    `uvm_object_utils(chip_reg_block)

    function new(string name = "chip_reg_block",
                 int    has_coverage = UVM_NO_COVERAGE);
      super.new(name, has_coverage);
    endfunction : new

    virtual function void build(uvm_reg_addr_t base_addr,
                                csr_excl_item csr_excl = null);
      // create default map
      this.default_map = create_map(.name("default_map"),
                                    .base_addr(base_addr),
                                    .n_bytes(${top.regwidth//8}),
                                    .endian(UVM_LITTLE_ENDIAN));
      if (csr_excl == null) begin
        csr_excl = csr_excl_item::type_id::create("csr_excl");
        this.csr_excl = csr_excl;
      end

      // create sub blocks and add their maps
% for block_name, block in sorted(top.blocks.items()):
%   for inst_name in top.block_instances[block_name.lower()]:
%     for if_name, rb in block.reg_blocks.items():
<%
        if_suffix = '' if if_name is None else '_' + if_name
        esc_if_name = block_name.lower() + if_suffix
        if_inst = inst_name + if_suffix

        if top.attrs.get(inst_name) == 'reggen_only':
          hdl_path = 'tb.dut.u_' + inst_name
        else:
          hdl_path = 'tb.dut.top_earlgrey.u_' + inst_name
        qual_if_name = (inst_name, if_name)
        base_addr = top.if_addrs[qual_if_name]
        base_addr_txt = sv_base_addr(top, qual_if_name)

        hpr_indent = (len(if_inst) + len('.set_hdl_path_root(')) * ' '
%>\
      ${if_inst} =
          ${bcname(esc_if_name)}::type_id::create("${if_inst}");
      ${if_inst}.set_ip_name("${inst_name}");
      ${if_inst}.configure(.parent(this));
      ${if_inst}.build(.base_addr(base_addr + ${base_addr_txt}), .csr_excl(csr_excl));
      ${if_inst}.set_hdl_path_root("${hdl_path}",
      ${hpr_indent}"BkdrRegPathRtl");
      ${if_inst}.set_hdl_path_root("${hdl_path}",
      ${hpr_indent}"BkdrRegPathRtlCommitted");
      ${if_inst}.set_hdl_path_root("${hdl_path}",
      ${hpr_indent}"BkdrRegPathRtlShadow");
      default_map.add_submap(.child_map(${if_inst}.default_map),
                             .offset(base_addr + ${base_addr_txt}));
%     endfor
%   endfor
% endfor
${make_ral_pkg_window_instances(top.regwidth, 'chip', top.window_block)}

    endfunction : build
  endclass : chip_reg_block

endpackage
