blob: 1c5520a53e92e7645d2a008ed9b085577993ad1a [file] [log] [blame]
lowRISC Contributors802543a2019-08-31 12:12:56 +01001// 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
Eunchan Kim51461cd2019-09-18 14:00:49 -07006<%
Eunchan Kim668ea2e2019-11-12 15:44:08 -08007 from topgen import lib # TODO: Split lib to common lib module
Rupert Swarbrick200d8b42021-03-08 12:32:11 +00008
9 from reggen.access import HwAccess, SwRdAccess, SwWrAccess
Rupert Swarbrick4d645362021-02-08 17:17:05 +000010 from reggen.register import Register
11 from reggen.multi_register import MultiRegister
Rupert Swarbrickede94802021-02-08 09:16:50 +000012
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000013 from reggen import gen_rtl
14
Rupert Swarbrick611a6422021-02-12 11:56:48 +000015 localparams = block.params.get_localparams()
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000016
17 addr_widths = gen_rtl.get_addr_widths(block)
Rupert Swarbrick269bb3d2021-02-23 15:41:56 +000018
19 lblock = block.name.lower()
20 ublock = lblock.upper()
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000021
22 def reg_pfx(reg):
23 return '{}_{}'.format(ublock, reg.name.upper())
24
25 def reg_resname(reg):
26 return '{}_RESVAL'.format(reg_pfx(reg))
27
28 def field_resname(reg, field):
29 return '{}_{}_RESVAL'.format(reg_pfx(reg), field.name.upper())
30
Eunchan Kim51461cd2019-09-18 14:00:49 -070031%>\
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000032<%def name="typedefs_for_iface(iface_name, iface_desc, for_iface, rb)">\
Rupert Swarbrick4d645362021-02-08 17:17:05 +000033<%
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000034 hdr = gen_rtl.make_box_quote('Typedefs for registers' + for_iface)
Rupert Swarbrick4d645362021-02-08 17:17:05 +000035%>\
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000036% for r in rb.all_regs:
37 % if r.get_n_bits(["q"]):
38 % if hdr:
39
40${hdr}
41 % endif
42<%
43 r0 = gen_rtl.get_r0(r)
44 hdr = None
45%>\
46
Eunchan Kim668ea2e2019-11-12 15:44:08 -080047 typedef struct packed {
Rupert Swarbrick4d645362021-02-08 17:17:05 +000048 % if r.is_homogeneous():
49 ## If we have a homogeneous register or multireg, there is just one field
50 ## (possibly replicated many times). The typedef is for one copy of that
51 ## field.
52<%
53 field = r.get_field_list()[0]
54 field_q_width = field.get_n_bits(r0.hwext, ['q'])
55 field_q_bits = lib.bitarray(field_q_width, 2)
56%>\
57 logic ${field_q_bits} q;
58 % if field.hwqe:
Eunchan Kim668ea2e2019-11-12 15:44:08 -080059 logic qe;
Rupert Swarbrick4d645362021-02-08 17:17:05 +000060 % endif
61 % if field.hwre or (r0.shadowed and r0.hwext):
Eunchan Kim668ea2e2019-11-12 15:44:08 -080062 logic re;
Rupert Swarbrick4d645362021-02-08 17:17:05 +000063 % endif
64 % if r0.shadowed and not r0.hwext:
Pirmin Vogelab9d1ca2020-05-25 14:52:55 +020065 logic err_update;
66 logic err_storage;
Rupert Swarbrick4d645362021-02-08 17:17:05 +000067 % endif
68 % else:
69 ## We are inhomogeneous, which means there is more than one different
70 ## field. Generate a reg2hw typedef that packs together all the fields of
71 ## the register.
72 % for f in r0.fields:
73 % if f.get_n_bits(r0.hwext, ["q"]) >= 1:
74<%
75 field_q_width = f.get_n_bits(r0.hwext, ['q'])
76 field_q_bits = lib.bitarray(field_q_width, 2)
Eunchan Kim668ea2e2019-11-12 15:44:08 -080077
Rupert Swarbrick4d645362021-02-08 17:17:05 +000078 struct_name = f.name.lower()
79%>\
Eunchan Kim668ea2e2019-11-12 15:44:08 -080080 struct packed {
Rupert Swarbrick4d645362021-02-08 17:17:05 +000081 logic ${field_q_bits} q;
82 % if f.hwqe:
Eunchan Kim668ea2e2019-11-12 15:44:08 -080083 logic qe;
Rupert Swarbrick4d645362021-02-08 17:17:05 +000084 % endif
85 % if f.hwre or (r0.shadowed and r0.hwext):
Eunchan Kim668ea2e2019-11-12 15:44:08 -080086 logic re;
Rupert Swarbrick4d645362021-02-08 17:17:05 +000087 % endif
88 % if r0.shadowed and not r0.hwext:
Pirmin Vogelab9d1ca2020-05-25 14:52:55 +020089 logic err_update;
90 logic err_storage;
Rupert Swarbrick4d645362021-02-08 17:17:05 +000091 % endif
92 } ${struct_name};
93 %endif
94 %endfor
95 %endif
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000096 } ${gen_rtl.get_reg_tx_type(block, r, False)};
Michael Schaffnera2c51d92019-09-27 16:38:24 -070097 %endif
Michael Schaffner9a94b6c2019-09-25 16:17:35 -070098% endfor
Rupert Swarbrick200d8b42021-03-08 12:32:11 +000099% for r in rb.all_regs:
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000100 % if r.get_n_bits(["d"]):
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000101 % if hdr:
Eunchan Kim668ea2e2019-11-12 15:44:08 -0800102
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000103${hdr}
104 % endif
105<%
106 r0 = gen_rtl.get_r0(r)
107 hdr = None
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000108%>\
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000109
Eunchan Kim668ea2e2019-11-12 15:44:08 -0800110 typedef struct packed {
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000111 % if r.is_homogeneous():
112 ## If we have a homogeneous register or multireg, there is just one field
113 ## (possibly replicated many times). The typedef is for one copy of that
114 ## field.
115<%
116 field = r.get_field_list()[0]
117 field_d_width = field.get_n_bits(r0.hwext, ['d'])
118 field_d_bits = lib.bitarray(field_d_width, 2)
119%>\
120 logic ${field_d_bits} d;
121 % if not r0.hwext:
122 logic de;
Michael Schaffnera2c51d92019-09-27 16:38:24 -0700123 % endif
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000124 % else:
125 ## We are inhomogeneous, which means there is more than one different
126 ## field. Generate a hw2reg typedef that packs together all the fields of
127 ## the register.
128 % for f in r0.fields:
129 % if f.get_n_bits(r0.hwext, ["d"]) >= 1:
130<%
131 field_d_width = f.get_n_bits(r0.hwext, ['d'])
132 field_d_bits = lib.bitarray(field_d_width, 2)
133
134 struct_name = f.name.lower()
135%>\
136 struct packed {
137 logic ${field_d_bits} d;
138 % if not r0.hwext:
139 logic de;
140 % endif
141 } ${struct_name};
142 %endif
143 %endfor
144 %endif
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000145 } ${gen_rtl.get_reg_tx_type(block, r, True)};
Michael Schaffnera2c51d92019-09-27 16:38:24 -0700146 % endif
147% endfor
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000148</%def>\
149<%def name="reg2hw_for_iface(iface_name, iface_desc, for_iface, rb)">\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100150<%
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000151nbits = rb.get_n_bits(["q", "qe", "re"])
lowRISC Contributors802543a2019-08-31 12:12:56 +0100152packbit = 0
Eunchan Kim668ea2e2019-11-12 15:44:08 -0800153%>\
Michael Schaffner9a92bea2019-09-30 18:13:14 -0700154% if nbits > 0:
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000155
156 // Register -> HW type${for_iface}
Eunchan Kim668ea2e2019-11-12 15:44:08 -0800157 typedef struct packed {
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000158% for r in rb.all_regs:
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000159 % if r.get_n_bits(["q"]):
Eunchan Kim668ea2e2019-11-12 15:44:08 -0800160<%
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000161 r0 = gen_rtl.get_r0(r)
162 struct_type = gen_rtl.get_reg_tx_type(block, r, False)
163 struct_width = r0.get_n_bits(['q', 'qe', 're'])
164
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000165 if isinstance(r, MultiRegister):
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000166 struct_type += " [{}:0]".format(r.count - 1)
167 struct_width *= r.count
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000168
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000169 msb = nbits - packbit - 1
170 lsb = msb - struct_width + 1
171 packbit += struct_width
Eunchan Kim668ea2e2019-11-12 15:44:08 -0800172%>\
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000173 ${struct_type} ${r0.name.lower()}; // [${msb}:${lsb}]
lowRISC Contributors802543a2019-08-31 12:12:56 +0100174 % endif
175% endfor
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000176 } ${gen_rtl.get_iface_tx_type(block, iface_name, False)};
Michael Schaffner9a92bea2019-09-30 18:13:14 -0700177% endif
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000178</%def>\
179<%def name="hw2reg_for_iface(iface_name, iface_desc, for_iface, rb)">\
lowRISC Contributors802543a2019-08-31 12:12:56 +0100180<%
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000181nbits = rb.get_n_bits(["d", "de"])
lowRISC Contributors802543a2019-08-31 12:12:56 +0100182packbit = 0
Eunchan Kim668ea2e2019-11-12 15:44:08 -0800183%>\
Michael Schaffner9a92bea2019-09-30 18:13:14 -0700184% if nbits > 0:
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000185
186 // HW -> register type${for_iface}
Eunchan Kim668ea2e2019-11-12 15:44:08 -0800187 typedef struct packed {
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000188% for r in rb.all_regs:
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000189 % if r.get_n_bits(["d"]):
Eunchan Kim668ea2e2019-11-12 15:44:08 -0800190<%
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000191 r0 = gen_rtl.get_r0(r)
192 struct_type = gen_rtl.get_reg_tx_type(block, r, True)
193 struct_width = r0.get_n_bits(['d', 'de'])
194
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000195 if isinstance(r, MultiRegister):
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000196 struct_type += " [{}:0]".format(r.count - 1)
197 struct_width *= r.count
Rupert Swarbrick5e62ebc2020-11-25 11:27:46 +0000198
Rupert Swarbrick5e62ebc2020-11-25 11:27:46 +0000199 msb = nbits - packbit - 1
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000200 lsb = msb - struct_width + 1
201 packbit += struct_width
Eunchan Kim668ea2e2019-11-12 15:44:08 -0800202%>\
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000203 ${struct_type} ${r0.name.lower()}; // [${msb}:${lsb}]
lowRISC Contributors802543a2019-08-31 12:12:56 +0100204 % endif
205% endfor
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000206 } ${gen_rtl.get_iface_tx_type(block, iface_name, True)};
207% endif
208</%def>\
209<%def name="offsets_for_iface(iface_name, iface_desc, for_iface, rb)">\
210% if not rb.flat_regs:
211<% return STOP_RENDERING %>
Michael Schaffner9a92bea2019-09-30 18:13:14 -0700212% endif
lowRISC Contributors802543a2019-08-31 12:12:56 +0100213
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000214 // Register offsets${for_iface}
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000215<%
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000216aw_name, aw = addr_widths[iface_name]
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000217%>\
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000218% for r in rb.flat_regs:
Rupert Swarbrickc5841b72021-02-15 08:25:02 +0000219<%
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000220value = "{}'h {:x}".format(aw, r.offset)
221%>\
222 parameter logic [${aw_name}-1:0] ${reg_pfx(r)}_OFFSET = ${value};
223% endfor
224</%def>\
225<%def name="hwext_resvals_for_iface(iface_name, iface_desc, for_iface, rb)">\
226<%
227 hwext_regs = [r for r in rb.flat_regs if r.hwext]
Rupert Swarbrickc5841b72021-02-15 08:25:02 +0000228%>\
229% if hwext_regs:
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000230
231 // Reset values for hwext registers and their fields${for_iface}
Rupert Swarbrickc5841b72021-02-15 08:25:02 +0000232 % for reg in hwext_regs:
233<%
234 reg_width = reg.get_width()
235 reg_msb = reg_width - 1
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000236 reg_resval = "{}'h {:x}".format(reg_width, reg.resval)
Rupert Swarbrickc5841b72021-02-15 08:25:02 +0000237%>\
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000238 parameter logic [${reg_msb}:0] ${reg_resname(reg)} = ${reg_resval};
Rupert Swarbrick66e40932021-02-16 13:11:27 +0000239 % for field in reg.fields:
240 % if field.resval is not None:
241<%
242 field_width = field.bits.width()
243 field_msb = field_width - 1
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000244 field_resval = "{}'h {:x}".format(field_width, field.resval)
Rupert Swarbrick66e40932021-02-16 13:11:27 +0000245%>\
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000246 parameter logic [${field_msb}:0] ${field_resname(reg, field)} = ${field_resval};
Rupert Swarbrick66e40932021-02-16 13:11:27 +0000247 % endif
248 % endfor
Rupert Swarbrickc5841b72021-02-15 08:25:02 +0000249 % endfor
Rupert Swarbrickc5841b72021-02-15 08:25:02 +0000250% endif
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000251</%def>\
252<%def name="windows_for_iface(iface_name, iface_desc, for_iface, rb)">\
253% if rb.windows:
254<%
255 aw_name, aw = addr_widths[iface_name]
256%>\
257
258 // Window parameters${for_iface}
259% for i,w in enumerate(rb.windows):
Rupert Swarbrickbc2bc582021-02-09 13:30:37 +0000260<%
261 win_pfx = '{}_{}'.format(ublock, w.name.upper())
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000262 base_txt_val = "{}'h {:x}".format(aw, w.offset)
Rupert Swarbrickcfcfbce2021-03-09 14:14:30 +0000263 size_txt_val = "'h {:x}".format(w.size_in_bytes)
lowRISC Contributors802543a2019-08-31 12:12:56 +0100264
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000265 offset_type = 'logic [{}-1:0]'.format(aw_name)
266 size_type = 'int unsigned'
267 max_type_len = max(len(offset_type), len(size_type))
268
269 offset_type += ' ' * (max_type_len - len(offset_type))
270 size_type += ' ' * (max_type_len - len(size_type))
271
272%>\
273 parameter ${offset_type} ${win_pfx}_OFFSET = ${base_txt_val};
274 parameter ${size_type} ${win_pfx}_SIZE = ${size_txt_val};
275% endfor
Rupert Swarbrickc5841b72021-02-15 08:25:02 +0000276% endif
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000277</%def>\
278<%def name="reg_data_for_iface(iface_name, iface_desc, for_iface, rb)">\
279% if rb.flat_regs:
280<%
281 lpfx = gen_rtl.get_type_name_pfx(block, iface_name)
282 upfx = lpfx.upper()
283 idx_len = len("{}".format(len(rb.flat_regs) - 1))
284%>\
285
286 // Register index${for_iface}
Eunchan Kim51461cd2019-09-18 14:00:49 -0700287 typedef enum int {
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000288% for r in rb.flat_regs:
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000289 ${ublock}_${r.name.upper()}${"" if loop.last else ","}
Eunchan Kim51461cd2019-09-18 14:00:49 -0700290% endfor
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000291 } ${lpfx}_id_e;
Eunchan Kim51461cd2019-09-18 14:00:49 -0700292
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000293 // Register width information to check illegal writes${for_iface}
294 parameter logic [3:0] ${upfx}_PERMIT [${len(rb.flat_regs)}] = '{
295 % for i, r in enumerate(rb.flat_regs):
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000296<%
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000297 index_str = "{}".format(i).rjust(idx_len)
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000298 width = r.get_width()
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000299 if width > 24:
300 mask = '1111'
301 elif width > 16:
302 mask = '0111'
303 elif width > 8:
304 mask = '0011'
305 else:
306 mask = '0001'
307
308 comma = ',' if i < len(rb.flat_regs) - 1 else ' '
Rupert Swarbrick4d645362021-02-08 17:17:05 +0000309%>\
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000310 4'b ${mask}${comma} // index[${index_str}] ${ublock}_${r.name.upper()}
311 % endfor
Eunchan Kim51461cd2019-09-18 14:00:49 -0700312 };
Rupert Swarbrick200d8b42021-03-08 12:32:11 +0000313% endif
314</%def>\
315
316package ${lblock}_reg_pkg;
317% if localparams:
318
319 // Param list
320% for param in localparams:
321 parameter ${param.param_type} ${param.name} = ${param.value};
322% endfor
323% endif
324
325 // Address widths within the block
326% for param_name, width in addr_widths.values():
327 parameter int ${param_name} = ${width};
328% endfor
329<%
330 just_default = len(block.reg_blocks) == 1 and None in block.reg_blocks
331%>\
332% for iface_name, rb in block.reg_blocks.items():
333<%
334 iface_desc = iface_name or 'default'
335 for_iface = '' if just_default else ' for {} interface'.format(iface_desc)
336%>\
337${typedefs_for_iface(iface_name, iface_desc, for_iface, rb)}\
338${reg2hw_for_iface(iface_name, iface_desc, for_iface, rb)}\
339${hw2reg_for_iface(iface_name, iface_desc, for_iface, rb)}\
340${offsets_for_iface(iface_name, iface_desc, for_iface, rb)}\
341${hwext_resvals_for_iface(iface_name, iface_desc, for_iface, rb)}\
342${windows_for_iface(iface_name, iface_desc, for_iface, rb)}\
343${reg_data_for_iface(iface_name, iface_desc, for_iface, rb)}\
344% endfor
345
lowRISC Contributors802543a2019-08-31 12:12:56 +0100346endpackage
Eunchan Kim51461cd2019-09-18 14:00:49 -0700347