| // 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 data structure |
| // Do Not Edit directly |
| <% from reggen import (gen_dv) |
| %>\ |
| <%def name="construct_classes(block)">\ |
| % for b in block.blocks: |
| ${construct_classes(b)} |
| % endfor |
| <% |
| regs_flat = block.reg_block.flat_regs |
| hier_path = "" |
| if (block.hier_path): |
| hier_path = block.hier_path + "." |
| %>\ |
| |
| // Block: ${block.name} |
| package ${block.name}_ral_pkg; |
| // dep packages |
| import uvm_pkg::*; |
| import dv_base_reg_pkg::*; |
| % if dv_base_prefix != "dv_base": |
| import ${dv_base_prefix}_reg_pkg::*; |
| % endif |
| % for b in block.blocks: |
| import ${b.name}_ral_pkg::*; |
| % endfor |
| |
| // macro includes |
| `include "uvm_macros.svh" |
| |
| // Forward declare all register/memory/block classes |
| % for r in regs_flat: |
| typedef class ${gen_dv.rcname(block, r)}; |
| % endfor |
| % for w in block.reg_block.windows: |
| typedef class ${gen_dv.mcname(block, w)}; |
| % endfor |
| typedef class ${gen_dv.bcname(block)}; |
| |
| % for r in regs_flat: |
| <% |
| reg_width = block.width |
| reg_name = r.name.lower() |
| is_ext = 0 |
| reg_shadowed = r.shadowed |
| %>\ |
| // Class: ${gen_dv.rcname(block, r)} |
| class ${gen_dv.rcname(block, r)} extends ${dv_base_prefix}_reg; |
| // fields |
| % for f in r.fields: |
| rand ${dv_base_prefix}_reg_field ${f.name.lower()}; |
| % endfor |
| |
| `uvm_object_utils(${gen_dv.rcname(block, r)}) |
| |
| function new(string name = "${gen_dv.rcname(block, r)}", |
| 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); |
| // create fields |
| % for f in r.fields: |
| <% |
| field_size = f.bits.width() |
| if f.swaccess.key == "r0w1c": |
| field_access = "W1C" |
| else: |
| field_access = f.swaccess.value[1].name |
| |
| if not f.hwaccess.allows_write(): |
| field_volatile = 0 |
| else: |
| field_volatile = 1 |
| field_tags = f.tags |
| |
| if r.hwext or (f.hwaccess.value[1] == HwAccess.NONE and |
| f.swaccess.swrd() == SwRdAccess.RD and |
| not f.swaccess.allows_write()): |
| is_ext = 1 |
| |
| fname = f.name.lower() |
| |
| if len(r.fields) == 1: |
| reg_field_name = reg_name |
| else: |
| reg_field_name = reg_name + "_" + fname |
| %>\ |
| ${fname} = ${dv_base_prefix}_reg_field::type_id::create("${fname}"); |
| ${fname}.configure( |
| .parent(this), |
| .size(${field_size}), |
| .lsb_pos(${f.bits.lsb}), |
| .access("${field_access}"), |
| .volatile(${field_volatile}), |
| .reset(${reg_width}'h${format(f.resval or 0, 'x')}), |
| .has_reset(1), |
| .is_rand(1), |
| .individually_accessible(1)); |
| ${fname}.set_original_access("${field_access}"); |
| % if ((f.hwaccess.value[1] == HwAccess.NONE and\ |
| f.swaccess.swrd() == SwRdAccess.RD and\ |
| not f.swaccess.allows_write())): |
| // constant reg |
| add_hdl_path_slice("${hier_path}u_reg.${reg_field_name}_qs", ${f.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtl"); |
| % else: |
| add_hdl_path_slice("${hier_path}u_reg.u_${reg_field_name}.q${"s" if r.hwext else ""}", ${f.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtl"); |
| % endif |
| % if reg_shadowed and not r.hwext: |
| add_hdl_path_slice("${hier_path}u_reg.u_${reg_field_name}.committed_reg.q", ${f.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtlCommitted"); |
| add_hdl_path_slice("${hier_path}u_reg.u_${reg_field_name}.shadow_reg.q", ${f.bits.lsb}, ${field_size}, 0, "BkdrRegPathRtlShadow"); |
| % 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(${f.name.lower()}.get_full_name(), ${tag[2]}, ${tag[1]}); |
| % endif |
| % endfor |
| % endif |
| % endfor |
| % if reg_shadowed and r.hwext: |
| add_update_err_alert("${r.update_err_alert}"); |
| add_storage_err_alert("${r.storage_err_alert}"); |
| <% shadowed_reg_path = "" %>\ |
| % for r_tag in r.tags: |
| <% tag = r_tag.split(":") %>\ |
| % if tag[0] == "shadowed_reg_path": |
| <% shadowed_reg_path = tag[1] %>\ |
| % endif |
| % endfor |
| % if shadowed_reg_path == "": |
| print("ERROR: ext shadow_reg does not have tags for shadowed_reg_path!") |
| % else: |
| add_hdl_path_slice("${shadowed_reg_path}.committed_reg.q", 0, (${f.bits.lsb} + ${field_size}), 0, "BkdrRegPathRtlCommitted"); |
| add_hdl_path_slice("${shadowed_reg_path}.shadow_reg.q", 0, (${f.bits.lsb} + ${field_size}), 0, "BkdrRegPathRtlShadow"); |
| % endif |
| % endif |
| % if is_ext: |
| set_is_ext_reg(1); |
| % endif |
| endfunction : build |
| |
| endclass : ${gen_dv.rcname(block, r)} |
| |
| % endfor |
| % for w in block.reg_block.windows: |
| <% |
| mem_name = w.name.lower() |
| mem_right = w.swaccess.dv_rights() |
| mem_n_bits = w.validbits |
| mem_size = w.items |
| %>\ |
| // Class: ${gen_dv.mcname(block, w)} |
| class ${gen_dv.mcname(block, w)} extends ${dv_base_prefix}_mem; |
| |
| `uvm_object_utils(${gen_dv.mcname(block, w)}) |
| |
| function new(string name = "${gen_dv.mcname(block, w)}", |
| 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 w.byte_write: |
| set_mem_partial_write_support(1); |
| % endif |
| endfunction : new |
| |
| endclass : ${gen_dv.mcname(block, w)} |
| |
| % endfor |
| // Class: ${gen_dv.bcname(block)} |
| class ${gen_dv.bcname(block)} extends ${dv_base_prefix}_reg_block; |
| % if block.blocks: |
| // sub blocks |
| % endif |
| % for b in block.blocks: |
| % for inst in b.base_addr.keys(): |
| rand ${gen_dv.bcname(b)} ${inst}; |
| % endfor |
| % endfor |
| % if regs_flat: |
| // registers |
| % endif |
| % for r in regs_flat: |
| rand ${gen_dv.rcname(block, r)} ${r.name.lower()}; |
| % endfor |
| % if block.reg_block.windows: |
| // memories |
| % endif |
| % for w in block.reg_block.windows: |
| rand ${gen_dv.mcname(block, w)} ${gen_dv.miname(w)}; |
| % endfor |
| |
| `uvm_object_utils(${gen_dv.bcname(block)}) |
| |
| function new(string name = "${gen_dv.bcname(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(${block.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 block.blocks: |
| |
| // create sub blocks and add their maps |
| % endif |
| % for b in block.blocks: |
| % for inst, base_addr in b.base_addr.items(): |
| ${inst} = ${gen_dv.bcname(b)}::type_id::create("${inst}"); |
| ${inst}.configure(.parent(this)); |
| ${inst}.build(.base_addr(base_addr + ${gen_dv.sv_base_addr(b, inst)}), .csr_excl(csr_excl)); |
| ${inst}.set_hdl_path_root("tb.dut.top_earlgrey.u_${inst}", "BkdrRegPathRtl"); |
| ${inst}.set_hdl_path_root("tb.dut.top_earlgrey.u_${inst}", "BkdrRegPathRtlCommitted"); |
| ${inst}.set_hdl_path_root("tb.dut.top_earlgrey.u_${inst}", "BkdrRegPathRtlShadow"); |
| default_map.add_submap(.child_map(${inst}.default_map), |
| .offset(base_addr + ${gen_dv.sv_base_addr(b, inst)})); |
| % endfor |
| % endfor |
| % if regs_flat: |
| set_hdl_path_root("tb.dut", "BkdrRegPathRtl"); |
| set_hdl_path_root("tb.dut", "BkdrRegPathRtlCommitted"); |
| set_hdl_path_root("tb.dut", "BkdrRegPathRtlShadow"); |
| // create registers |
| % endif |
| % for r in regs_flat: |
| <% |
| reg_name = r.name.lower() |
| reg_right = r.dv_rights() |
| reg_width = block.width |
| reg_offset = str(reg_width) + "'h" + "%x" % r.offset |
| reg_tags = r.tags |
| reg_shadowed = r.shadowed |
| %>\ |
| ${reg_name} = ${gen_dv.rcname(block, r)}::type_id::create("${reg_name}"); |
| ${reg_name}.configure(.blk_parent(this)); |
| ${reg_name}.build(csr_excl); |
| default_map.add_reg(.rg(${reg_name}), |
| .offset(${reg_offset}), |
| .rights("${reg_right}")); |
| % if reg_shadowed: |
| ${reg_name}.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_name}.get_full_name(), ${tag[2]}, ${tag[1]}); |
| % endif |
| % endfor |
| % endif |
| % endfor |
| |
| // assign locked reg to its regwen reg |
| % for r in regs_flat: |
| % if r.regwen: |
| % for reg in regs_flat: |
| % if r.regwen.lower() == reg.name.lower(): |
| ${r.regwen.lower()}.add_lockable_reg_or_fld(${r.name.lower()}); |
| <% break %>\ |
| % elif reg.name.lower() in r.regwen.lower(): |
| % for field in reg.get_field_list(): |
| % if r.regwen.lower() == (reg.name.lower() + "_" + field.name.lower()): |
| ${r.regwen.lower()}.${field.name.lower()}.add_lockable_reg_or_fld(${r.name.lower()}); |
| <% break %>\ |
| % endif |
| % endfor |
| % endif |
| % endfor |
| % endif |
| % endfor |
| |
| % if block.reg_block.windows: |
| |
| // create memories |
| % endif |
| % for w in block.reg_block.windows: |
| <% |
| mem_name = w.name.lower() |
| mem_right = w.swaccess.dv_rights() |
| mem_offset = str(block.width) + "'h" + "%x" % w.offset |
| mem_n_bits = w.validbits |
| mem_size = w.items |
| %>\ |
| ${mem_name} = ${gen_dv.mcname(block, 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 |
| endfunction : build |
| |
| endclass : ${gen_dv.bcname(block)} |
| |
| endpackage\ |
| </%def>\ |
| |
| // verilog_lint: waive-start package-filename |
| ${construct_classes(block)} |
| |
| // verilog_lint: waive-stop package-filename |