blob: 72cc3083903db4ea4c66b8027d0ad584c3e317f3 [file] [log] [blame]
Rupert Swarbrick25468b42021-03-11 15:20:10 +00001// 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 from reggen import gen_dv
6 from reggen.access import HwAccess, SwRdAccess, SwWrAccess
Weicai Yang00f6d782021-06-29 17:42:43 -07007 from reggen.multi_register import MultiRegister
8 from reggen.register import Register
Weicai Yangf69b7002021-07-12 17:06:49 -07009 from typing import Dict
10
11 # Get a list reg and its instance name
12 # For single reg, return Dict[reg_inst:reg]
13 # For multireg, if it's dv_compact, return Dict[mr.name[idx]:mr.reg],
14 # if not, return all the mr.regs with their name
15 def get_inst_to_reg_dict(r) -> Dict:
16 inst_regs = {} # type: Dict[inst_name:Register]
17 if isinstance(r, MultiRegister):
18 if r.dv_compact:
19 inst_base = r.reg.name.lower()
20 for idx, reg in enumerate(r.regs):
Weicai Yangb1466592021-08-20 16:08:37 -070021 inst_name = f'{inst_base}[{idx}]'
Weicai Yangf69b7002021-07-12 17:06:49 -070022 inst_regs[inst_name] = reg
23 else:
24 for r0 in r.regs:
25 inst_regs[r0.name] = r0
26 else:
27 inst_regs[r.name.lower()] = r
28 return inst_regs
29%>\
Rupert Swarbrick25468b42021-03-11 15:20:10 +000030##
31##
32## make_ral_pkg
33## ============
34##
35## Generate the RAL package for a device interface.
36##
37## dv_base_prefix a string naming the base register type. If it is FOO,
38## then we will inherit from FOO_reg (assumed to
39## be a subclass of uvm_reg).
40##
41## reg_width an integer giving the width of registers in bits
42##
Rupert Swarbrickbe212852021-03-30 08:43:11 +010043## reg_block_path the hierarchical path to the relevant register block in the
44## design
Rupert Swarbrick25468b42021-03-11 15:20:10 +000045##
46## rb a RegBlock object
47##
48## esc_if_name a string giving the full, escaped, interface name. For
49## a device interface called FOO on block BAR,
50## this will be bar__foo. For an unnamed interface
51## on block BAR, this will be just bar.
52##
Rupert Swarbrickbe212852021-03-30 08:43:11 +010053<%def name="make_ral_pkg(dv_base_prefix, reg_width, reg_block_path, rb, esc_if_name)">\
Rupert Swarbrick25468b42021-03-11 15:20:10 +000054package ${esc_if_name}_ral_pkg;
55${make_ral_pkg_hdr(dv_base_prefix, [])}
56
Weicai Yang00f6d782021-06-29 17:42:43 -070057${make_ral_pkg_fwd_decls(esc_if_name, rb.type_regs, rb.windows)}
58% for r in rb.all_regs:
59<%
Weicai Yang57dc8dc2021-07-22 18:10:14 -070060 mr = None
Weicai Yangf69b7002021-07-12 17:06:49 -070061 if isinstance(r, MultiRegister):
Weicai Yang57dc8dc2021-07-22 18:10:14 -070062 mr = r
Weicai Yangf69b7002021-07-12 17:06:49 -070063 if r.dv_compact:
Weicai Yang57dc8dc2021-07-22 18:10:14 -070064 regs = [r.reg]
Weicai Yangf69b7002021-07-12 17:06:49 -070065 else:
66 regs = r.regs
67 else:
68 regs = [r]
Weicai Yang00f6d782021-06-29 17:42:43 -070069%>\
Weicai Yang57dc8dc2021-07-22 18:10:14 -070070 % for idx, reg in enumerate(regs):
Rupert Swarbrick25468b42021-03-11 15:20:10 +000071
Weicai Yang57dc8dc2021-07-22 18:10:14 -070072${make_ral_pkg_reg_class(dv_base_prefix, reg_width, esc_if_name, reg_block_path, reg, mr, idx)}
Weicai Yangf69b7002021-07-12 17:06:49 -070073 % endfor
Rupert Swarbrick25468b42021-03-11 15:20:10 +000074% endfor
75% for window in rb.windows:
76
77${make_ral_pkg_window_class(dv_base_prefix, esc_if_name, window)}
78% endfor
79
80<%
81 reg_block_name = gen_dv.bcname(esc_if_name)
82%>\
83 class ${reg_block_name} extends ${dv_base_prefix}_reg_block;
84% if rb.flat_regs:
85 // registers
Weicai Yang00f6d782021-06-29 17:42:43 -070086 % for r in rb.all_regs:
87<%
Weicai Yangb1466592021-08-20 16:08:37 -070088 # If it's dv_compact, then create it as an array even when it only contains one item
89 count = 0
Weicai Yangf69b7002021-07-12 17:06:49 -070090 if isinstance(r, MultiRegister):
91 if r.dv_compact:
92 regs = [r.reg]
93 count = len(r.regs)
94 else:
95 regs = r.regs
Weicai Yangf69b7002021-07-12 17:06:49 -070096 else:
97 regs = [r]
Weicai Yangf69b7002021-07-12 17:06:49 -070098%>\
99 % for r0 in regs:
100<%
Weicai Yang00f6d782021-06-29 17:42:43 -0700101 reg_type = gen_dv.rcname(esc_if_name, r0)
102 inst_name = r0.name.lower()
Weicai Yangb1466592021-08-20 16:08:37 -0700103 inst_decl = f'{inst_name}[{count}]' if count > 0 else inst_name
Weicai Yang00f6d782021-06-29 17:42:43 -0700104%>\
105 rand ${reg_type} ${inst_decl};
Weicai Yangf69b7002021-07-12 17:06:49 -0700106 % endfor
Weicai Yang00f6d782021-06-29 17:42:43 -0700107 % endfor
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000108% endif
109% if rb.windows:
110 // memories
111% for window in rb.windows:
112 rand ${gen_dv.mcname(esc_if_name, window)} ${gen_dv.miname(window)};
113% endfor
114% endif
115
116 `uvm_object_utils(${reg_block_name})
117
118 function new(string name = "${reg_block_name}",
119 int has_coverage = UVM_NO_COVERAGE);
120 super.new(name, has_coverage);
121 endfunction : new
122
123 virtual function void build(uvm_reg_addr_t base_addr,
124 csr_excl_item csr_excl = null);
125 // create default map
126 this.default_map = create_map(.name("default_map"),
127 .base_addr(base_addr),
128 .n_bytes(${reg_width//8}),
129 .endian(UVM_LITTLE_ENDIAN));
130 if (csr_excl == null) begin
131 csr_excl = csr_excl_item::type_id::create("csr_excl");
132 this.csr_excl = csr_excl;
133 end
134% if rb.flat_regs:
135 set_hdl_path_root("tb.dut", "BkdrRegPathRtl");
136 set_hdl_path_root("tb.dut", "BkdrRegPathRtlCommitted");
137 set_hdl_path_root("tb.dut", "BkdrRegPathRtlShadow");
138 // create registers
Weicai Yang00f6d782021-06-29 17:42:43 -0700139 % for r in rb.all_regs:
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000140<%
Weicai Yang00f6d782021-06-29 17:42:43 -0700141 r0 = r.reg if isinstance(r, MultiRegister) else r
142 reg_type = gen_dv.rcname(esc_if_name, r0)
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000143%>\
Weicai Yang00f6d782021-06-29 17:42:43 -0700144 % if isinstance(r, MultiRegister):
145 % for idx, reg in enumerate(r.regs):
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000146<%
Weicai Yangf69b7002021-07-12 17:06:49 -0700147 if r.dv_compact:
148 inst_base = r0.name.lower()
Weicai Yangb1466592021-08-20 16:08:37 -0700149 inst_name = f'{inst_base}[{idx}]'
Weicai Yangf69b7002021-07-12 17:06:49 -0700150 else:
151 inst_name = reg.name.lower()
152 reg_type = gen_dv.rcname(esc_if_name, reg)
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000153%>\
Weicai Yang00f6d782021-06-29 17:42:43 -0700154${instantiate_register(reg_width, reg_block_path, reg, reg_type, inst_name)}\
155 % endfor
156 % else:
157${instantiate_register(reg_width, reg_block_path, r, reg_type, r.name.lower())}\
158 % endif
159 % endfor
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000160<%
161 any_regwen = False
162 for r in rb.flat_regs:
163 if r.regwen:
164 any_regwen = True
165 break
166%>\
Weicai Yang00f6d782021-06-29 17:42:43 -0700167 % if any_regwen:
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000168 // assign locked reg to its regwen reg
Weicai Yang00f6d782021-06-29 17:42:43 -0700169 % for r in rb.all_regs:
Weicai Yangf69b7002021-07-12 17:06:49 -0700170 % for inst, reg in get_inst_to_reg_dict(r).items():
171${apply_regwen(rb, reg, inst)}\
172 % endfor
Weicai Yang00f6d782021-06-29 17:42:43 -0700173 % endfor
174 % endif
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000175% endif
176${make_ral_pkg_window_instances(reg_width, esc_if_name, rb)}
177 endfunction : build
178 endclass : ${reg_block_name}
179
180endpackage
181</%def>\
182##
183##
184## make_ral_pkg_hdr
185## ================
186##
187## Generate the header for a RAL package
188##
189## dv_base_prefix as for make_ral_pkg
190##
191## deps a list of names for packages that should be explicitly
192## imported
193##
194<%def name="make_ral_pkg_hdr(dv_base_prefix, deps)">\
195 // dep packages
196 import uvm_pkg::*;
197 import dv_base_reg_pkg::*;
198% if dv_base_prefix != "dv_base":
199 import ${dv_base_prefix}_reg_pkg::*;
200% endif
201% for dep in deps:
202 import ${dep}::*;
203% endfor
204
205 // macro includes
206 `include "uvm_macros.svh"\
207</%def>\
208##
209##
210## make_ral_pkg_fwd_decls
211## ======================
212##
213## Generate the forward declarations for a RAL package
214##
215## esc_if_name as for make_ral_pkg
216##
Weicai Yang00f6d782021-06-29 17:42:43 -0700217## type_regs a list of Register objects, one for each type that
218## should be defined. Each MultiRegister will contribute
219## just one register to the list.
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000220##
221## windows a list of Window objects
222##
Weicai Yang00f6d782021-06-29 17:42:43 -0700223<%def name="make_ral_pkg_fwd_decls(esc_if_name, type_regs, windows)">\
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000224 // Forward declare all register/memory/block classes
Weicai Yang00f6d782021-06-29 17:42:43 -0700225% for r in type_regs:
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000226 typedef class ${gen_dv.rcname(esc_if_name, r)};
227% endfor
228% for w in windows:
229 typedef class ${gen_dv.mcname(esc_if_name, w)};
230% endfor
231 typedef class ${gen_dv.bcname(esc_if_name)};\
232</%def>\
233##
234##
235## make_ral_pkg_reg_class
236## ======================
237##
238## Generate the classes for a register inside a RAL package
239##
240## dv_base_prefix as for make_ral_pkg
241##
242## reg_width as for make_ral_pkg
243##
244## esc_if_name as for make_ral_pkg
245##
Rupert Swarbrickbe212852021-03-30 08:43:11 +0100246## reg_block_path as for make_ral_pkg
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000247##
Weicai Yang57dc8dc2021-07-22 18:10:14 -0700248## reg a Register object
249##
250## mr a MultiRegister object if this reg is from a MultiRegister
251##
252## reg_idx the index location of this reg if this reg is from a MultiRegister,
253## or zero if not
254<%def name="make_ral_pkg_reg_class(dv_base_prefix, reg_width, esc_if_name, reg_block_path,
255reg, mr, reg_idx)">\
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000256<%
257 reg_name = reg.name.lower()
258
259 is_ext = reg.hwext
260 for field in reg.fields:
261 if (field.hwaccess.value[1] == HwAccess.NONE and
262 field.swaccess.swrd() == SwRdAccess.RD and
263 not field.swaccess.allows_write()):
264 is_ext = 1
265
266 class_name = gen_dv.rcname(esc_if_name, reg)
267%>\
268 class ${class_name} extends ${dv_base_prefix}_reg;
269 // fields
Weicai Yang57dc8dc2021-07-22 18:10:14 -0700270<%
271 suffix = ""
272 start_idx = 0
273 add_style_waive = False
274 compact_field_inst_name = ""
275 if mr is None:
276 fields = reg.fields
277 else:
278 if not mr.compact:
279 fields = mr.reg.fields
280 else:
281 fields = mr.regs[reg_idx].fields
282 compact_field_inst_name = mr.reg.fields[0].name.lower()
283 if mr.dv_compact:
284 # The dv_compact flag means that the fields of the multi-reg divide equally into registers.
285 # In this case, there's an array of registers and make_ral_pkg_reg_class() gets called once
286 # to define that array's type, using the fields of the first register in the replication.
287 assert reg_idx == 0
288 if len(fields) > 1:
289 suffix = f'[{len(fields)}]'
290 else:
291 # In this case, the multi-register is "compact", so there might be multiple copies of its
292 # single field in each generated register. But dv_compact is false, which probably means
293 # that the fields didn't divide equally into a whole number of registers. In this case, we
294 # are generating a different class for each output register and should spit out fields
295 # accordingly. Note that we generate an array, even if len(fields) = 1. If that happens, we
296 # know we're on the last generated register, so want to keep everything uniform.
297 num_fields_per_reg = 32 // fields[0].bits.width()
298 start_idx = num_fields_per_reg * reg_idx
299 end_idx = start_idx + len(fields) - 1
300 suffix = f'[{start_idx}:{end_idx}]'
301 if start_idx == 0:
302 add_style_waive = True
303%>\
304% if add_style_waive:
305 // verilog_lint: waive unpacked-dimensions-range-ordering
306% endif
307% if compact_field_inst_name:
308 rand ${dv_base_prefix}_reg_field ${compact_field_inst_name}${suffix};
309% else:
310% for f in fields:
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000311 rand ${dv_base_prefix}_reg_field ${f.name.lower()};
Weicai Yang57dc8dc2021-07-22 18:10:14 -0700312% endfor
313% endif
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000314
315 `uvm_object_utils(${class_name})
316
317 function new(string name = "${class_name}",
318 int unsigned n_bits = ${reg_width},
319 int has_coverage = UVM_NO_COVERAGE);
320 super.new(name, n_bits, has_coverage);
321 endfunction : new
322
323 virtual function void build(csr_excl_item csr_excl = null);
324 // create fields
Weicai Yang57dc8dc2021-07-22 18:10:14 -0700325% for idx, field in enumerate(fields):
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000326<%
Weicai Yang57dc8dc2021-07-22 18:10:14 -0700327 if compact_field_inst_name:
328 reg_field_name = compact_field_inst_name
329 if len(fields) > 1:
330 reg_field_name = reg_field_name + f'[{idx + start_idx}]'
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000331 else:
Weicai Yang57dc8dc2021-07-22 18:10:14 -0700332 reg_field_name = field.name.lower()
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000333%>\
Rupert Swarbrickbe212852021-03-30 08:43:11 +0100334${_create_reg_field(dv_base_prefix, reg_width, reg_block_path, reg.shadowed, reg.hwext, reg_field_name, field)}
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000335% endfor
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000336% if is_ext:
337 set_is_ext_reg(1);
338% endif
339 endfunction : build
340 endclass : ${class_name}\
341</%def>\
342##
343##
344## _create_reg_field
345## =================
346##
347## Generate the code that creates a uvm_reg_field object for a field
348## in a register.
349##
350## dv_base_prefix as for make_ral_pkg
351##
352## reg_width as for make_ral_pkg
353##
Rupert Swarbrickbe212852021-03-30 08:43:11 +0100354## reg_block_path as for make_ral_pkg
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000355##
356## shadowed true if the field's register is shadowed
357##
358## hwext true if the field's register is hwext
359##
360## reg_field_name a string with the name to give the field in the HDL
361##
362## field a Field object
Rupert Swarbrickbe212852021-03-30 08:43:11 +0100363<%def name="_create_reg_field(dv_base_prefix, reg_width, reg_block_path, shadowed, hwext, reg_field_name, field)">\
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000364<%
365 field_size = field.bits.width()
Rupert Swarbrick7252f172021-06-17 17:04:20 +0100366 field_access = field.swaccess.dv_rights()
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000367
368 if not field.hwaccess.allows_write():
369 field_volatile = 0
370 else:
371 field_volatile = 1
372 field_tags = field.tags
373
Weicai Yang57dc8dc2021-07-22 18:10:14 -0700374 fname = reg_field_name
Rupert Swarbrick63578162021-04-22 10:53:46 +0100375 type_id_indent = ' ' * (len(fname) + 4)
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000376%>\
Rupert Swarbrick63578162021-04-22 10:53:46 +0100377 ${fname} = (${dv_base_prefix}_reg_field::
Weicai Yang57dc8dc2021-07-22 18:10:14 -0700378 ${type_id_indent}type_id::create("${field.name.lower()}"));
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000379 ${fname}.configure(
380 .parent(this),
381 .size(${field_size}),
382 .lsb_pos(${field.bits.lsb}),
383 .access("${field_access}"),
384 .volatile(${field_volatile}),
385 .reset(${reg_width}'h${format(field.resval or 0, 'x')}),
386 .has_reset(1),
387 .is_rand(1),
388 .individually_accessible(1));
Weicai Yang00f6d782021-06-29 17:42:43 -0700389
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000390 ${fname}.set_original_access("${field_access}");
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000391% if field_tags:
392 // create field tags
393% for field_tag in field_tags:
394<%
395 tag = field_tag.split(":")
396%>\
397% if tag[0] == "excl":
Weicai Yang57dc8dc2021-07-22 18:10:14 -0700398 csr_excl.add_excl(${fname}.get_full_name(), ${tag[2]}, ${tag[1]});
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000399% endif
400% endfor
401% endif
402</%def>\
403##
404##
405## make_ral_pkg_window_class
406## =========================
407##
408## Generate the classes for a window inside a RAL package
409##
410## dv_base_prefix as for make_ral_pkg
411##
412## esc_if_name as for make_ral_pkg
413##
414## window a Window object
415<%def name="make_ral_pkg_window_class(dv_base_prefix, esc_if_name, window)">\
416<%
417 mem_name = window.name.lower()
418 mem_right = window.swaccess.dv_rights()
419 mem_n_bits = window.validbits
420 mem_size = window.items
421
422 class_name = gen_dv.mcname(esc_if_name, window)
423%>\
424 class ${class_name} extends ${dv_base_prefix}_mem;
425
426 `uvm_object_utils(${class_name})
427
428 function new(string name = "${class_name}",
429 longint unsigned size = ${mem_size},
430 int unsigned n_bits = ${mem_n_bits},
431 string access = "${mem_right}",
432 int has_coverage = UVM_NO_COVERAGE);
433 super.new(name, size, n_bits, access, has_coverage);
434% if window.byte_write:
435 set_mem_partial_write_support(1);
436% endif
437 endfunction : new
438
439 endclass : ${class_name}
440</%def>\
441##
442##
443## make_ral_pkg_window_instances
444## =============================
445##
446## Generate the classes for a window inside a RAL package
447##
448## reg_width as for make_ral_pkg
449##
450## esc_if_name as for make_ral_pkg
451##
452## rb a RegBlock object
453##
454<%def name="make_ral_pkg_window_instances(reg_width, esc_if_name, rb)">\
455% if rb.windows:
456
457 // create memories
458% for w in rb.windows:
459<%
460 mem_name = w.name.lower()
461 mem_right = w.swaccess.dv_rights()
462 mem_offset = "{}'h{:x}".format(reg_width, w.offset)
463 mem_n_bits = w.validbits
464 mem_size = w.items
465%>\
Michael Schaffner4e7114e2021-07-02 17:57:11 -0700466 ${mem_name} =
467 ${gen_dv.mcname(esc_if_name, w)}::type_id::create("${mem_name}");
Rupert Swarbrick25468b42021-03-11 15:20:10 +0000468 ${mem_name}.configure(.parent(this));
469 default_map.add_mem(.mem(${mem_name}),
470 .offset(${mem_offset}),
471 .rights("${mem_right}"));
472% endfor
473% endif
474</%def>\
Weicai Yang00f6d782021-06-29 17:42:43 -0700475##
476##
477## instantiate_register
478## ====================
479##
480## Actually instantiate a register in a register block
481##
482## reg_width an integer giving the width of registers in bits
483##
484## reg_block_path as for make_ral_pkg
485##
486## reg the Register to instantiate
487##
488## reg_type a string giving the type name (a subclass of
489## uvm_register) to instantiate.
490##
491## reg_inst a string giving the field of the uvm_reg_block that
492## should be set to this new register. For single
493## registers, this will just be the register name. For
494## elements of multi-registers, it will be the name of an
495## array item.
496##
497<%def name="instantiate_register(reg_width, reg_block_path, reg, reg_type, reg_inst)">\
498<%
499 reg_name = reg.name.lower()
500 reg_offset = "{}'h{:x}".format(reg_width, reg.offset)
501
502 inst_id_indent = ' ' * (len(reg_inst) + 4)
503%>\
504 ${reg_inst} = (${reg_type}::
505 ${inst_id_indent}type_id::create("${reg_name}"));
506 ${reg_inst}.configure(.blk_parent(this));
507 ${reg_inst}.build(csr_excl);
508 default_map.add_reg(.rg(${reg_inst}),
509 .offset(${reg_offset}));
Timothy Chenc58548c2021-08-02 19:17:24 -0700510% if reg.shadowed:
Timothy Chenc58548c2021-08-02 19:17:24 -0700511 % if reg.update_err_alert:
Weicai Yang00f6d782021-06-29 17:42:43 -0700512 ${reg_inst}.add_update_err_alert("${reg.update_err_alert}");
Timothy Chenc58548c2021-08-02 19:17:24 -0700513 % endif
514
515 % if reg.storage_err_alert:
Weicai Yang00f6d782021-06-29 17:42:43 -0700516 ${reg_inst}.add_storage_err_alert("${reg.storage_err_alert}");
Timothy Chenc58548c2021-08-02 19:17:24 -0700517 % endif
518
519 % if reg.hwext:
Pirmin Vogelc473f702021-08-12 16:43:54 +0200520 % for field in reg.fields:
521<%
522 shadowed_reg_path = ''
523 for tag in field.tags:
524 parts = tag.split(':')
525 if parts[0] == 'shadowed_reg_path':
526 shadowed_reg_path = parts[1]
527
528 if not shadowed_reg_path:
529 print("ERROR: ext shadow_reg does not have tags for shadowed_reg_path for each field!")
530 assert 0
531%>\
Weicai Yang00f6d782021-06-29 17:42:43 -0700532 ${reg_inst}.add_hdl_path_slice(
Weicai Yangf69b7002021-07-12 17:06:49 -0700533 "${shadowed_reg_path}.committed_reg.q",
Pirmin Vogelc473f702021-08-12 16:43:54 +0200534 ${field.bits.lsb}, ${field.bits.width()}, 0, "BkdrRegPathRtlCommitted");
Weicai Yang00f6d782021-06-29 17:42:43 -0700535 ${reg_inst}.add_hdl_path_slice(
Weicai Yangf69b7002021-07-12 17:06:49 -0700536 "${shadowed_reg_path}.shadow_reg.q",
Pirmin Vogelc473f702021-08-12 16:43:54 +0200537 ${field.bits.lsb}, ${field.bits.width()}, 0, "BkdrRegPathRtlShadow");
538 % endfor
Timothy Chenc58548c2021-08-02 19:17:24 -0700539 % endif
Weicai Yang00f6d782021-06-29 17:42:43 -0700540% endif
541% for field in reg.fields:
542<%
543 field_size = field.bits.width()
544 if len(reg.fields) == 1:
545 reg_field_name = reg_name
546 else:
547 reg_field_name = reg_name + "_" + field.name.lower()
Timothy Chenc57e5582021-07-30 22:06:24 -0700548
Timothy Chen5d835372021-08-18 19:39:25 -0700549 ##if reg.async_name and not reg.hwext:
550 ## reg_field_name += ".u_subreg"
Weicai Yang00f6d782021-06-29 17:42:43 -0700551%>\
552% if ((field.hwaccess.value[1] == HwAccess.NONE and\
553 field.swaccess.swrd() == SwRdAccess.RD and\
554 not field.swaccess.allows_write())):
555 // constant reg
556 ${reg_inst}.add_hdl_path_slice(
Weicai Yangf69b7002021-07-12 17:06:49 -0700557 "${reg_block_path}.${reg_field_name}_qs",
558 ${field.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtl");
Weicai Yang00f6d782021-06-29 17:42:43 -0700559% else:
560 ${reg_inst}.add_hdl_path_slice(
Weicai Yangf69b7002021-07-12 17:06:49 -0700561 "${reg_block_path}.u_${reg_field_name}.q${"s" if reg.hwext else ""}",
562 ${field.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtl");
Weicai Yang00f6d782021-06-29 17:42:43 -0700563% endif
Timothy Chenc58548c2021-08-02 19:17:24 -0700564% if reg.shadowed and not reg.hwext:
Weicai Yang00f6d782021-06-29 17:42:43 -0700565 ${reg_inst}.add_hdl_path_slice(
Weicai Yangf69b7002021-07-12 17:06:49 -0700566 "${reg_block_path}.u_${reg_field_name}.committed_reg.q",
567 ${field.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtlCommitted");
Weicai Yang00f6d782021-06-29 17:42:43 -0700568 ${reg_inst}.add_hdl_path_slice(
Weicai Yangf69b7002021-07-12 17:06:49 -0700569 "${reg_block_path}.u_${reg_field_name}.shadow_reg.q",
570 ${field.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtlShadow");
Weicai Yang00f6d782021-06-29 17:42:43 -0700571% endif
572% endfor
573
574% if reg.shadowed:
575 ${reg_inst}.set_is_shadowed();
576% endif
577% if reg.tags:
578 // create register tags
579% for reg_tag in reg.tags:
580<%
581 tag = reg_tag.split(":")
582%>\
583% if tag[0] == "excl":
584 csr_excl.add_excl(${reg_inst}.get_full_name(), ${tag[2]}, ${tag[1]});
585% endif
586% endfor
587% endif
588</%def>\
589##
590##
591## apply_regwen
592## ============
593##
594## Apply a regwen to a register
595##
596## rb the register block
597##
598## reg the Register that needs apply regwens
599##
600## reg_inst a string giving the field of the uvm_reg_block that
601## should be updated. For single registers, this will just
602## be the register name. For elements of multi-registers,
603## it will be the name of an array item.
604##
605<%def name="apply_regwen(rb, reg, reg_inst)">\
606% if reg.regwen is None:
607<% return "" %>\
608% endif
Weicai Yangf69b7002021-07-12 17:06:49 -0700609% for wen in rb.all_regs:
610% for wen_inst, wen_reg in get_inst_to_reg_dict(wen).items():
611% if reg.regwen.lower() == wen_reg.name.lower():
612 ${wen_inst}.add_lockable_reg_or_fld(${reg_inst});
Weicai Yang00f6d782021-06-29 17:42:43 -0700613<% return "" %>\
Weicai Yangf69b7002021-07-12 17:06:49 -0700614% elif wen_reg.name.lower() in reg.regwen.lower():
615% for field in wen_reg.get_field_list():
616% if reg.regwen.lower() == (wen_reg.name.lower() + "_" + field.name.lower()):
617 ${wen_inst}.${field.name.lower()}.add_lockable_reg_or_fld(${reg_inst});
Weicai Yang00f6d782021-06-29 17:42:43 -0700618<% return "" %>\
Weicai Yangf69b7002021-07-12 17:06:49 -0700619% endif
620% endfor
621% endif
622% endfor
Weicai Yang00f6d782021-06-29 17:42:43 -0700623% endfor
624</%def>\