blob: 0670db53f2870528ce90320ced39f8c57bc9c77a [file] [log] [blame]
// 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
from reggen.ip_block import IpBlock
from reggen.top import Top
%>\
<%def name="construct_classes(block)">\
<%
if isinstance(block, IpBlock) and block.hier_path is not None:
hier_path = block.hier_path + "."
else:
hier_path = ""
if isinstance(block, IpBlock):
regs_flat = []
seg_windows = []
flat_windows = []
for if_name, rb in block.reg_blocks.items():
regs_flat += rb.flat_regs
flat_windows += rb.windows
seg_windows.append(rb.windows)
else:
assert isinstance(block, Top)
regs_flat = []
flat_windows = block.window_block.windows
seg_windows = [block.window_block.windows]
reg_width = block.regwidth
%>\
% if isinstance(block, Top):
% for sub_block in block.blocks.values():
${construct_classes(sub_block)}
% endfor
% endif
// Block: ${block.name.lower()}
package ${block.name.lower()}_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
% if isinstance(block, Top):
% for b in block.blocks:
import ${b.lower()}_ral_pkg::*;
% endfor
% endif
// 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 flat_windows:
typedef class ${gen_dv.mcname(block, w)};
% endfor
typedef class ${gen_dv.bcname(block)};
% for r in regs_flat:
<%
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 flat_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 isinstance(block, Top):
// sub blocks
% for b in block.blocks.values():
% for inst_name in block.block_instances[b.name.lower()]:
rand ${gen_dv.bcname(b)} ${inst_name};
% endfor
% endfor
%endif
% if regs_flat:
// registers
% endif
% for r in regs_flat:
rand ${gen_dv.rcname(block, r)} ${r.name.lower()};
% endfor
% if flat_windows:
// memories
% endif
% for w in flat_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(${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 isinstance(block, Top):
// create sub blocks and add their maps
% for b in block.blocks.values():
% for inst in block.block_instances[b.name.lower()]:
% for if_name in b.reg_blocks.keys():
<%
qual_if_name = (inst, if_name)
base_addr = block.if_addrs[qual_if_name]
sv_base_addr = gen_dv.sv_base_addr(block, qual_if_name)
%>\
${inst} = ${gen_dv.bcname(b)}::type_id::create("${inst}");
${inst}.configure(.parent(this));
${inst}.build(.base_addr(base_addr + ${sv_base_addr}), .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 + ${sv_base_addr}));
% endfor
% endfor
% endfor
% endif
% 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
% for idx, rb in enumerate(block.reg_blocks.values()):
<%
seg_offset = idx << 28
assert seg_offset < (1 << 32)
%>\
% for r in rb.flat_regs:
<%
reg_name = r.name.lower()
reg_right = r.dv_rights()
assert seg_offset + r.offset < (1 << 32)
reg_offset = "{}'h{:x}".format(reg_width, seg_offset + 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
% endfor
% endif
// 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 seg_windows:
// create memories
% endif
% for idx, windows in enumerate(seg_windows):
<%
seg_offset = idx << 28
assert seg_offset < (1 << 32)
%>\
% for w in windows:
<%
mem_name = w.name.lower()
mem_right = w.swaccess.dv_rights()
mem_offset = "{}'h{:x}".format(reg_width, seg_offset + 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
% 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