// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Register Package auto-generated by `reggen` containing data structure

<%
  num_regs = block.get_n_regs_flat()
  max_regs_char = len("{}".format(num_regs-1))
%>\
package ${block.name}_reg_pkg;
% if len(block.params) != 0:

  // Param list
% endif
% for param in [p for p in block.params if p["local"] == "true"]:
  localparam ${param["type"]} ${param["name"]} = ${param["default"]};
% endfor

% if block.contains_multiregs():
////////////////////////////
// Typedefs for multiregs //
////////////////////////////

% for r in block.regs:
  ## in this case we have a homogeneous multireg, with only one replicated field
  % if r.is_multi_reg() and r.get_n_bits(["q"]) and r.ishomog:
typedef struct packed {
  logic [${r.get_field_flat(0).get_n_bits()-1}:0] q;
  % if r.get_field_flat(0).hwqe:
  logic qe;
  % endif
  % if r.get_field_flat(0).hwre:
  logic re;
  % endif
} ${block.name + "_reg2hw_" + r.name + "_mreg_t"};
  ## in this case we have an inhomogeneous multireg, with several different fields per register
  % elif r.is_multi_reg() and r.get_n_bits(["q"]) and not r.ishomog:
typedef struct packed {
    % for f in r.get_reg_flat(0).fields:
  struct packed {
    logic [${f.get_n_bits()-1}:0] q;
      % if f.hwqe:
    logic qe;
      % endif
      % if f.hwre:
    logic re;
      % endif
  } ${f.get_basename()};
    %endfor
} ${block.name + "_reg2hw_" + r.name + "_mreg_t"};
  %endif
% endfor

% for r in block.regs:
 ## in this case we have a homogeneous multireg, with only one replicated field
  % if r.is_multi_reg() and r.get_n_bits(["d"]) and r.ishomog:
typedef struct packed {
  logic [${r.get_field_flat(0).get_n_bits(["d"])-1}:0] d;
    % if not r.get_reg_flat(0).hwext:
  logic de;
    % endif
} ${block.name + "_hw2reg_" + r.name + "_mreg_t"};
  ## in this case we have an inhomogeneous multireg, with several different fields per register
  % elif r.is_multi_reg() and r.get_n_bits(["d"]) and not r.ishomog:
typedef struct packed {
    % for f in r.get_reg_flat(0).fields:
  struct packed {
    logic [${f.get_n_bits(["d"])-1}:0] d;
      % if not r.hwext:
    logic de;
      % endif
  } ${f.get_basename()};
    %endfor
} ${block.name + "_hw2reg_" + r.name + "_mreg_t"};
  % endif
% endfor

% endif
///////////////////////////////////////
// Register to internal design logic //
///////////////////////////////////////
<%
nbits = block.get_n_bits(["q","qe","re"]) - 1
packbit = 0
%>
% if nbits > 0:
typedef struct packed {
% for r in block.regs:
  ######################## multiregister ###########################
  % if r.is_multi_reg() and r.get_n_bits(["q"]):
  <%
  array_dims = ""
  for d in r.get_nested_dims():
    array_dims += "[%d:0]" % (d-1)
  %>${block.name + "_reg2hw_" + r.name + "_mreg_t"} ${array_dims} ${r.name}; // [${nbits - packbit}:${nbits - (packbit + r.get_n_bits(["q", "qe", "re"]) - 1)}]<% packbit += r.get_n_bits(["q", "qe", "re"]) %>
  ######################## register with single field ###########################
  % elif len(r.fields) == 1 and r.get_n_bits(["q"]):
    ## Only one field, should use register name as it is
  struct packed {
    logic [${r.fields[0].get_n_bits()-1}:0] q; // [${nbits - packbit}:${nbits - (packbit + r.fields[0].get_n_bits() - 1)}]<% packbit += r.fields[0].get_n_bits() %>
    % if r.fields[0].hwqe:
    logic qe; // [${nbits - packbit}]<% packbit += 1 %>
    % endif
    % if r.fields[0].hwre:
    logic re; // [${nbits - packbit}]<% packbit += 1 %>
    % endif
  } ${r.name};
  ######################## register with multiple fields ###########################
  % elif len(r.fields) >= 2 and r.get_n_bits(["q"]):
  struct packed {
    % for f in r.fields:
      % if f.hwaccess in [HwAccess.HRW, HwAccess.HRO]:
    struct packed {
      ## reg2hw signal based on HW type and virtual?
      % if f.get_n_bits() > 1:
      logic [${f.get_n_bits()-1}:0] q; // [${nbits - packbit}:${nbits - (packbit + f.get_n_bits() - 1)}]<% packbit += f.get_n_bits() %>
      % else:
      logic q; // [${nbits - packbit}]<% packbit += 1 %>
      % endif
      % if f.hwqe:
      logic qe; // [${nbits - packbit}]<% packbit += 1 %>
      % endif
      % if f.hwre:
      logic re; // [${nbits - packbit}]<% packbit += 1 %>
      % endif
    } ${f.name};
      % endif
    % endfor
  } ${r.name};
  % endif
% endfor
} ${block.name}_reg2hw_t;
% endif

