| // 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 |
| |
| <% |
| from topgen import lib # TODO: Split lib to common lib module |
| 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"]: |
| parameter ${param["type"]} ${param["name"]} = ${param["default"]}; |
| % endfor |
| |
| //////////////////////////// |
| // Typedefs for registers // |
| //////////////////////////// |
| % for r in block.regs: |
| ## in this case we have a homogeneous multireg, with only one replicated field |
| % if r.get_n_bits(["q"]) and r.ishomog: |
| typedef struct packed { |
| logic ${lib.bitarray(r.get_field_flat(0).get_n_bits(["q"]),2)} q; |
| % if r.get_field_flat(0).hwqe: |
| logic qe; |
| % endif |
| % if r.get_field_flat(0).hwre or (r.get_field_flat(0).shadowed and r.get_field_flat(0).hwext): |
| logic re; |
| % endif |
| % if r.get_field_flat(0).shadowed and not r.get_field_flat(0).hwext: |
| logic err_update; |
| logic err_storage; |
| % endif |
| } ${block.name + "_reg2hw_" + r.name + ("_mreg_t" if r.is_multi_reg() else "_reg_t")}; |
| |
| ## in this case we have an inhomogeneous multireg, with several different fields per register |
| % elif r.get_n_bits(["q"]) and not r.ishomog: |
| typedef struct packed { |
| % for f in r.get_reg_flat(0).fields: |
| % if f.get_n_bits(["q"]) >= 1: |
| struct packed { |
| logic ${lib.bitarray(f.get_n_bits(["q"]),2)} q; |
| % if f.hwqe: |
| logic qe; |
| % endif |
| % if f.hwre or (f.shadowed and f.hwext): |
| logic re; |
| % endif |
| % if f.shadowed and not f.hwext: |
| logic err_update; |
| logic err_storage; |
| % endif |
| } ${f.get_basename() if r.is_multi_reg() else f.name}; |
| %endif |
| %endfor |
| } ${block.name + "_reg2hw_" + r.name + ("_mreg_t" if r.is_multi_reg() else "_reg_t")}; |
| |
| %endif |
| % endfor |
| |
| % for r in block.regs: |
| ## in this case we have a homogeneous multireg, with only one replicated field |
| % if r.get_n_bits(["d"]) and r.ishomog: |
| typedef struct packed { |
| logic ${lib.bitarray(r.get_field_flat(0).get_n_bits(["d"]),2)} d; |
| % if not r.get_reg_flat(0).hwext: |
| logic de; |
| % endif |
| } ${block.name + "_hw2reg_" + r.name + ("_mreg_t" if r.is_multi_reg() else "_reg_t")}; |
| |
| ## in this case we have an inhomogeneous multireg, with several different fields per register |
| % elif r.get_n_bits(["d"]) and not r.ishomog: |
| typedef struct packed { |
| % for f in r.get_reg_flat(0).fields: |
| % if f.get_n_bits(["d"]) >= 1: |
| struct packed { |
| logic ${lib.bitarray(f.get_n_bits(["d"]),2)} d; |
| % if not r.hwext: |
| logic de; |
| % endif |
| } ${f.get_basename() if r.is_multi_reg() else f.name}; |
| %endif |
| %endfor |
| } ${block.name + "_hw2reg_" + r.name + ("_mreg_t" if r.is_multi_reg() else "_reg_t")}; |
| |
| % endif |
| % endfor |
| |
| /////////////////////////////////////// |
| // Register to internal design logic // |
| /////////////////////////////////////// |
| <% |
| nbits = block.get_n_bits(["q","qe","re"]) |
| 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 - 1}:${nbits - (packbit + r.get_n_bits(["q", "qe", "re"]))}]<% packbit += r.get_n_bits(["q", "qe", "re"]) %>\ |
| |
| ######################## register ########################### |
| % elif r.get_n_bits(["q"]): |
| ## Only one field, should use register name as it is |
| ${block.name + "_reg2hw_" + r.name + "_reg_t"} ${r.name}; // [${nbits - packbit - 1}:${nbits - (packbit + r.get_n_bits(["q", "qe", "re"]))}]<% packbit += r.get_n_bits(["q", "qe", "re"]) %>\ |
| |
| % endif |
| % endfor |
| } ${block.name}_reg2hw_t; |
| % endif |
| |
| /////////////////////////////////////// |
| // Internal design logic to register // |
| /////////////////////////////////////// |
| <% |
| nbits = block.get_n_bits(["d","de"]) |
| 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 - 1}:${nbits - (packbit + r.get_n_bits(["d", "de"]))}]<% packbit += r.get_n_bits(["d", "de"]) %>\ |
| |
| ######################## register with single field ########################### |
| % elif r.get_n_bits(["d"]): |
| ## Only one field, should use register name as it is |
| ${block.name + "_hw2reg_" + r.name + "_reg_t"} ${r.name}; // [${nbits - packbit - 1}:${nbits - (packbit + r.get_n_bits(["q", "qe", "re"]))}]<% packbit += r.get_n_bits(["q", "qe", "re"]) %>\ |
| |
| % endif |
| % endfor |
| } ${block.name}_hw2reg_t; |
| % endif |
| |
| // Register Address |
| % for r in block.get_regs_flat(): |
| parameter logic [${block.addr_width-1}:0] ${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 logic [${block.addr_width-1}:0] ${block.name.upper()}_${w.name.upper()}_OFFSET = ${block.addr_width}'h ${"%x" % w.base_addr}; |
| parameter logic [${block.addr_width-1}:0] ${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 |
| parameter 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 |
| |