// 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, get_block_base_name,
  get_dv_base_names_objects, DvBaseNames)
%>
##
## This template is used for chip-wide tests. It expects to be run with the
## following arguments
##
##    top            a Top object
##
##    dv_base_names  a DvBaseNames object for the base register type
##
## 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.
<%dv_base_names_map = get_dv_base_names_objects(dv_base_names) %>\
% 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 = block.bus_interfaces.device_hier_paths[if_name] + if_suffix
%>\
// Block: ${block_name.lower()}${if_desc}
<%
  block_dv_base_names = get_block_base_name(dv_base_names_map, block_name.lower())
%>\
${make_ral_pkg(block_dv_base_names, 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
  block_dv_base_names = get_block_base_name(dv_base_names_map, "chip")
%>\
${make_ral_pkg_hdr(block_dv_base_names.pkg, if_packages)}
${make_ral_pkg_fwd_decls('chip', [], windows)}
% for window in windows:

${make_ral_pkg_window_class(block_dv_base_names.mem, 'chip', window)}
% endfor

  class chip_reg_block extends ${block_dv_base_names.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
%>\
    bit create_${if_inst} = 1'b1;
    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 (create_${if_inst}) begin
        ${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}));
      end
%     endfor
%   endfor
% endfor
${make_ral_pkg_window_instances(top.regwidth, 'chip', top.window_block)}

    endfunction : build
  endclass : chip_reg_block

endpackage
