// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
<%!
  from reggen import gen_dv
  from reggen.access import HwAccess, SwRdAccess, SwWrAccess
  from reggen.multi_register import MultiRegister
  from reggen.register import Register
  from typing import Dict

  # Get a list reg and its instance name
  # For single reg, return Dict[reg_inst:reg]
  # For multireg, if it's dv_compact, return Dict[mr.name[idx]:mr.reg],
  # if not, return all the mr.regs with their name
  def get_inst_to_reg_dict(r) -> Dict:
    inst_regs = {} # type: Dict[inst_name:Register]
    if isinstance(r, MultiRegister):
      if r.dv_compact:
        inst_base = r.reg.name.lower()
        for idx, reg in enumerate(r.regs):
          inst_name = f'{inst_base}[{idx}]'
          inst_regs[inst_name] = reg
      else:
        for r0 in r.regs:
          inst_regs[r0.name] = r0
    else:
      inst_regs[r.name.lower()] = r
    return inst_regs
%>\
##
##
## make_ral_pkg
## ============
##
## Generate the RAL package for a device interface.
##
##    dv_base_names     a DvBaseNames object that contains register base class names
##
##    reg_width         an integer giving the width of registers in bits
##
##    reg_block_path    the hierarchical path to the relevant register block in the
##                      design
##
##    rb                a RegBlock object
##
##    esc_if_name       a string giving the full, escaped, interface name. For
##                      a device interface called FOO on block BAR,
##                      this will be bar__foo. For an unnamed interface
##                      on block BAR, this will be just bar.
##
<%def name="make_ral_pkg(dv_base_names, reg_width, reg_block_path, rb, esc_if_name)">\
package ${esc_if_name}_ral_pkg;
${make_ral_pkg_hdr(dv_base_names.pkg, [])}

${make_ral_pkg_fwd_decls(esc_if_name, rb.type_regs, rb.windows)}
% for r in rb.all_regs:
<%
    mr = None
    if isinstance(r, MultiRegister):
      mr = r
      if r.dv_compact:
        regs = [r.reg]
      else:
        regs = r.regs
    else:
      regs = [r]
%>\
  % for idx, reg in enumerate(regs):

${make_ral_pkg_reg_class(dv_base_names.reg, dv_base_names.field, reg_width, esc_if_name,
reg_block_path, reg, mr, idx)}
  % endfor
% endfor
% for window in rb.windows:

${make_ral_pkg_window_class(dv_base_names.mem, esc_if_name, window)}
% endfor

<%
  reg_block_name = gen_dv.bcname(esc_if_name)
%>\
  class ${reg_block_name} extends ${dv_base_names.block};
% if rb.flat_regs:
    // registers
  % for r in rb.all_regs:
<%
      # If it's dv_compact, then create it as an array even when it only contains one item
      count = 0
      if isinstance(r, MultiRegister):
        if r.dv_compact:
          regs = [r.reg]
          count = len(r.regs)
        else:
          regs = r.regs
      else:
        regs = [r]
%>\
    % for r0 in regs:
<%
      reg_type = gen_dv.rcname(esc_if_name, r0)
      inst_name = r0.name.lower()
      inst_decl = f'{inst_name}[{count}]' if count > 0 else inst_name
%>\
    rand ${reg_type} ${inst_decl};
    % endfor
  % endfor
% endif
% if rb.windows:
    // memories
% for window in rb.windows:
    rand ${gen_dv.mcname(esc_if_name, window)} ${gen_dv.miname(window)};
