// Copyright 2022-2023 Google LLC.
// 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
##
##    create_isp_wrapper	Create isp_wrapper RAL model based on the context
##
##    create_dma     Create RAL models for dma0/dma_smc based on the context
##
## 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

        create_block = "1'b1"
        if (inst_name == "rv_plic_smc" or
            inst_name == "tlul_mailbox_smc" or
            inst_name == "rv_core_ibex_smc"):
          create_block = "1'b0"
        elif inst_name == "isp_wrapper":
          create_block = create_isp_wrapper
        elif (inst_name == "dma0" or
              inst_name == "dma_smc"):
          create_block = create_dma
%>\
    bit create_${if_inst} = ${create_block};
    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_matcha.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
