| // Copyright lowRISC contributors. | |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | |
| // SPDX-License-Identifier: Apache-2.0 | |
| // UVM registers auto-generated by `reggen` containing UVM definitions for the entire top-level | |
| <%! | |
| from topgen.gen_dv import sv_base_addr | |
| from reggen.gen_dv import bcname, mcname, miname | |
| %> | |
| ## | |
| ## This template is used for chip-wide tests. It expects to be run with the | |
| ## following arguments | |
| ## | |
| ## top a Top object | |
| ## | |
| ## dv_base_prefix a string for the base register type. If it is FOO, then | |
| ## we will inherit from FOO_reg (assumed to be a subclass | |
| ## of uvm_reg). | |
| ## | |
| ## Like uvm_reg.sv.tpl, we use functions from uvm_reg_base.sv.tpl to define | |
| ## per-device-interface code. | |
| ## | |
| <%namespace file="uvm_reg_base.sv.tpl" import="*"/>\ | |
| ## | |
| ## | |
| ## Waive the package-filename check: we're going to be defining all sorts of | |
| ## packages in a single file. | |
| // verilog_lint: waive-start package-filename | |
| ## | |
| ## Iterate over the device interfaces of blocks in Top, constructing a package | |
| ## for each. Sorting items like this guarantees we'll work alphabetically in | |
| ## block name. | |
| % for block_name, block in sorted(top.blocks.items()): | |
| % for if_name, rb in block.reg_blocks.items(): | |
| <% | |
| if_suffix = '' if if_name is None else '_' + if_name | |
| esc_if_name = block_name.lower() + if_suffix | |
| if_desc = '' if if_name is None else '; interface {}'.format(if_name) | |
| reg_block_path = 'u_reg' + if_suffix | |
| reg_block_path = reg_block_path if block.hier_path is None else block.hier_path + "." + reg_block_path | |
| %>\ | |
| // Block: ${block_name.lower()}${if_desc} | |
| ${make_ral_pkg(dv_base_prefix, top.regwidth, reg_block_path, rb, esc_if_name)} | |
| % endfor | |
| % endfor | |
| ## | |
| ## | |
| ## Now that we've made the block-level packages, re-instate the | |
| ## package-filename check. The only package left is chip_ral_pkg, which should | |
| ## match the generated filename. | |
| // verilog_lint: waive-start package-filename | |
| // Block: chip | |
| package chip_ral_pkg; | |
| <% | |
| if_packages = [] | |
| for block_name, block in sorted(top.blocks.items()): | |
| for if_name in block.reg_blocks: | |
| if_suffix = '' if if_name is None else '_' + if_name | |
| if_packages.append('{}{}_ral_pkg'.format(block_name.lower(), if_suffix)) | |
| windows = top.window_block.windows | |
| %>\ | |
| ${make_ral_pkg_hdr(dv_base_prefix, if_packages)} | |
| ${make_ral_pkg_fwd_decls('chip', [], windows)} | |
| % for window in windows: | |
| ${make_ral_pkg_window_class(dv_base_prefix, 'chip', window)} | |
| % endfor | |
| class chip_reg_block extends ${dv_base_prefix}_reg_block; | |
| // sub blocks | |
| % for block_name, block in sorted(top.blocks.items()): | |
| % for inst_name in top.block_instances[block_name.lower()]: | |
| % for if_name, rb in block.reg_blocks.items(): | |
| <% | |
| if_suffix = '' if if_name is None else '_' + if_name | |
| esc_if_name = block_name.lower() + if_suffix | |
| if_inst = inst_name + if_suffix | |
| %>\ | |
| rand ${bcname(esc_if_name)} ${if_inst}; | |
| % endfor | |
| % endfor | |
| % endfor | |
| % if windows: | |
| // memories | |
| % for window in windows: | |
| rand ${mcname('chip', window)} ${miname(window)}; | |
| % endfor | |
| % endif | |
| `uvm_object_utils(chip_reg_block) | |
| function new(string name = "chip_reg_block", | |
| 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(${top.regwidth//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 | |
| // create sub blocks and add their maps | |
| % for block_name, block in sorted(top.blocks.items()): | |
| % for inst_name in top.block_instances[block_name.lower()]: | |
| % for if_name, rb in block.reg_blocks.items(): | |
| <% | |
| if_suffix = '' if if_name is None else '_' + if_name | |
| esc_if_name = block_name.lower() + if_suffix | |
| if_inst = inst_name + if_suffix | |
| if top.attrs.get(inst_name) == 'reggen_only': | |
| hdl_path = 'tb.dut.u_' + inst_name | |
| else: | |
| hdl_path = 'tb.dut.top_earlgrey.u_' + inst_name | |
| qual_if_name = (inst_name, if_name) | |
| base_addr = top.if_addrs[qual_if_name] | |
| base_addr_txt = sv_base_addr(top, qual_if_name) | |
| hpr_indent = (len(if_inst) + len('.set_hdl_path_root(')) * ' ' | |
| %>\ | |
| ${if_inst} = ${bcname(esc_if_name)}::type_id::create("${if_inst}"); | |
| ${if_inst}.configure(.parent(this)); | |
| ${if_inst}.build(.base_addr(base_addr + ${base_addr_txt}), .csr_excl(csr_excl)); | |
| ${if_inst}.set_hdl_path_root("${hdl_path}", | |
| ${hpr_indent}"BkdrRegPathRtl"); | |
| ${if_inst}.set_hdl_path_root("${hdl_path}", | |
| ${hpr_indent}"BkdrRegPathRtlCommitted"); | |
| ${if_inst}.set_hdl_path_root("${hdl_path}", | |
| ${hpr_indent}"BkdrRegPathRtlShadow"); | |
| default_map.add_submap(.child_map(${if_inst}.default_map), | |
| .offset(base_addr + ${base_addr_txt})); | |
| % endfor | |
| % endfor | |
| % endfor | |
| ${make_ral_pkg_window_instances(top.regwidth, 'chip', top.window_block)} | |
| endfunction : build | |
| endclass : chip_reg_block | |
| endpackage |