blob: f97b476a0c12dc097f9dfc6cd44bca2c3ff0c689 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Register Package auto-generated by `reggen` containing data structure
<%
from topgen import lib # TODO: Split lib to common lib module
from reggen.register import Register
from reggen.multi_register import MultiRegister
flat_regs = block.reg_block.flat_regs
num_regs = len(flat_regs)
max_regs_char = len("{}".format(num_regs - 1))
localparams = block.params.get_localparams()
%>\
package ${block.name}_reg_pkg;
% if localparams:
// Param list
% endif
% for param in localparams:
parameter ${param.param_type} ${param.name} = ${param.value};
% endfor
// Address width within the block
parameter int BlockAw = ${block.addr_width};
////////////////////////////
// Typedefs for registers //
////////////////////////////
% for r in block.reg_block.all_regs:
% if r.get_n_bits(["q"]):
<%
if isinstance(r, Register):
r0 = r
type_suff = 'reg_t'
else:
assert isinstance(r, MultiRegister)
r0 = r.reg
type_suff = 'mreg_t'
reg2hw_name = ('{}_reg2hw_{}_{}'
.format(block.name, r0.name.lower(), type_suff))
%>\
typedef struct packed {
% if r.is_homogeneous():
## If we have a homogeneous register or multireg, there is just one field
## (possibly replicated many times). The typedef is for one copy of that
## field.
<%
field = r.get_field_list()[0]
field_q_width = field.get_n_bits(r0.hwext, ['q'])
field_q_bits = lib.bitarray(field_q_width, 2)
%>\
logic ${field_q_bits} q;
% if field.hwqe:
logic qe;
% endif
% if field.hwre or (r0.shadowed and r0.hwext):
logic re;
% endif
% if r0.shadowed and not r0.hwext:
logic err_update;
logic err_storage;
% endif
% else:
## We are inhomogeneous, which means there is more than one different
## field. Generate a reg2hw typedef that packs together all the fields of
## the register.
% for f in r0.fields:
% if f.get_n_bits(r0.hwext, ["q"]) >= 1:
<%
field_q_width = f.get_n_bits(r0.hwext, ['q'])
field_q_bits = lib.bitarray(field_q_width, 2)
struct_name = f.name.lower()
%>\
struct packed {
logic ${field_q_bits} q;
% if f.hwqe:
logic qe;
% endif
% if f.hwre or (r0.shadowed and r0.hwext):
logic re;
% endif
% if r0.shadowed and not r0.hwext:
logic err_update;
logic err_storage;
% endif
} ${struct_name};
%endif
%endfor
%endif
} ${reg2hw_name};
%endif
% endfor
% for r in block.reg_block.all_regs:
% if r.get_n_bits(["d"]):
<%
if isinstance(r, Register):
r0 = r
type_suff = 'reg_t'
else:
assert isinstance(r, MultiRegister)
r0 = r.reg
type_suff = 'mreg_t'
hw2reg_name = ('{}_hw2reg_{}_{}'
.format(block.name, r0.name.lower(), type_suff))
%>\
typedef struct packed {
% if r.is_homogeneous():
## If we have a homogeneous register or multireg, there is just one field
## (possibly replicated many times). The typedef is for one copy of that
## field.
<%
field = r.get_field_list()[0]
field_d_width = field.get_n_bits(r0.hwext, ['d'])
field_d_bits = lib.bitarray(field_d_width, 2)
%>\
logic ${field_d_bits} d;
% if not r0.hwext:
logic de;
% endif
% else:
## We are inhomogeneous, which means there is more than one different
## field. Generate a hw2reg typedef that packs together all the fields of
## the register.
% for f in r0.fields:
% if f.get_n_bits(r0.hwext, ["d"]) >= 1:
<%
field_d_width = f.get_n_bits(r0.hwext, ['d'])
field_d_bits = lib.bitarray(field_d_width, 2)
struct_name = f.name.lower()
%>\
struct packed {
logic ${field_d_bits} d;
% if not r0.hwext:
logic de;
% endif
} ${struct_name};
%endif
%endfor
%endif
} ${hw2reg_name};
% endif
% endfor
///////////////////////////////////////
// Register to internal design logic //
///////////////////////////////////////
<%
nbits = block.reg_block.get_n_bits(["q", "qe", "re"])
packbit = 0
%>\
% if nbits > 0:
typedef struct packed {
% for r in block.reg_block.all_regs:
% if r.get_n_bits(["q"]):
<%
if isinstance(r, MultiRegister):
r0 = r.reg
repl_count = r.count
type_suff = 'mreg_t [{}:0]'.format(repl_count - 1)
else:
r0 = r
repl_count = 1
type_suff = 'reg_t'
struct_type = ('{}_reg2hw_{}_{}'
.format(block.name, r0.name.lower(), type_suff))
struct_width = r0.get_n_bits(['q', 'qe', 're']) * repl_count
msb = nbits - packbit - 1
lsb = msb - struct_width + 1
packbit += struct_width
%>\
${struct_type} ${r0.name.lower()}; // [${msb}:${lsb}]
% endif
% endfor
} ${block.name}_reg2hw_t;
% endif
///////////////////////////////////////
// Internal design logic to register //
///////////////////////////////////////
<%
nbits = block.reg_block.get_n_bits(["d", "de"])
packbit = 0
%>\
% if nbits > 0:
typedef struct packed {
% for r in block.reg_block.all_regs:
% if r.get_n_bits(["d"]):
<%
if isinstance(r, MultiRegister):
r0 = r.reg
repl_count = r.count
type_suff = 'mreg_t [{}:0]'.format(repl_count - 1)
else:
r0 = r
repl_count = 1
type_suff = 'reg_t'
struct_type = ('{}_hw2reg_{}_{}'
.format(block.name, r0.name.lower(), type_suff))
struct_width = r0.get_n_bits(['d', 'de']) * repl_count
msb = nbits - packbit - 1
lsb = msb - struct_width + 1
packbit += struct_width
%>\
${struct_type} ${r0.name.lower()}; // [${msb}:${lsb}]
% endif
% endfor
} ${block.name}_hw2reg_t;
% endif
// Register Address
<%
ublock = block.name.upper()
def reg_pfx(reg):
return '{}_{}'.format(ublock, reg.name.upper())
def reg_resname(reg):
return '{}_RESVAL'.format(reg_pfx(reg))
def field_resname(reg, field):
return '{}_{}_RESVAL'.format(reg_pfx(reg), field.name.upper())
%>\
% for r in flat_regs:
parameter logic [BlockAw-1:0] ${reg_pfx(r)}_OFFSET = ${block.addr_width}'h ${"%x" % r.offset};
% endfor
<%
hwext_regs = [r for r in flat_regs if r.hwext]
%>\
% if hwext_regs:
// Reset values for hwext registers and their fields
% for reg in hwext_regs:
<%
reg_width = reg.get_width()
reg_msb = reg_width - 1
%>\
parameter logic [${reg_msb}:0] ${reg_resname(reg)} = ${"{}'h {:x}".format(reg_width, reg.resval)};
% for field in reg.fields:
% if field.resval is not None:
<%
field_width = field.bits.width()
field_msb = field_width - 1
%>\
parameter logic [${field_msb}:0] ${field_resname(reg, field)} = ${"{}'h {:x}".format(field_width, field.resval)};
% endif
% endfor
% endfor
% endif
% if len(block.reg_block.windows) > 0:
// Window parameter
% for i,w in enumerate(block.reg_block.windows):
<%
win_pfx = '{}_{}'.format(ublock, w.name.upper())
base_txt_val = "{}'h {:x}".format(block.addr_width, w.offset)
size_txt_val = "{}'h {:x}".format(block.addr_width, w.size_in_bytes)
%>\
parameter logic [BlockAw-1:0] ${win_pfx}_OFFSET = ${base_txt_val};
parameter logic [BlockAw-1:0] ${win_pfx}_SIZE = ${size_txt_val};
% endfor
% endif
// Register Index
typedef enum int {
% for r in flat_regs:
${ublock}_${r.name.upper()}${"" if loop.last else ","}
% endfor
} ${block.name}_id_e;
// Register width information to check illegal writes
parameter logic [3:0] ${ublock}_PERMIT [${len(flat_regs)}] = '{
% for i,r in enumerate(flat_regs):
<%
index_str = "{}".format(i).rjust(max_regs_char)
width = r.get_width()
%>\
% if width > 24:
4'b 1111${" " if i == num_regs-1 else ","} // index[${index_str}] ${ublock}_${r.name.upper()}
% elif width > 16:
4'b 0111${" " if i == num_regs-1 else ","} // index[${index_str}] ${ublock}_${r.name.upper()}
% elif width > 8:
4'b 0011${" " if i == num_regs-1 else ","} // index[${index_str}] ${ublock}_${r.name.upper()}
% else:
4'b 0001${" " if i == num_regs-1 else ","} // index[${index_str}] ${ublock}_${r.name.upper()}
% endif
% endfor
};
endpackage