% endfor
% endif

    `uvm_object_utils(${reg_block_name})

    function new(string name = "${reg_block_name}",
                 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(${reg_width//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
% if rb.flat_regs:
      set_hdl_path_root("tb.dut", "BkdrRegPathRtl");
      set_hdl_path_root("tb.dut", "BkdrRegPathRtlShadow");
      // create registers
  % for r in rb.all_regs:
<%
    r0 = r.reg if isinstance(r, MultiRegister) else r
    reg_type = gen_dv.rcname(esc_if_name, r0)
%>\
    % if isinstance(r, MultiRegister):
      % for idx, reg in enumerate(r.regs):
<%
        if r.dv_compact:
          inst_base = r0.name.lower()
          inst_name = f'{inst_base}[{idx}]'
        else:
          inst_name = reg.name.lower()
          reg_type = gen_dv.rcname(esc_if_name, reg)
%>\
${instantiate_register(reg_width, reg_block_path, reg, reg_type, inst_name)}\
      % endfor
    % else:
${instantiate_register(reg_width, reg_block_path, r, reg_type, r.name.lower())}\
    % endif
  % endfor
<%
  any_regwen = False
  for r in rb.flat_regs:
    if r.regwen:
      any_regwen = True
      break
%>\
  % if any_regwen:
      // assign locked reg to its regwen reg
    % for r in rb.all_regs:
      % for inst, reg in get_inst_to_reg_dict(r).items():
${apply_regwen(rb, reg, inst)}\
      % endfor
    % endfor
  % endif
% endif
${make_ral_pkg_window_instances(reg_width, esc_if_name, rb)}
    endfunction : build
  endclass : ${reg_block_name}

endpackage
</%def>\
##
##
## make_ral_pkg_hdr
## ================
##
## Generate the header for a RAL package
##
##    dv_base_reg_pkg_name   a string name for the base reg_pkg type
##
##    deps                   a list of names for packages that should be explicitly
##                           imported
##
<%def name="make_ral_pkg_hdr(dv_base_reg_pkg_name, deps)">\
  // dep packages
  import uvm_pkg::*;
  import dv_base_reg_pkg::*;
% if dv_base_reg_pkg_name != "dv_base_reg_pkg":
  import ${dv_base_reg_pkg_name}::*;
% endif
% for dep in deps:
  import ${dep}::*;
% endfor

  // macro includes
  `include "uvm_macros.svh"\
</%def>\
##
##
## make_ral_pkg_fwd_decls
## ======================
##
## Generate the forward declarations for a RAL package
##
##    esc_if_name      as for make_ral_pkg
##
##    type_regs        a list of Register objects, one for each type that
##                     should be defined. Each MultiRegister will contribute
##                     just one register to the list.
##
##    windows          a list of Window objects
##
<%def name="make_ral_pkg_fwd_decls(esc_if_name, type_regs, windows)">\
  // Forward declare all register/memory/block classes
% for r in type_regs:
  typedef class ${gen_dv.rcname(esc_if_name, r)};
% endfor
% for w in windows:
  typedef class ${gen_dv.mcname(esc_if_name, w)};
% endfor
  typedef class ${gen_dv.bcname(esc_if_name)};\
</%def>\
##
##
## make_ral_pkg_reg_class
## ======================
##
## Generate the classes for a register inside a RAL package
##
##    dv_base_reg_name     a string name for the base register type
##
##    dv_base_field_name   a string name for the base reg_field type
##
##    reg_width            as for make_ral_pkg
##
##    esc_if_name          as for make_ral_pkg
##
##    reg_block_path       as for make_ral_pkg
##
##    reg                  a Register object
##
##    mr                   a MultiRegister object if this reg is from a MultiRegister
##
##    reg_idx              the index location of this reg if this reg is from a MultiRegister,
##                         or zero if not
<%def name="make_ral_pkg_reg_class(dv_base_reg_name, dv_base_field_name, reg_width, esc_if_name,
reg_block_path, reg, mr, reg_idx)">\
<%
  reg_name = reg.name.lower()

  is_ext = reg.hwext
  for field in reg.fields:
    if (field.hwaccess.value[1] == HwAccess.NONE and
        field.swaccess.swrd() == SwRdAccess.RD and
        not field.swaccess.allows_write()):
      is_ext = 1

  class_name = gen_dv.rcname(esc_if_name, reg)
%>\
  class ${class_name} extends ${dv_base_reg_name};
    // fields
