| // Copyright lowRISC contributors. | 
 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
 | // SPDX-License-Identifier: Apache-2.0 | 
 | <%! | 
 |   from reggen import gen_dv | 
 |   from reggen.access import HwAccess, SwRdAccess, SwWrAccess | 
 |   from reggen.multi_register import MultiRegister | 
 |   from reggen.register import Register | 
 |   from typing import Dict | 
 |  | 
 |   # Get a list reg and its instance name | 
 |   # For single reg, return Dict[reg_inst:reg] | 
 |   # For multireg, if it's dv_compact, return Dict[mr.name[idx]:mr.reg], | 
 |   # if not, return all the mr.regs with their name | 
 |   def get_inst_to_reg_dict(r) -> Dict: | 
 |     inst_regs = {} # type: Dict[inst_name:Register] | 
 |     if isinstance(r, MultiRegister): | 
 |       if r.dv_compact: | 
 |         inst_base = r.reg.name.lower() | 
 |         for idx, reg in enumerate(r.regs): | 
 |           inst_name = f'{inst_base}[{idx}]' | 
 |           inst_regs[inst_name] = reg | 
 |       else: | 
 |         for r0 in r.regs: | 
 |           inst_regs[r0.name] = r0 | 
 |     else: | 
 |       inst_regs[r.name.lower()] = r | 
 |     return inst_regs | 
 | %>\ | 
 | ## | 
 | ## | 
 | ## make_ral_pkg | 
 | ## ============ | 
 | ## | 
 | ## Generate the RAL package for a device interface. | 
 | ## | 
 | ##    dv_base_names     a DvBaseNames object that contains register base class names | 
 | ## | 
 | ##    reg_width         an integer giving the width of registers in bits | 
 | ## | 
 | ##    reg_block_path    the hierarchical path to the relevant register block in the | 
 | ##                      design | 
 | ## | 
 | ##    rb                a RegBlock object | 
 | ## | 
 | ##    esc_if_name       a string giving the full, escaped, interface name. For | 
 | ##                      a device interface called FOO on block BAR, | 
 | ##                      this will be bar__foo. For an unnamed interface | 
 | ##                      on block BAR, this will be just bar. | 
 | ## | 
 | <%def name="make_ral_pkg(dv_base_names, reg_width, reg_block_path, rb, esc_if_name)">\ | 
 | package ${esc_if_name}_ral_pkg; | 
 | ${make_ral_pkg_hdr(dv_base_names.pkg, [])} | 
 |  | 
 | ${make_ral_pkg_fwd_decls(esc_if_name, rb.type_regs, rb.windows)} | 
 | % for r in rb.all_regs: | 
 | <% | 
 |     mr = None | 
 |     if isinstance(r, MultiRegister): | 
 |       mr = r | 
 |       if r.dv_compact: | 
 |         regs = [r.reg] | 
 |       else: | 
 |         regs = r.regs | 
 |     else: | 
 |       regs = [r] | 
 | %>\ | 
 |   % for idx, reg in enumerate(regs): | 
 |  | 
 | ${make_ral_pkg_reg_class(dv_base_names.reg, dv_base_names.field, reg_width, esc_if_name, | 
 | reg_block_path, reg, mr, idx)} | 
 |   % endfor | 
 | % endfor | 
 | % for window in rb.windows: | 
 |  | 
 | ${make_ral_pkg_window_class(dv_base_names.mem, esc_if_name, window)} | 
 | % endfor | 
 |  | 
 | <% | 
 |   reg_block_name = gen_dv.bcname(esc_if_name) | 
 | %>\ | 
 |   class ${reg_block_name} extends ${dv_base_names.block}; | 
 | % if rb.flat_regs: | 
 |     // registers | 
 |   % for r in rb.all_regs: | 
 | <% | 
 |       # If it's dv_compact, then create it as an array even when it only contains one item | 
 |       count = 0 | 
 |       if isinstance(r, MultiRegister): | 
 |         if r.dv_compact: | 
 |           regs = [r.reg] | 
 |           count = len(r.regs) | 
 |         else: | 
 |           regs = r.regs | 
 |       else: | 
 |         regs = [r] | 
 | %>\ | 
 |     % for r0 in regs: | 
 | <% | 
 |       reg_type = gen_dv.rcname(esc_if_name, r0) | 
 |       inst_name = r0.name.lower() | 
 |       inst_decl = f'{inst_name}[{count}]' if count > 0 else inst_name | 
 | %>\ | 
 |     rand ${reg_type} ${inst_decl}; | 
 |       % if r0.alias_target is not None: | 
 | <% | 
 |         alias_inst_name = r0.alias_target.lower() | 
 |         alias_inst_decl = f'{alias_inst_name}[{count}]' if count > 0 else alias_inst_name | 
 | %>\ | 
 |     rand ${reg_type} ${alias_inst_decl}; // aliases to ${inst_decl} | 
 |       % endif | 
 |     % endfor | 
 |   % endfor | 
 | % endif | 
 | % if rb.windows: | 
 |     // memories | 
 | % for window in rb.windows: | 
 |     rand ${gen_dv.mcname(esc_if_name, window)} ${gen_dv.miname(window)}; | 
 | % endfor | 
 | % endif | 
 |  | 
 |     `uvm_object_utils(${reg_block_name}) | 
 |  | 
 |     function new(string name = "${reg_block_name}", | 
 |                  int    has_coverage = UVM_NO_COVERAGE); | 
 |       super.new(name, has_coverage); | 
 |     endfunction : new | 
 |  | 
 |     virtual function void build(uvm_reg_addr_t base_addr, | 
 |                                 csr_excl_item csr_excl = null); | 
 |       // create default map | 
 |       this.default_map = create_map(.name("default_map"), | 
 |                                     .base_addr(base_addr), | 
 |                                     .n_bytes(${reg_width//8}), | 
 |                                     .endian(UVM_LITTLE_ENDIAN)); | 
 |       if (csr_excl == null) begin | 
 |         csr_excl = csr_excl_item::type_id::create("csr_excl"); | 
 |         this.csr_excl = csr_excl; | 
 |       end | 
 | % if rb.flat_regs: | 
 |       set_hdl_path_root("tb.dut", "BkdrRegPathRtl"); | 
 |       set_hdl_path_root("tb.dut", "BkdrRegPathRtlShadow"); | 
 |       // create registers | 
 |   % for r in rb.all_regs: | 
 | <% | 
 |     r0 = r.reg if isinstance(r, MultiRegister) else r | 
 |     reg_type = gen_dv.rcname(esc_if_name, r0) | 
 | %>\ | 
 |     % if isinstance(r, MultiRegister): | 
 |       % for idx, reg in enumerate(r.regs): | 
 | <% | 
 |         if r.dv_compact: | 
 |           inst_base = r0.name.lower() | 
 |           inst_name = f'{inst_base}[{idx}]' | 
 |           if r0.alias_target is not None: | 
 |             alias_inst_base = r0.alias_target.lower() | 
 |             alias_inst_name = f'{alias_inst_base}[{idx}]' | 
 |         else: | 
 |           inst_name = reg.name.lower() | 
 |           reg_type = gen_dv.rcname(esc_if_name, reg) | 
 |           if r0.alias_target is not None: | 
 |             alias_inst_name = reg.alias_target.lower() | 
 | %>\ | 
 | ${instantiate_register(reg_width, reg_block_path, reg, reg_type, inst_name)}\ | 
 |         % if reg.alias_target is not None: | 
 |       // Assign alias register to generic handle. | 
 |       ${alias_inst_name} = ${inst_name}; | 
 |         % endif | 
 |       % endfor | 
 |     % else: | 
 | ${instantiate_register(reg_width, reg_block_path, r, reg_type, r.name.lower())}\ | 
 |     % endif | 
 |     % if r0.alias_target is not None: | 
 | <% | 
 |     inst_name = r0.name.lower() | 
 |     alias_inst_name = r0.alias_target.lower() | 
 | %>\ | 
 |       // Assign alias register to generic handle. | 
 |       ${alias_inst_name} = ${inst_name}; | 
 |     % endif | 
 |   % endfor | 
 | <% | 
 |   any_regwen = False | 
 |   for r in rb.flat_regs: | 
 |     if r.regwen: | 
 |       any_regwen = True | 
 |       break | 
 | %>\ | 
 |   % if any_regwen: | 
 |       // assign locked reg to its regwen reg | 
 |     % for r in rb.all_regs: | 
 |       % for inst, reg in get_inst_to_reg_dict(r).items(): | 
 | ${apply_regwen(rb, reg, inst)}\ | 
 |       % endfor | 
 |     % endfor | 
 |   % endif | 
 | % endif | 
 | ${make_ral_pkg_window_instances(reg_width, esc_if_name, rb)} | 
 |  | 
 |       // Create functional coverage for comportable IP-specific specialized registers. | 
 |       // This function can only be called if it is a root block to get the correct gating condition | 
 |       // and avoid creating duplicated cov. | 
 |       if (this.get_parent() == null && en_dv_reg_cov) create_cov(); | 
 |     endfunction : build | 
 |   endclass : ${reg_block_name} | 
 |  | 
 | endpackage | 
 | </%def>\ | 
 | ## | 
 | ## | 
 | ## make_ral_pkg_hdr | 
 | ## ================ | 
 | ## | 
 | ## Generate the header for a RAL package | 
 | ## | 
 | ##    dv_base_reg_pkg_name   a string name for the base reg_pkg type | 
 | ## | 
 | ##    deps                   a list of names for packages that should be explicitly | 
 | ##                           imported | 
 | ## | 
 | <%def name="make_ral_pkg_hdr(dv_base_reg_pkg_name, deps)">\ | 
 |   // dep packages | 
 |   import uvm_pkg::*; | 
 |   import dv_base_reg_pkg::*; | 
 | % if dv_base_reg_pkg_name != "dv_base_reg_pkg": | 
 |   import ${dv_base_reg_pkg_name}::*; | 
 | % endif | 
 | % for dep in deps: | 
 |   import ${dep}::*; | 
 | % endfor | 
 |  | 
 |   // macro includes | 
 |   `include "uvm_macros.svh"\ | 
 | </%def>\ | 
 | ## | 
 | ## | 
 | ## make_ral_pkg_fwd_decls | 
 | ## ====================== | 
 | ## | 
 | ## Generate the forward declarations for a RAL package | 
 | ## | 
 | ##    esc_if_name      as for make_ral_pkg | 
 | ## | 
 | ##    type_regs        a list of Register objects, one for each type that | 
 | ##                     should be defined. Each MultiRegister will contribute | 
 | ##                     just one register to the list. | 
 | ## | 
 | ##    windows          a list of Window objects | 
 | ## | 
 | <%def name="make_ral_pkg_fwd_decls(esc_if_name, type_regs, windows)">\ | 
 |   // Forward declare all register/memory/block classes | 
 | % for r in type_regs: | 
 |   typedef class ${gen_dv.rcname(esc_if_name, r)}; | 
 | % endfor | 
 | % for w in windows: | 
 |   typedef class ${gen_dv.mcname(esc_if_name, w)}; | 
 | % endfor | 
 |   typedef class ${gen_dv.bcname(esc_if_name)};\ | 
 | </%def>\ | 
 | ## | 
 | ## | 
 | ## make_ral_pkg_reg_class | 
 | ## ====================== | 
 | ## | 
 | ## Generate the classes for a register inside a RAL package | 
 | ## | 
 | ##    dv_base_reg_name     a string name for the base register type | 
 | ## | 
 | ##    dv_base_field_name   a string name for the base reg_field type | 
 | ## | 
 | ##    reg_width            as for make_ral_pkg | 
 | ## | 
 | ##    esc_if_name          as for make_ral_pkg | 
 | ## | 
 | ##    reg_block_path       as for make_ral_pkg | 
 | ## | 
 | ##    reg                  a Register object | 
 | ## | 
 | ##    mr                   a MultiRegister object if this reg is from a MultiRegister | 
 | ## | 
 | ##    reg_idx              the index location of this reg if this reg is from a MultiRegister, | 
 | ##                         or zero if not | 
 | <%def name="make_ral_pkg_reg_class(dv_base_reg_name, dv_base_field_name, reg_width, esc_if_name, | 
 | reg_block_path, reg, mr, reg_idx)">\ | 
 | <% | 
 |   reg_name = reg.name.lower() | 
 |  | 
 |   is_ext = reg.hwext | 
 |   for field in reg.fields: | 
 |     if (field.hwaccess.value[1] == HwAccess.NONE and | 
 |         field.swaccess.swrd() == SwRdAccess.RD and | 
 |         not field.swaccess.allows_write()): | 
 |       is_ext = 1 | 
 |  | 
 |   class_name = gen_dv.rcname(esc_if_name, reg) | 
 |   alias_class_name = gen_dv.alias_rcname(esc_if_name, reg) | 
 | %>\ | 
 |   class ${class_name} extends ${dv_base_reg_name}; | 
 |     // fields | 
 | <% | 
 |   suffix = "" | 
 |   start_idx = 0 | 
 |   add_style_waive = False | 
 |   compact_field_inst_name = "" | 
 |   compact_alias_field_inst_name = "" | 
 |  | 
 |   if mr is None: | 
 |       fields = reg.fields | 
 |   else: | 
 |     if not mr.compact: | 
 |       fields = mr.reg.fields | 
 |     else: | 
 |       fields = mr.regs[reg_idx].fields | 
 |       compact_field_inst_name = mr.reg.fields[0].name.lower() | 
 |       compact_alias_field_inst_name = mr.reg.fields[0].alias_target | 
 |       if mr.dv_compact: | 
 |         # The dv_compact flag means that the fields of the multi-reg divide equally into registers. | 
 |         # In this case, there's an array of registers and make_ral_pkg_reg_class() gets called once | 
 |         # to define that array's type, using the fields of the first register in the replication. | 
 |         assert reg_idx == 0 | 
 |         if len(fields) > 1: | 
 |           suffix = f'[{len(fields)}]' | 
 |       else: | 
 |         # In this case, the multi-register is "compact", so there might be multiple copies of its | 
 |         # single field in each generated register. But dv_compact is false, which probably means | 
 |         # that the fields didn't divide equally into a whole number of registers. In this case, we | 
 |         # are generating a different class for each output register and should spit out fields | 
 |         # accordingly. Note that we generate an array, even if len(fields) = 1. If that happens, we | 
 |         # know we're on the last generated register, so want to keep everything uniform. | 
 |         num_fields_per_reg = 32 // fields[0].bits.width() | 
 |         start_idx = num_fields_per_reg * reg_idx | 
 |         end_idx = start_idx + len(fields) - 1 | 
 |         suffix = f'[{start_idx}:{end_idx}]' | 
 |         if start_idx == 0: | 
 |           add_style_waive = True | 
 | %>\ | 
 | % if add_style_waive: | 
 |     // verilog_lint: waive unpacked-dimensions-range-ordering | 
 | % endif | 
 | % if compact_field_inst_name: | 
 |     rand ${dv_base_field_name} ${compact_field_inst_name}${suffix}; | 
 | %     if compact_alias_field_inst_name: | 
 |     rand ${dv_base_field_name} ${compact_alias_field_inst_name.lower()}${suffix}; | 
 | %     endif | 
 | % else: | 
 | %   for f in fields: | 
 |     rand ${dv_base_field_name} ${f.name.lower()}; | 
 | %     if f.alias_target is not None: | 
 |     rand ${dv_base_field_name} ${f.alias_target.lower()}; // aliases to ${f.name.lower()} | 
 | %     endif | 
 | %   endfor | 
 | % endif | 
 |  | 
 |     `uvm_object_utils(${class_name}) | 
 |  | 
 |     function new(string       name = "${class_name}", | 
 |                  int unsigned n_bits = ${reg_width}, | 
 |                  int          has_coverage = UVM_NO_COVERAGE); | 
 |       super.new(name, n_bits, has_coverage); | 
 |     endfunction : new | 
 |  | 
 |     virtual function void build(csr_excl_item csr_excl = null); | 
 | % if alias_class_name is not None: | 
 |       set_alias_name("${alias_class_name}"); | 
 | % endif\ | 
 |       // create fields | 
 | % for idx, field in enumerate(fields): | 
 | <% | 
 |     alias_reg_field_name = "" | 
 |     if compact_field_inst_name: | 
 |       reg_field_name = compact_field_inst_name | 
 |       if compact_alias_field_inst_name: | 
 |         alias_reg_field_name = compact_alias_field_inst_name | 
 |       # If len(fields) > 1, we define generated reg fields as an array and we need an index to | 
 |       # refer to the field object | 
 |       # If start_idx > 0, the fields cross more than one register, we define an array for the | 
 |       # fields even when the last register only contains one field. | 
 |       if len(fields) > 1 or start_idx > 0: | 
 |         reg_field_name = reg_field_name + f'[{idx + start_idx}]' | 
 |         if compact_alias_field_inst_name: | 
 |           alias_reg_field_name = alias_reg_field_name + f'[{idx + start_idx}]' | 
 |     else: | 
 |       reg_field_name = field.name.lower() | 
 |       if field.alias_target is not None: | 
 |         alias_reg_field_name = field.alias_target.lower() | 
 | %>\ | 
 | ${_create_reg_field(dv_base_field_name, reg_width, reg_block_path, reg.shadowed, reg.hwext, | 
 | reg_field_name, field)}\ | 
 |   % if field.alias_target is not None: | 
 |       ${alias_reg_field_name} = ${reg_field_name}; // assign to generic handle | 
 |   % endif | 
 | % endfor | 
 | % if is_ext: | 
 |       set_is_ext_reg(1); | 
 | % endif | 
 |     endfunction : build | 
 |   endclass : ${class_name}\ | 
 | </%def>\ | 
 | ## | 
 | ## | 
 | ## _create_reg_field | 
 | ## ================= | 
 | ## | 
 | ## Generate the code that creates a uvm_reg_field object for a field | 
 | ## in a register. | 
 | ## | 
 | ##    dv_base_reg_field_name   as for make_ral_pkg_reg_class | 
 | ## | 
 | ##    reg_width                as for make_ral_pkg | 
 | ## | 
 | ##    reg_block_path           as for make_ral_pkg | 
 | ## | 
 | ##    shadowed                 true if the field's register is shadowed | 
 | ## | 
 | ##    hwext                    true if the field's register is hwext | 
 | ## | 
 | ##    reg_field_name           a string with the name to give the field in the HDL | 
 | ## | 
 | ##    field                    a Field object | 
 | <%def name="_create_reg_field(dv_base_reg_field_name, reg_width, reg_block_path, shadowed, hwext, | 
 | reg_field_name, field)">\ | 
 | <% | 
 |   field_size = field.bits.width() | 
 |   field_access = field.swaccess.dv_rights() | 
 |  | 
 |   if not field.hwaccess.allows_write(): | 
 |     field_volatile = 0 | 
 |   else: | 
 |     field_volatile = 1 | 
 |   field_tags = field.tags | 
 |  | 
 |   fname = reg_field_name | 
 |   type_id_indent = ' ' * (len(fname) + 4) | 
 | %>\ | 
 |       ${fname} = (${dv_base_reg_field_name}:: | 
 |       ${type_id_indent}type_id::create("${field.name.lower()}")); | 
 |       ${fname}.configure( | 
 |         .parent(this), | 
 |         .size(${field_size}), | 
 |         .lsb_pos(${field.bits.lsb}), | 
 |         .access("${field_access}"), | 
 |         .volatile(${field_volatile}), | 
 |         .reset(${reg_width}'h${format(field.resval or 0, 'x')}), | 
 |         .has_reset(1), | 
 |         .is_rand(1), | 
 |         .individually_accessible(1)); | 
 |  | 
 | % if field.alias_target is not None: | 
 |       ${fname}.set_alias_name("${field.alias_target.lower()}"); | 
 | % endif | 
 |       ${fname}.set_original_access("${field_access}"); | 
 | % if field.mubi: | 
 |       ${fname}.set_mubi_width(${field_size}); | 
 | % endif | 
 | % if field_tags: | 
 |       // create field tags | 
 | %     for field_tag in field_tags: | 
 | <% | 
 |   tag = field_tag.split(":") | 
 | %>\ | 
 | %       if tag[0] == "excl": | 
 |       csr_excl.add_excl(${fname}.get_full_name(), ${tag[2]}, ${tag[1]}); | 
 | %       endif | 
 | %     endfor | 
 | %   endif | 
 | </%def>\ | 
 | ## | 
 | ## | 
 | ## make_ral_pkg_window_class | 
 | ## ========================= | 
 | ## | 
 | ## Generate the classes for a window inside a RAL package | 
 | ## | 
 | ##    dv_base_window_name   a string name for the base windoe type | 
 | ## | 
 | ##    esc_if_name           as for make_ral_pkg | 
 | ## | 
 | ##    window                a Window object | 
 | <%def name="make_ral_pkg_window_class(dv_base_window_name, esc_if_name, window)">\ | 
 | <% | 
 |   mem_name = window.name.lower() | 
 |   mem_right = window.swaccess.dv_rights() | 
 |   mem_n_bits = window.validbits | 
 |   mem_size = window.items | 
 |  | 
 |   class_name = gen_dv.mcname(esc_if_name, window) | 
 | %>\ | 
 |   class ${class_name} extends ${dv_base_window_name}; | 
 |  | 
 |     `uvm_object_utils(${class_name}) | 
 |  | 
 |     function new(string           name = "${class_name}", | 
 |                  longint unsigned size = ${mem_size}, | 
 |                  int unsigned     n_bits = ${mem_n_bits}, | 
 |                  string           access = "${mem_right}", | 
 |                  int              has_coverage = UVM_NO_COVERAGE); | 
 |       super.new(name, size, n_bits, access, has_coverage); | 
 | %     if window.byte_write: | 
 |       set_mem_partial_write_support(1); | 
 | %     endif | 
 | %     if window.data_intg_passthru: | 
 |       set_data_intg_passthru(1); | 
 | %     endif | 
 |     endfunction : new | 
 |  | 
 |   endclass : ${class_name} | 
 | </%def>\ | 
 | ## | 
 | ## | 
 | ## make_ral_pkg_window_instances | 
 | ## ============================= | 
 | ## | 
 | ## Generate the classes for a window inside a RAL package | 
 | ## | 
 | ##    reg_width        as for make_ral_pkg | 
 | ## | 
 | ##    esc_if_name      as for make_ral_pkg | 
 | ## | 
 | ##    rb               a RegBlock object | 
 | ## | 
 | <%def name="make_ral_pkg_window_instances(reg_width, esc_if_name, rb)">\ | 
 | % if rb.windows: | 
 |  | 
 |       // create memories | 
 | %  for w in rb.windows: | 
 | <% | 
 |       mem_name = w.name.lower() | 
 |       mem_right = w.swaccess.dv_rights() | 
 |       mem_offset = "{}'h{:x}".format(reg_width, w.offset) | 
 |       mem_n_bits = w.validbits | 
 |       mem_size = w.items | 
 | %>\ | 
 |       ${mem_name} = | 
 |           ${gen_dv.mcname(esc_if_name, w)}::type_id::create("${mem_name}"); | 
 |       ${mem_name}.configure(.parent(this)); | 
 |       default_map.add_mem(.mem(${mem_name}), | 
 |                           .offset(${mem_offset}), | 
 |                           .rights("${mem_right}")); | 
 | %   endfor | 
 | % endif | 
 | </%def>\ | 
 | ## | 
 | ## | 
 | ## instantiate_register | 
 | ## ==================== | 
 | ## | 
 | ## Actually instantiate a register in a register block | 
 | ## | 
 | ##    reg_width        an integer giving the width of registers in bits | 
 | ## | 
 | ##    reg_block_path   as for make_ral_pkg | 
 | ## | 
 | ##    reg              the Register to instantiate | 
 | ## | 
 | ##    reg_type         a string giving the type name (a subclass of | 
 | ##                     uvm_register) to instantiate. | 
 | ## | 
 | ##    reg_inst         a string giving the field of the uvm_reg_block that | 
 | ##                     should be set to this new register. For single | 
 | ##                     registers, this will just be the register name. For | 
 | ##                     elements of multi-registers, it will be the name of an | 
 | ##                     array item. | 
 | ## | 
 | <%def name="instantiate_register(reg_width, reg_block_path, reg, reg_type, reg_inst)">\ | 
 | <% | 
 |       reg_name = reg.name.lower() | 
 |       reg_offset = "{}'h{:x}".format(reg_width, reg.offset) | 
 |  | 
 |       inst_id_indent = ' ' * (len(reg_inst) + 4) | 
 | %>\ | 
 |       ${reg_inst} = (${reg_type}:: | 
 |       ${inst_id_indent}type_id::create("${reg_name}")); | 
 |       ${reg_inst}.configure(.blk_parent(this)); | 
 |       ${reg_inst}.build(csr_excl); | 
 |       default_map.add_reg(.rg(${reg_inst}), | 
 |                           .offset(${reg_offset})); | 
 | % if reg.shadowed: | 
 |       % if reg.update_err_alert: | 
 |       ${reg_inst}.add_update_err_alert("${reg.update_err_alert}"); | 
 |       % endif | 
 |  | 
 |       % if reg.storage_err_alert: | 
 |       ${reg_inst}.add_storage_err_alert("${reg.storage_err_alert}"); | 
 |       % endif | 
 |  | 
 |   % if reg.hwext: | 
 |     % for field in reg.fields: | 
 | <% | 
 |       shadowed_reg_path = '' | 
 |       for tag in field.tags: | 
 |         parts = tag.split(':') | 
 |         if parts[0] == 'shadowed_reg_path': | 
 |           shadowed_reg_path = parts[1] | 
 |  | 
 |       if not shadowed_reg_path: | 
 |         print("ERROR: ext shadow_reg does not have tags for shadowed_reg_path for each field!") | 
 |         assert 0 | 
 | %>\ | 
 |       ${reg_inst}.add_hdl_path_slice( | 
 |           "${shadowed_reg_path}.committed_reg.q", | 
 |           ${field.bits.lsb}, ${field.bits.width()}, 0, "BkdrRegPathRtl"); | 
 |       ${reg_inst}.add_hdl_path_slice( | 
 |           "${shadowed_reg_path}.shadow_reg.q", | 
 |           ${field.bits.lsb}, ${field.bits.width()}, 0, "BkdrRegPathRtlShadow"); | 
 |     % endfor | 
 |   % endif | 
 | % endif | 
 | % for field in reg.fields: | 
 | <% | 
 |     field_size = field.bits.width() | 
 |     if len(reg.fields) == 1: | 
 |       reg_field_name = reg_name | 
 |     else: | 
 |       reg_field_name = reg_name + "_" + field.name.lower() | 
 |  | 
 |     ##if reg.async_name and not reg.hwext: | 
 |     ##  reg_field_name += ".u_subreg" | 
 | %>\ | 
 | %   if ((field.hwaccess.value[1] == HwAccess.NONE and\ | 
 |        field.swaccess.swrd() == SwRdAccess.RD and\ | 
 |        not field.swaccess.allows_write())): | 
 |       // constant reg | 
 |       ${reg_inst}.add_hdl_path_slice( | 
 |           "${reg_block_path}.${reg_field_name}_qs", | 
 |           ${field.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtl"); | 
 | %   elif not reg.shadowed: | 
 |       ${reg_inst}.add_hdl_path_slice( | 
 |           "${reg_block_path}.u_${reg_field_name}.q${"s" if reg.hwext else ""}", | 
 |           ${field.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtl"); | 
 | %   endif | 
 | %   if reg.shadowed and not reg.hwext: | 
 |       ${reg_inst}.add_hdl_path_slice( | 
 |           "${reg_block_path}.u_${reg_field_name}.committed_reg.q", | 
 |           ${field.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtl"); | 
 |       ${reg_inst}.add_hdl_path_slice( | 
 |           "${reg_block_path}.u_${reg_field_name}.shadow_reg.q", | 
 |           ${field.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtlShadow"); | 
 | %   endif | 
 | % endfor | 
 |  | 
 | %     if reg.shadowed: | 
 |       ${reg_inst}.set_is_shadowed(); | 
 | %     endif | 
 | %     if reg.tags: | 
 |       // create register tags | 
 | %       for reg_tag in reg.tags: | 
 | <% | 
 |         tag = reg_tag.split(":") | 
 | %>\ | 
 | %         if tag[0] == "excl": | 
 |       csr_excl.add_excl(${reg_inst}.get_full_name(), ${tag[2]}, ${tag[1]}); | 
 | %         endif | 
 | %       endfor | 
 | %     endif | 
 | </%def>\ | 
 | ## | 
 | ## | 
 | ## apply_regwen | 
 | ## ============ | 
 | ## | 
 | ## Apply a regwen to a register | 
 | ## | 
 | ##    rb               the register block | 
 | ## | 
 | ##    reg              the Register that needs apply regwens | 
 | ## | 
 | ##    reg_inst         a string giving the field of the uvm_reg_block that | 
 | ##                     should be updated. For single registers, this will just | 
 | ##                     be the register name. For elements of multi-registers, | 
 | ##                     it will be the name of an array item. | 
 | ## | 
 | <%def name="apply_regwen(rb, reg, reg_inst)">\ | 
 | % if reg.regwen is None: | 
 | <% return "" %>\ | 
 | % endif | 
 | % for wen in rb.all_regs: | 
 | %   for wen_inst, wen_reg in get_inst_to_reg_dict(wen).items(): | 
 | %     if reg.regwen.lower() == wen_reg.name.lower(): | 
 |       ${wen_inst}.add_lockable_reg_or_fld(${reg_inst}); | 
 | <% return "" %>\ | 
 | %     elif wen_reg.name.lower() in reg.regwen.lower(): | 
 | %       for field in wen_reg.get_field_list(): | 
 | %         if reg.regwen.lower() == (wen_reg.name.lower() + "_" + field.name.lower()): | 
 |       ${wen_inst}.${field.name.lower()}.add_lockable_reg_or_fld(${reg_inst}); | 
 | <% return "" %>\ | 
 | %         endif | 
 | %       endfor | 
 | %     endif | 
 | %   endfor | 
 | % endfor | 
 | </%def>\ |