///////////////////////////////////////
// Internal design logic to register //
///////////////////////////////////////
<%
nbits = block.get_n_bits(["d","de"]) - 1
packbit = 0
%>
% if nbits > 0:
typedef struct packed {
% for r in block.regs:
  ######################## multiregister ###########################
  % if r.is_multi_reg() and r.get_n_bits(["d"]):
  <%
  array_dims = ""
  for d in r.get_nested_dims():
    array_dims += "[%d:0]" % (d-1)
  %>${block.name + "_hw2reg_" + r.name + "_mreg_t"} ${array_dims} ${r.name}; // [${nbits - packbit}:${nbits - (packbit + r.get_n_bits(["d", "de"]) - 1)}]<% packbit += r.get_n_bits(["d", "de"]) %>
  ######################## register with single field ###########################
  % elif len(r.fields) == 1 and r.get_n_bits(["d"]):
    ## Only one field, should use register name as it is
  struct packed {
    logic [${r.fields[0].get_n_bits("d")-1}:0] d; // [${nbits - packbit}:${nbits - (packbit + r.fields[0].get_n_bits("d") - 1)}]<% packbit += r.fields[0].get_n_bits("d") %>
    % if r.hwext == 0:
    logic de; // [${nbits - packbit}]<% packbit += 1 %>
    % endif
  } ${r.name};
  ######################## register with multiple fields ###########################
  % elif len(r.fields) >= 2 and r.get_n_bits(["d"]):
  struct packed {
    % for f in r.fields:
      % if f.hwaccess in [HwAccess.HRW, HwAccess.HWO]:
    struct packed {
      ## reg2hw signal based on HW type and virtual?
      % if f.get_n_bits("d") > 1:
      logic [${f.get_n_bits("d")-1}:0] d; // [${nbits - packbit}:${nbits - (packbit + f.get_n_bits("d") - 1)}]<% packbit += f.get_n_bits("d") %>
      % else:
      logic d; // [${nbits - packbit}]<% packbit += 1 %>
      % endif
      % if not r.hwext:
      logic de; // [${nbits - packbit}]<% packbit += 1 %>
      % endif
    } ${f.name};
      % endif
    % endfor
  } ${r.name};
  % endif
% endfor
} ${block.name}_hw2reg_t;
% endif

  // Register Address
% for r in block.get_regs_flat():
  parameter ${block.name.upper()}_${r.name.upper()}_OFFSET = ${block.addr_width}'h ${"%x" % r.offset};
% endfor

% if len(block.wins) > 0:
  // Window parameter
% endif
% for i,w in enumerate(block.wins):
  parameter ${block.name.upper()}_${w.name.upper()}_OFFSET = ${block.addr_width}'h ${"%x" % w.base_addr};
  parameter ${block.name.upper()}_${w.name.upper()}_SIZE   = ${block.addr_width}'h ${"%x" % (w.limit_addr - w.base_addr)};
% endfor

  // Register Index
  typedef enum int {
% for r in block.get_regs_flat():
    ${block.name.upper()}_${r.name.upper()}${"" if loop.last else ","}
% endfor
  } ${block.name}_id_e;

  // Register width information to check illegal writes
  localparam logic [3:0] ${block.name.upper()}_PERMIT [${block.get_n_regs_flat()}] = '{
% for i,r in enumerate(block.get_regs_flat()):
<% index_str = "{}".format(i).rjust(max_regs_char) %>\
  % if r.width > 24:
    4'b 1111${" " if i == num_regs-1 else ","} // index[${index_str}] ${block.name.upper()}_${r.name.upper()}
  % elif r.width > 16:
    4'b 0111${" " if i == num_regs-1 else ","} // index[${index_str}] ${block.name.upper()}_${r.name.upper()}
  % elif r.width > 8:
    4'b 0011${" " if i == num_regs-1 else ","} // index[${index_str}] ${block.name.upper()}_${r.name.upper()}
  % else:
    4'b 0001${" " if i == num_regs-1 else ","} // index[${index_str}] ${block.name.upper()}_${r.name.upper()}
  % endif
% endfor
  };
endpackage

