lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 1 | // Copyright lowRISC contributors. |
| 2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | // SPDX-License-Identifier: Apache-2.0 |
| 4 | // |
| 5 | // Register Package auto-generated by `reggen` containing data structure |
| 6 | |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 7 | <% |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 8 | num_regs = block.get_n_regs_flat() |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 9 | max_regs_char = len("{}".format(num_regs-1)) |
| 10 | %>\ |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 11 | package ${block.name}_reg_pkg; |
Eunchan Kim | c4873f3 | 2019-09-25 12:46:12 -0700 | [diff] [blame] | 12 | % if len(block.params) != 0: |
| 13 | |
| 14 | // Param list |
| 15 | % endif |
Eunchan Kim | b993190 | 2019-09-26 14:16:40 -0700 | [diff] [blame] | 16 | % for param in [p for p in block.params if p["local"] == "true"]: |
Eunchan Kim | c4873f3 | 2019-09-25 12:46:12 -0700 | [diff] [blame] | 17 | localparam ${param["type"]} ${param["name"]} = ${param["default"]}; |
| 18 | % endfor |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 19 | |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 20 | % if block.contains_multiregs(): |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 21 | ///////////////////////////////////////////////////////////////////// |
| 22 | // Typedefs for multiregs |
| 23 | ///////////////////////////////////////////////////////////////////// |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 24 | |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 25 | % for r in block.regs: |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 26 | ## in this case we have a homogeneous multireg, with only one replicated field |
| 27 | % if r.is_multi_reg() and r.get_n_bits(["q"]) and r.ishomog: |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 28 | typedef struct packed { |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 29 | logic [${r.get_field_flat(0).get_n_bits()-1}:0] q; |
| 30 | % if r.get_field_flat(0).hwqe: |
| 31 | logic qe; |
| 32 | % endif |
| 33 | % if r.get_field_flat(0).hwre: |
| 34 | logic re; |
| 35 | % endif |
| 36 | } ${block.name + "_reg2hw_" + r.name + "_mreg_t"}; |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 37 | ## in this case we have an inhomogeneous multireg, with several different fields per register |
| 38 | % elif r.is_multi_reg() and r.get_n_bits(["q"]) and not r.ishomog: |
| 39 | typedef struct packed { |
| 40 | % for f in r.get_reg_flat(0).fields: |
| 41 | struct packed { |
| 42 | logic [${f.get_n_bits()-1}:0] q; |
| 43 | % if f.hwqe: |
| 44 | logic qe; |
| 45 | % endif |
| 46 | % if f.hwre: |
| 47 | logic re; |
| 48 | % endif |
| 49 | } ${f.get_basename()}; |
| 50 | %endfor |
| 51 | } ${block.name + "_reg2hw_" + r.name + "_mreg_t"}; |
| 52 | %endif |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 53 | % endfor |
| 54 | |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 55 | % for r in block.regs: |
| 56 | ## in this case we have a homogeneous multireg, with only one replicated field |
| 57 | % if r.is_multi_reg() and r.get_n_bits(["d"]) and r.ishomog: |
| 58 | typedef struct packed { |
| 59 | logic [${r.get_field_flat(0).get_n_bits(["d"])-1}:0] d; |
| 60 | % if not r.get_reg_flat(0).hwext: |
| 61 | logic de; |
| 62 | % endif |
| 63 | } ${block.name + "_hw2reg_" + r.name + "_mreg_t"}; |
| 64 | ## in this case we have an inhomogeneous multireg, with several different fields per register |
| 65 | % elif r.is_multi_reg() and r.get_n_bits(["d"]) and not r.ishomog: |
| 66 | typedef struct packed { |
| 67 | % for f in r.get_reg_flat(0).fields: |
| 68 | struct packed { |
| 69 | logic [${f.get_n_bits(["d"])-1}:0] d; |
| 70 | % if not r.hwext: |
| 71 | logic de; |
| 72 | % endif |
| 73 | } ${f.get_basename()}; |
| 74 | %endfor |
| 75 | } ${block.name + "_hw2reg_" + r.name + "_mreg_t"}; |
| 76 | % endif |
| 77 | % endfor |
| 78 | |
| 79 | % endif |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 80 | ///////////////////////////////////////////////////////////////////// |
| 81 | // Register to internal design logic |
| 82 | ///////////////////////////////////////////////////////////////////// |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 83 | <% |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 84 | nbits = block.get_n_bits(["q","qe","re"]) - 1 |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 85 | packbit = 0 |
| 86 | %> |
Michael Schaffner | 9a92bea | 2019-09-30 18:13:14 -0700 | [diff] [blame^] | 87 | % if nbits > 0: |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 88 | typedef struct packed { |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 89 | % for r in block.regs: |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 90 | ######################## multiregister ########################### |
| 91 | % if r.is_multi_reg() and r.get_n_bits(["q"]): |
| 92 | <% |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 93 | array_dims = "" |
Michael Schaffner | f9fe005 | 2019-09-27 12:05:58 -0700 | [diff] [blame] | 94 | for d in r.get_nested_dims(): |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 95 | array_dims += "[%d:0]" % (d-1) |
| 96 | %>${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"]) %> |
| 97 | ######################## register with single field ########################### |
| 98 | % elif len(r.fields) == 1 and r.get_n_bits(["q"]): |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 99 | ## Only one field, should use register name as it is |
| 100 | struct packed { |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 101 | 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() %> |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 102 | % if r.fields[0].hwqe: |
| 103 | logic qe; // [${nbits - packbit}]<% packbit += 1 %> |
| 104 | % endif |
| 105 | % if r.fields[0].hwre: |
| 106 | logic re; // [${nbits - packbit}]<% packbit += 1 %> |
| 107 | % endif |
| 108 | } ${r.name}; |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 109 | ######################## register with multiple fields ########################### |
| 110 | % elif len(r.fields) >= 2 and r.get_n_bits(["q"]): |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 111 | struct packed { |
| 112 | % for f in r.fields: |
| 113 | % if f.hwaccess in [HwAccess.HRW, HwAccess.HRO]: |
| 114 | struct packed { |
| 115 | ## reg2hw signal based on HW type and virtual? |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 116 | % if f.get_n_bits() > 1: |
| 117 | logic [${f.get_n_bits()-1}:0] q; // [${nbits - packbit}:${nbits - (packbit + f.get_n_bits() - 1)}]<% packbit += f.get_n_bits() %> |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 118 | % else: |
| 119 | logic q; // [${nbits - packbit}]<% packbit += 1 %> |
| 120 | % endif |
| 121 | % if f.hwqe: |
| 122 | logic qe; // [${nbits - packbit}]<% packbit += 1 %> |
| 123 | % endif |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 124 | % if f.hwre: |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 125 | logic re; // [${nbits - packbit}]<% packbit += 1 %> |
| 126 | % endif |
| 127 | } ${f.name}; |
| 128 | % endif |
| 129 | % endfor |
| 130 | } ${r.name}; |
| 131 | % endif |
| 132 | % endfor |
| 133 | } ${block.name}_reg2hw_t; |
Michael Schaffner | 9a92bea | 2019-09-30 18:13:14 -0700 | [diff] [blame^] | 134 | % endif |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 135 | |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 136 | ///////////////////////////////////////////////////////////////////// |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 137 | // Internal design logic to register |
| 138 | ///////////////////////////////////////////////////////////////////// |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 139 | <% |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 140 | nbits = block.get_n_bits(["d","de"]) - 1 |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 141 | packbit = 0 |
| 142 | %> |
Michael Schaffner | 9a92bea | 2019-09-30 18:13:14 -0700 | [diff] [blame^] | 143 | % if nbits > 0: |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 144 | typedef struct packed { |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 145 | % for r in block.regs: |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 146 | ######################## multiregister ########################### |
| 147 | % if r.is_multi_reg() and r.get_n_bits(["d"]): |
| 148 | <% |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 149 | array_dims = "" |
Michael Schaffner | f9fe005 | 2019-09-27 12:05:58 -0700 | [diff] [blame] | 150 | for d in r.get_nested_dims(): |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 151 | array_dims += "[%d:0]" % (d-1) |
| 152 | %>${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"]) %> |
| 153 | ######################## register with single field ########################### |
| 154 | % elif len(r.fields) == 1 and r.get_n_bits(["d"]): |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 155 | ## Only one field, should use register name as it is |
| 156 | struct packed { |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 157 | 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") %> |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 158 | % if r.hwext == 0: |
| 159 | logic de; // [${nbits - packbit}]<% packbit += 1 %> |
| 160 | % endif |
| 161 | } ${r.name}; |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 162 | ######################## register with multiple fields ########################### |
| 163 | % elif len(r.fields) >= 2 and r.get_n_bits(["d"]): |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 164 | struct packed { |
| 165 | % for f in r.fields: |
| 166 | % if f.hwaccess in [HwAccess.HRW, HwAccess.HWO]: |
| 167 | struct packed { |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 168 | ## reg2hw signal based on HW type and virtual? |
| 169 | % if f.get_n_bits("d") > 1: |
| 170 | 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") %> |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 171 | % else: |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 172 | logic d; // [${nbits - packbit}]<% packbit += 1 %> |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 173 | % endif |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 174 | % if not r.hwext: |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 175 | logic de; // [${nbits - packbit}]<% packbit += 1 %> |
| 176 | % endif |
| 177 | } ${f.name}; |
| 178 | % endif |
| 179 | % endfor |
| 180 | } ${r.name}; |
| 181 | % endif |
| 182 | % endfor |
| 183 | } ${block.name}_hw2reg_t; |
Michael Schaffner | 9a92bea | 2019-09-30 18:13:14 -0700 | [diff] [blame^] | 184 | % endif |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 185 | |
| 186 | // Register Address |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 187 | % for r in block.get_regs_flat(): |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 188 | parameter ${block.name.upper()}_${r.name.upper()}_OFFSET = ${block.addr_width}'h ${"%x" % r.offset}; |
| 189 | % endfor |
| 190 | |
| 191 | % if len(block.wins) > 0: |
| 192 | // Window parameter |
| 193 | % endif |
| 194 | % for i,w in enumerate(block.wins): |
| 195 | parameter ${block.name.upper()}_${w.name.upper()}_OFFSET = ${block.addr_width}'h ${"%x" % w.base_addr}; |
| 196 | parameter ${block.name.upper()}_${w.name.upper()}_SIZE = ${block.addr_width}'h ${"%x" % (w.limit_addr - w.base_addr)}; |
| 197 | % endfor |
| 198 | |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 199 | // Register Index |
| 200 | typedef enum int { |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 201 | % for r in block.get_regs_flat(): |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 202 | ${block.name.upper()}_${r.name.upper()}${"" if loop.last else ","} |
| 203 | % endfor |
| 204 | } ${block.name}_id_e; |
| 205 | |
| 206 | // Register width information to check illegal writes |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 207 | localparam logic [3:0] ${block.name.upper()}_PERMIT [${block.get_n_regs_flat()}] = '{ |
| 208 | % for i,r in enumerate(block.get_regs_flat()): |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 209 | <% index_str = "{}".format(i).rjust(max_regs_char) %>\ |
| 210 | % if r.width > 16: |
Eunchan Kim | bc5d514 | 2019-09-19 14:54:06 -0700 | [diff] [blame] | 211 | 4'b 1111${" " if i == num_regs-1 else ","} // index[${index_str}] ${block.name.upper()}_${r.name.upper()} |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 212 | % elif r.width > 8: |
Eunchan Kim | bc5d514 | 2019-09-19 14:54:06 -0700 | [diff] [blame] | 213 | 4'b 0011${" " if i == num_regs-1 else ","} // index[${index_str}] ${block.name.upper()}_${r.name.upper()} |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 214 | % else: |
Eunchan Kim | bc5d514 | 2019-09-19 14:54:06 -0700 | [diff] [blame] | 215 | 4'b 0001${" " if i == num_regs-1 else ","} // index[${index_str}] ${block.name.upper()}_${r.name.upper()} |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 216 | % endif |
| 217 | % endfor |
| 218 | }; |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 219 | endpackage |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 220 | |