// 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}]' if len(r.regs) > 1 else inst_base
          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_prefix   a string naming the base register type. If it is FOO,
##                     then we will inherit from FOO_reg (assumed to
##                     be a subclass of uvm_reg).
##
##    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_prefix, reg_width, reg_block_path, rb, esc_if_name)">\
package ${esc_if_name}_ral_pkg;
${make_ral_pkg_hdr(dv_base_prefix, [])}

${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_prefix, 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_prefix, esc_if_name, window)}
% endfor

<%
  reg_block_name = gen_dv.bcname(esc_if_name)
%>\
  class ${reg_block_name} extends ${dv_base_prefix}_reg_block;
% if rb.flat_regs:
    // registers
  % for r in rb.all_regs:
<%
      if isinstance(r, MultiRegister):
        if r.dv_compact:
          regs = [r.reg]
          count = len(r.regs)
        else:
          regs = r.regs
          count = 1
      else:
        regs = [r]
        count = 1
%>\
    % 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 > 1 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", "BkdrRegPathRtlCommitted");
      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}]' if len(r.regs) > 1 else inst_base
        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_prefix   as for make_ral_pkg
##
##    deps             a list of names for packages that should be explicitly
##                     imported
##
<%def name="make_ral_pkg_hdr(dv_base_prefix, deps)">\
  // dep packages
  import uvm_pkg::*;
  import dv_base_reg_pkg::*;
% if dv_base_prefix != "dv_base":
  import ${dv_base_prefix}_reg_pkg::*;
% 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_prefix   as for make_ral_pkg
##
##    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_prefix, 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_prefix}_reg;
    // 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_prefix}_reg_field ${compact_field_inst_name}${suffix};
% else:
%   for f in fields:
    rand ${dv_base_prefix}_reg_field ${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:
        reg_field_name = reg_field_name + f'[{idx + start_idx}]'
    else:
      reg_field_name = field.name.lower()
%>\
${_create_reg_field(dv_base_prefix, 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_prefix   as for make_ral_pkg
##
##    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_prefix, 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_prefix}_reg_field::
      ${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_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_prefix   as for make_ral_pkg
##
##    esc_if_name      as for make_ral_pkg
##
##    window           a Window object
<%def name="make_ral_pkg_window_class(dv_base_prefix, 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_prefix}_mem;

    `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
    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.hwext:
      shadowed_reg_path = ''
      for tag in reg.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!")
        assert 0

      bit_idx = reg.fields[-1].bits.msb + 1
%>\
      % 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:
      ${reg_inst}.add_hdl_path_slice(
          "${shadowed_reg_path}.committed_reg.q",
          0, ${bit_idx}, 0, "BkdrRegPathRtlCommitted");
      ${reg_inst}.add_hdl_path_slice(
          "${shadowed_reg_path}.shadow_reg.q",
          0, ${bit_idx}, 0, "BkdrRegPathRtlShadow");
  % 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");
%   else:
      ${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, "BkdrRegPathRtlCommitted");
      ${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>\