<%
  suffix = ""
  start_idx = 0
  add_style_waive = False
  compact_field_inst_name = ""
  if mr is None:
      fields = reg.fields
  else:
    if not mr.compact:
      fields = mr.reg.fields
    else:
      fields = mr.regs[reg_idx].fields
      compact_field_inst_name = mr.reg.fields[0].name.lower()
      if mr.dv_compact:
        # The dv_compact flag means that the fields of the multi-reg divide equally into registers.
        # In this case, there's an array of registers and make_ral_pkg_reg_class() gets called once
        # to define that array's type, using the fields of the first register in the replication.
        assert reg_idx == 0
        if len(fields) > 1:
          suffix = f'[{len(fields)}]'
      else:
        # In this case, the multi-register is "compact", so there might be multiple copies of its
        # single field in each generated register. But dv_compact is false, which probably means
        # that the fields didn't divide equally into a whole number of registers. In this case, we
        # are generating a different class for each output register and should spit out fields
        # accordingly. Note that we generate an array, even if len(fields) = 1. If that happens, we
        # know we're on the last generated register, so want to keep everything uniform.
        num_fields_per_reg = 32 // fields[0].bits.width()
        start_idx = num_fields_per_reg * reg_idx
        end_idx = start_idx + len(fields) - 1
        suffix = f'[{start_idx}:{end_idx}]'
        if start_idx == 0:
          add_style_waive = True
%>\
% if add_style_waive:
    // verilog_lint: waive unpacked-dimensions-range-ordering
% endif
% if compact_field_inst_name:
    rand ${dv_base_field_name} ${compact_field_inst_name}${suffix};
% else:
%   for f in fields:
    rand ${dv_base_field_name} ${f.name.lower()};
%   endfor
% endif

    `uvm_object_utils(${class_name})

    function new(string       name = "${class_name}",
                 int unsigned n_bits = ${reg_width},
                 int          has_coverage = UVM_NO_COVERAGE);
      super.new(name, n_bits, has_coverage);
    endfunction : new

    virtual function void build(csr_excl_item csr_excl = null);
      // create fields
% for idx, field in enumerate(fields):
<%
    if compact_field_inst_name:
      reg_field_name = compact_field_inst_name
      # If len(fields) > 1, we define generated reg fields as an array and we need an index to
      # refer to the field object
      # If start_idx > 0, the fields cross more than one register, we define an array for the
      # fields even when the last register only contains one field.
      if len(fields) > 1 or start_idx > 0:
        reg_field_name = reg_field_name + f'[{idx + start_idx}]'
    else:
      reg_field_name = field.name.lower()
%>\
${_create_reg_field(dv_base_field_name, reg_width, reg_block_path, reg.shadowed, reg.hwext,
reg_field_name, field)}
% endfor
% if is_ext:
      set_is_ext_reg(1);
% endif
    endfunction : build
  endclass : ${class_name}\
</%def>\
##
##
## _create_reg_field
## =================
##
## Generate the code that creates a uvm_reg_field object for a field
## in a register.
##
##    dv_base_reg_field_name   as for make_ral_pkg_reg_class
##
##    reg_width                as for make_ral_pkg
##
##    reg_block_path           as for make_ral_pkg
##
##    shadowed                 true if the field's register is shadowed
##
##    hwext                    true if the field's register is hwext
##
##    reg_field_name           a string with the name to give the field in the HDL
##
##    field                    a Field object
<%def name="_create_reg_field(dv_base_reg_field_name, reg_width, reg_block_path, shadowed, hwext,
reg_field_name, field)">\
<%
  field_size = field.bits.width()
  field_access = field.swaccess.dv_rights()

  if not field.hwaccess.allows_write():
    field_volatile = 0
  else:
    field_volatile = 1
  field_tags = field.tags

  fname = reg_field_name
  type_id_indent = ' ' * (len(fname) + 4)
%>\
      ${fname} = (${dv_base_reg_field_name}::
      ${type_id_indent}type_id::create("${field.name.lower()}"));
      ${fname}.configure(
        .parent(this),
        .size(${field_size}),
        .lsb_pos(${field.bits.lsb}),
        .access("${field_access}"),
        .volatile(${field_volatile}),
        .reset(${reg_width}'h${format(field.resval or 0, 'x')}),
        .has_reset(1),
        .is_rand(1),
        .individually_accessible(1));

      ${fname}.set_original_access("${field_access}");
% if field.mubi:
      ${fname}.create_mubi_cov(.mubi_width(${field_size}));
% endif
% if field_tags:
      // create field tags
%     for field_tag in field_tags:
<%
  tag = field_tag.split(":")
%>\
%       if tag[0] == "excl":
      csr_excl.add_excl(${fname}.get_full_name(), ${tag[2]}, ${tag[1]});
%       endif
%     endfor
%   endif
</%def>\
##
##
## make_ral_pkg_window_class
## =========================
##
## Generate the classes for a window inside a RAL package
##
##    dv_base_window_name   a string name for the base windoe type
##
##    esc_if_name           as for make_ral_pkg
##
##    window                a Window object
<%def name="make_ral_pkg_window_class(dv_base_window_name, esc_if_name, window)">\
<%
  mem_name = window.name.lower()
  mem_right = window.swaccess.dv_rights()
  mem_n_bits = window.validbits
  mem_size = window.items

  class_name = gen_dv.mcname(esc_if_name, window)
%>\
  class ${class_name} extends ${dv_base_window_name};

    `uvm_object_utils(${class_name})

    function new(string           name = "${class_name}",
                 longint unsigned size = ${mem_size},
                 int unsigned     n_bits = ${mem_n_bits},
                 string           access = "${mem_right}",
                 int              has_coverage = UVM_NO_COVERAGE);
      super.new(name, size, n_bits, access, has_coverage);
