blob: 98edc205bbd9e07a981f23f28418192603696f15 [file] [log] [blame]
// Copyright 2022-2023 Google LLC.
// 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, get_block_base_name,
get_dv_base_names_objects, DvBaseNames)
%>
##
## This template is used for chip-wide tests. It expects to be run with the
## following arguments
##
## top a Top object
##
## dv_base_names a DvBaseNames object for the base register type
##
## create_isp_wrapper Create isp_wrapper RAL model based on the context
##
## create_dma Create RAL models for dma0/dma_smc based on the context
##
## 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.
<%dv_base_names_map = get_dv_base_names_objects(dv_base_names) %>\
% 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 = block.bus_interfaces.device_hier_paths[if_name] + if_suffix
%>\
// Block: ${block_name.lower()}${if_desc}
<%
block_dv_base_names = get_block_base_name(dv_base_names_map, block_name.lower())
%>\
${make_ral_pkg(block_dv_base_names, 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
block_dv_base_names = get_block_base_name(dv_base_names_map, "chip")
%>\
${make_ral_pkg_hdr(block_dv_base_names.pkg, if_packages)}
${make_ral_pkg_fwd_decls('chip', [], windows)}
% for window in windows:
${make_ral_pkg_window_class(block_dv_base_names.mem, 'chip', window)}
% endfor
class chip_reg_block extends ${block_dv_base_names.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
create_block = "1'b1"
if (inst_name == "rv_plic_smc" or
inst_name == "tlul_mailbox_smc" or
inst_name == "rv_core_ibex_smc"):
create_block = "1'b0"
elif inst_name == "isp_wrapper":
create_block = create_isp_wrapper
elif (inst_name == "dma0" or
inst_name == "dma_smc"):
create_block = create_dma
%>\
bit create_${if_inst} = ${create_block};
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_matcha.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 (create_${if_inst}) begin
${if_inst} =
${bcname(esc_if_name)}::type_id::create("${if_inst}");
${if_inst}.set_ip_name("${inst_name}");
${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}));
end
% endfor
% endfor
% endfor
${make_ral_pkg_window_instances(top.regwidth, 'chip', top.window_block)}
endfunction : build
endclass : chip_reg_block
endpackage