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 | <% |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 8 | from topgen import lib # TODO: Split lib to common lib module |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 9 | num_regs = block.get_n_regs_flat() |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 10 | max_regs_char = len("{}".format(num_regs-1)) |
| 11 | %>\ |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 12 | package ${block.name}_reg_pkg; |
Eunchan Kim | c4873f3 | 2019-09-25 12:46:12 -0700 | [diff] [blame] | 13 | % if len(block.params) != 0: |
| 14 | |
| 15 | // Param list |
| 16 | % endif |
Eunchan Kim | b993190 | 2019-09-26 14:16:40 -0700 | [diff] [blame] | 17 | % for param in [p for p in block.params if p["local"] == "true"]: |
Michael Schaffner | 1b5fa9f | 2020-01-17 17:43:42 -0800 | [diff] [blame] | 18 | parameter ${param["type"]} ${param["name"]} = ${param["default"]}; |
Eunchan Kim | c4873f3 | 2019-09-25 12:46:12 -0700 | [diff] [blame] | 19 | % endfor |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 20 | |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 21 | //////////////////////////// |
| 22 | // Typedefs for registers // |
| 23 | //////////////////////////// |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 24 | % for r in block.regs: |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 25 | ## in this case we have a homogeneous multireg, with only one replicated field |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 26 | % if r.get_n_bits(["q"]) and r.ishomog: |
| 27 | typedef struct packed { |
| 28 | logic ${lib.bitarray(r.get_field_flat(0).get_n_bits(["q"]),2)} q; |
| 29 | % if r.get_field_flat(0).hwqe: |
| 30 | logic qe; |
| 31 | % endif |
Pirmin Vogel | ab9d1ca | 2020-05-25 14:52:55 +0200 | [diff] [blame^] | 32 | % if r.get_field_flat(0).hwre or (r.get_field_flat(0).shadowed and r.get_field_flat(0).hwext): |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 33 | logic re; |
| 34 | % endif |
Pirmin Vogel | ab9d1ca | 2020-05-25 14:52:55 +0200 | [diff] [blame^] | 35 | % if r.get_field_flat(0).shadowed and not r.get_field_flat(0).hwext: |
| 36 | logic err_update; |
| 37 | logic err_storage; |
| 38 | % endif |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 39 | } ${block.name + "_reg2hw_" + r.name + ("_mreg_t" if r.is_multi_reg() else "_reg_t")}; |
| 40 | |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 41 | ## in this case we have an inhomogeneous multireg, with several different fields per register |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 42 | % elif r.get_n_bits(["q"]) and not r.ishomog: |
| 43 | typedef struct packed { |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 44 | % for f in r.get_reg_flat(0).fields: |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 45 | % if f.get_n_bits(["q"]) >= 1: |
| 46 | struct packed { |
| 47 | logic ${lib.bitarray(f.get_n_bits(["q"]),2)} q; |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 48 | % if f.hwqe: |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 49 | logic qe; |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 50 | % endif |
Pirmin Vogel | ab9d1ca | 2020-05-25 14:52:55 +0200 | [diff] [blame^] | 51 | % if f.hwre or (f.shadowed and f.hwext): |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 52 | logic re; |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 53 | % endif |
Pirmin Vogel | ab9d1ca | 2020-05-25 14:52:55 +0200 | [diff] [blame^] | 54 | % if f.shadowed and not f.hwext: |
| 55 | logic err_update; |
| 56 | logic err_storage; |
| 57 | % endif |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 58 | } ${f.get_basename() if r.is_multi_reg() else f.name}; |
| 59 | %endif |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 60 | %endfor |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 61 | } ${block.name + "_reg2hw_" + r.name + ("_mreg_t" if r.is_multi_reg() else "_reg_t")}; |
| 62 | |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 63 | %endif |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 64 | % endfor |
| 65 | |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 66 | % for r in block.regs: |
| 67 | ## in this case we have a homogeneous multireg, with only one replicated field |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 68 | % if r.get_n_bits(["d"]) and r.ishomog: |
| 69 | typedef struct packed { |
| 70 | logic ${lib.bitarray(r.get_field_flat(0).get_n_bits(["d"]),2)} d; |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 71 | % if not r.get_reg_flat(0).hwext: |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 72 | logic de; |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 73 | % endif |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 74 | } ${block.name + "_hw2reg_" + r.name + ("_mreg_t" if r.is_multi_reg() else "_reg_t")}; |
| 75 | |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 76 | ## in this case we have an inhomogeneous multireg, with several different fields per register |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 77 | % elif r.get_n_bits(["d"]) and not r.ishomog: |
| 78 | typedef struct packed { |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 79 | % for f in r.get_reg_flat(0).fields: |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 80 | % if f.get_n_bits(["d"]) >= 1: |
| 81 | struct packed { |
| 82 | logic ${lib.bitarray(f.get_n_bits(["d"]),2)} d; |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 83 | % if not r.hwext: |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 84 | logic de; |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 85 | % endif |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 86 | } ${f.get_basename() if r.is_multi_reg() else f.name}; |
| 87 | %endif |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 88 | %endfor |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 89 | } ${block.name + "_hw2reg_" + r.name + ("_mreg_t" if r.is_multi_reg() else "_reg_t")}; |
| 90 | |
Michael Schaffner | a2c51d9 | 2019-09-27 16:38:24 -0700 | [diff] [blame] | 91 | % endif |
| 92 | % endfor |
| 93 | |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 94 | /////////////////////////////////////// |
| 95 | // Register to internal design logic // |
| 96 | /////////////////////////////////////// |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 97 | <% |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 98 | nbits = block.get_n_bits(["q","qe","re"]) - 1 |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 99 | packbit = 0 |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 100 | %>\ |
Michael Schaffner | 9a92bea | 2019-09-30 18:13:14 -0700 | [diff] [blame] | 101 | % if nbits > 0: |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 102 | typedef struct packed { |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 103 | % for r in block.regs: |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 104 | ######################## multiregister ########################### |
| 105 | % if r.is_multi_reg() and r.get_n_bits(["q"]): |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 106 | <% |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 107 | array_dims = "" |
Michael Schaffner | f9fe005 | 2019-09-27 12:05:58 -0700 | [diff] [blame] | 108 | for d in r.get_nested_dims(): |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 109 | array_dims += "[%d:0]" % (d-1) |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 110 | %>\ |
| 111 | ${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"]) %>\ |
| 112 | |
| 113 | ######################## register ########################### |
| 114 | % elif r.get_n_bits(["q"]): |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 115 | ## Only one field, should use register name as it is |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 116 | ${block.name + "_reg2hw_" + r.name + "_reg_t"} ${r.name}; // [${nbits - packbit}:${nbits - (packbit + r.get_n_bits(["q", "qe", "re"]) - 1)}]<% packbit += r.get_n_bits(["q", "qe", "re"]) %>\ |
| 117 | |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 118 | % endif |
| 119 | % endfor |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 120 | } ${block.name}_reg2hw_t; |
Michael Schaffner | 9a92bea | 2019-09-30 18:13:14 -0700 | [diff] [blame] | 121 | % endif |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 122 | |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 123 | /////////////////////////////////////// |
| 124 | // Internal design logic to register // |
| 125 | /////////////////////////////////////// |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 126 | <% |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 127 | nbits = block.get_n_bits(["d","de"]) - 1 |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 128 | packbit = 0 |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 129 | %>\ |
Michael Schaffner | 9a92bea | 2019-09-30 18:13:14 -0700 | [diff] [blame] | 130 | % if nbits > 0: |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 131 | typedef struct packed { |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 132 | % for r in block.regs: |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 133 | ######################## multiregister ########################### |
| 134 | % if r.is_multi_reg() and r.get_n_bits(["d"]): |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 135 | <% |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 136 | array_dims = "" |
Michael Schaffner | f9fe005 | 2019-09-27 12:05:58 -0700 | [diff] [blame] | 137 | for d in r.get_nested_dims(): |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 138 | array_dims += "[%d:0]" % (d-1) |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 139 | %>\ |
| 140 | ${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"]) %>\ |
| 141 | |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 142 | ######################## register with single field ########################### |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 143 | % elif r.get_n_bits(["d"]): |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 144 | ## Only one field, should use register name as it is |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 145 | ${block.name + "_hw2reg_" + r.name + "_reg_t"} ${r.name}; // [${nbits - packbit}:${nbits - (packbit + r.get_n_bits(["q", "qe", "re"]) - 1)}]<% packbit += r.get_n_bits(["q", "qe", "re"]) %>\ |
| 146 | |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 147 | % endif |
| 148 | % endfor |
Eunchan Kim | 668ea2e | 2019-11-12 15:44:08 -0800 | [diff] [blame] | 149 | } ${block.name}_hw2reg_t; |
Michael Schaffner | 9a92bea | 2019-09-30 18:13:14 -0700 | [diff] [blame] | 150 | % endif |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 151 | |
| 152 | // Register Address |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 153 | % for r in block.get_regs_flat(): |
Michael Schaffner | 1b5fa9f | 2020-01-17 17:43:42 -0800 | [diff] [blame] | 154 | parameter logic [${block.addr_width-1}:0] ${block.name.upper()}_${r.name.upper()}_OFFSET = ${block.addr_width}'h ${"%x" % r.offset}; |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 155 | % endfor |
| 156 | |
| 157 | % if len(block.wins) > 0: |
| 158 | // Window parameter |
| 159 | % endif |
| 160 | % for i,w in enumerate(block.wins): |
Michael Schaffner | 1b5fa9f | 2020-01-17 17:43:42 -0800 | [diff] [blame] | 161 | parameter logic [${block.addr_width-1}:0] ${block.name.upper()}_${w.name.upper()}_OFFSET = ${block.addr_width}'h ${"%x" % w.base_addr}; |
| 162 | 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)}; |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 163 | % endfor |
| 164 | |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 165 | // Register Index |
| 166 | typedef enum int { |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 167 | % for r in block.get_regs_flat(): |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 168 | ${block.name.upper()}_${r.name.upper()}${"" if loop.last else ","} |
| 169 | % endfor |
| 170 | } ${block.name}_id_e; |
| 171 | |
| 172 | // Register width information to check illegal writes |
Michael Schaffner | 1b5fa9f | 2020-01-17 17:43:42 -0800 | [diff] [blame] | 173 | parameter logic [3:0] ${block.name.upper()}_PERMIT [${block.get_n_regs_flat()}] = '{ |
Michael Schaffner | 9a94b6c | 2019-09-25 16:17:35 -0700 | [diff] [blame] | 174 | % for i,r in enumerate(block.get_regs_flat()): |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 175 | <% index_str = "{}".format(i).rjust(max_regs_char) %>\ |
Eunchan Kim | 534fb24 | 2019-10-08 12:05:35 -0700 | [diff] [blame] | 176 | % if r.width > 24: |
Eunchan Kim | bc5d514 | 2019-09-19 14:54:06 -0700 | [diff] [blame] | 177 | 4'b 1111${" " if i == num_regs-1 else ","} // index[${index_str}] ${block.name.upper()}_${r.name.upper()} |
Eunchan Kim | 534fb24 | 2019-10-08 12:05:35 -0700 | [diff] [blame] | 178 | % elif r.width > 16: |
| 179 | 4'b 0111${" " 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] | 180 | % elif r.width > 8: |
Eunchan Kim | bc5d514 | 2019-09-19 14:54:06 -0700 | [diff] [blame] | 181 | 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] | 182 | % else: |
Eunchan Kim | bc5d514 | 2019-09-19 14:54:06 -0700 | [diff] [blame] | 183 | 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] | 184 | % endif |
| 185 | % endfor |
| 186 | }; |
lowRISC Contributors | 802543a | 2019-08-31 12:12:56 +0100 | [diff] [blame] | 187 | endpackage |
Eunchan Kim | 51461cd | 2019-09-18 14:00:49 -0700 | [diff] [blame] | 188 | |