%     if window.byte_write:
      set_mem_partial_write_support(1);
%     endif
%     if window.data_intg_passthru:
      set_data_intg_passthru(1);
%     endif
    endfunction : new

  endclass : ${class_name}
</%def>\
##
##
## make_ral_pkg_window_instances
## =============================
##
## Generate the classes for a window inside a RAL package
##
##    reg_width        as for make_ral_pkg
##
##    esc_if_name      as for make_ral_pkg
##
##    rb               a RegBlock object
##
<%def name="make_ral_pkg_window_instances(reg_width, esc_if_name, rb)">\
% if rb.windows:

      // create memories
%  for w in rb.windows:
<%
      mem_name = w.name.lower()
      mem_right = w.swaccess.dv_rights()
      mem_offset = "{}'h{:x}".format(reg_width, w.offset)
      mem_n_bits = w.validbits
      mem_size = w.items
%>\
      ${mem_name} =
          ${gen_dv.mcname(esc_if_name, w)}::type_id::create("${mem_name}");
      ${mem_name}.configure(.parent(this));
      default_map.add_mem(.mem(${mem_name}),
                          .offset(${mem_offset}),
                          .rights("${mem_right}"));
%   endfor
% endif
</%def>\
##
##
## instantiate_register
## ====================
##
## Actually instantiate a register in a register block
##
##    reg_width        an integer giving the width of registers in bits
##
##    reg_block_path   as for make_ral_pkg
##
##    reg              the Register to instantiate
##
##    reg_type         a string giving the type name (a subclass of
##                     uvm_register) to instantiate.
##
##    reg_inst         a string giving the field of the uvm_reg_block that
##                     should be set to this new register. For single
##                     registers, this will just be the register name. For
##                     elements of multi-registers, it will be the name of an
##                     array item.
##
<%def name="instantiate_register(reg_width, reg_block_path, reg, reg_type, reg_inst)">\
<%
      reg_name = reg.name.lower()
      reg_offset = "{}'h{:x}".format(reg_width, reg.offset)

      inst_id_indent = ' ' * (len(reg_inst) + 4)
%>\
      ${reg_inst} = (${reg_type}::
      ${inst_id_indent}type_id::create("${reg_name}"));
      ${reg_inst}.configure(.blk_parent(this));
      ${reg_inst}.build(csr_excl);
      default_map.add_reg(.rg(${reg_inst}),
                          .offset(${reg_offset}));
% if reg.shadowed:
      % if reg.update_err_alert:
      ${reg_inst}.add_update_err_alert("${reg.update_err_alert}");
      % endif

      % if reg.storage_err_alert:
      ${reg_inst}.add_storage_err_alert("${reg.storage_err_alert}");
      % endif

  % if reg.hwext:
    % for field in reg.fields:
<%
      shadowed_reg_path = ''
      for tag in field.tags:
        parts = tag.split(':')
        if parts[0] == 'shadowed_reg_path':
          shadowed_reg_path = parts[1]

      if not shadowed_reg_path:
        print("ERROR: ext shadow_reg does not have tags for shadowed_reg_path for each field!")
        assert 0
%>\
      ${reg_inst}.add_hdl_path_slice(
          "${shadowed_reg_path}.committed_reg.q",
          ${field.bits.lsb}, ${field.bits.width()}, 0, "BkdrRegPathRtl");
      ${reg_inst}.add_hdl_path_slice(
          "${shadowed_reg_path}.shadow_reg.q",
          ${field.bits.lsb}, ${field.bits.width()}, 0, "BkdrRegPathRtlShadow");
    % endfor
  % endif
% endif
% for field in reg.fields:
<%
    field_size = field.bits.width()
    if len(reg.fields) == 1:
      reg_field_name = reg_name
    else:
      reg_field_name = reg_name + "_" + field.name.lower()

    ##if reg.async_name and not reg.hwext:
    ##  reg_field_name += ".u_subreg"
%>\
%   if ((field.hwaccess.value[1] == HwAccess.NONE and\
       field.swaccess.swrd() == SwRdAccess.RD and\
       not field.swaccess.allows_write())):
      // constant reg
      ${reg_inst}.add_hdl_path_slice(
          "${reg_block_path}.${reg_field_name}_qs",
          ${field.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtl");
%   elif not reg.shadowed:
      ${reg_inst}.add_hdl_path_slice(
          "${reg_block_path}.u_${reg_field_name}.q${"s" if reg.hwext else ""}",
          ${field.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtl");
%   endif
%   if reg.shadowed and not reg.hwext:
      ${reg_inst}.add_hdl_path_slice(
          "${reg_block_path}.u_${reg_field_name}.committed_reg.q",
          ${field.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtl");
      ${reg_inst}.add_hdl_path_slice(
          "${reg_block_path}.u_${reg_field_name}.shadow_reg.q",
          ${field.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtlShadow");
%   endif
% endfor

%     if reg.shadowed:
      ${reg_inst}.set_is_shadowed();
%     endif
%     if reg.tags:
      // create register tags
%       for reg_tag in reg.tags:
<%
        tag = reg_tag.split(":")
%>\
%         if tag[0] == "excl":
      csr_excl.add_excl(${reg_inst}.get_full_name(), ${tag[2]}, ${tag[1]});
%         endif
%       endfor
%     endif
</%def>\
##
##
## apply_regwen
## ============
##
## Apply a regwen to a register
##
##    rb               the register block
##
##    reg              the Register that needs apply regwens
##
##    reg_inst         a string giving the field of the uvm_reg_block that
##                     should be updated. For single registers, this will just
##                     be the register name. For elements of multi-registers,
##                     it will be the name of an array item.
##
<%def name="apply_regwen(rb, reg, reg_inst)">\
% if reg.regwen is None:
<% return "" %>\
% endif
% for wen in rb.all_regs:
%   for wen_inst, wen_reg in get_inst_to_reg_dict(wen).items():
%     if reg.regwen.lower() == wen_reg.name.lower():
      ${wen_inst}.add_lockable_reg_or_fld(${reg_inst});
<% return "" %>\
%     elif wen_reg.name.lower() in reg.regwen.lower():
%       for field in wen_reg.get_field_list():
%         if reg.regwen.lower() == (wen_reg.name.lower() + "_" + field.name.lower()):
      ${wen_inst}.${field.name.lower()}.add_lockable_reg_or_fld(${reg_inst});
<% return "" %>\
%         endif
%       endfor
%     endif
%   endfor
% endfor
</%def>\
