[reggen] Refactor reggen, first step towards nested multiregs
diff --git a/util/reggen/data.py b/util/reggen/data.py
index e3edfdb..aaad2e1 100644
--- a/util/reggen/data.py
+++ b/util/reggen/data.py
@@ -9,7 +9,7 @@
"""Field in a register.
Field class contains necessary info to generate RTL code.
- It has two additional (tool generated) feidls, swrdaccess and swwraccess,
+ It has two additional (tool generated) fields, swrdaccess and swwraccess,
which represent read and write type. This makes RTL generation code simpler.
"""
name = "" # required
@@ -22,6 +22,7 @@
hwaccess = HwAccess.HRO
hwqe = False
hwre = False
+ hwext = False
def __init__(self):
self.name = "" # required
@@ -34,6 +35,24 @@
self.hwaccess = HwAccess.HRO
self.hwqe = False
self.hwre = False
+ self.hwext = False
+
+ def get_n_bits(self, bittype=["q"]):
+ n_bits = 0
+ if "q" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HRO]:
+ n_bits += self.msb - self.lsb + 1
+ if "d" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HWO]:
+ n_bits += self.msb - self.lsb + 1
+ if "qe" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HRO]:
+ n_bits += self.hwqe
+ if "re" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HRO]:
+ n_bits += self.hwre
+ if "de" in bittype and self.hwaccess in [HwAccess.HRW, HwAccess.HWO]:
+ n_bits += not self.hwext
+ return n_bits
+
+ def get_fields_flat(self):
+ return [self]
class Reg():
@@ -48,8 +67,8 @@
fields = []
width = 0 # indicate register size
- def __init__(self):
- self.name = ""
+ def __init__(self, name=""):
+ self.name = name
self.offset = 0
self.hwqe = False
self.hwre = False
@@ -60,15 +79,85 @@
self.fields = []
self.width = 0
+ def is_multi_reg(self):
+ """Returns true if this is a multireg"""
+ return False
+
+ def get_n_bits(self, bittype=["q"]):
+ """Returns number of bits in this register (including all multiregs and
+ fields). By default this function counts read data bits (bittype "q"),
+ but other bits such as "d", qe", "re", "de" can be counted as well by
+ specifying them in the bittype list argument.
+ """
+ n_bits = 0
+ for f in self.fields:
+ n_bits += f.get_n_bits(bittype)
+ return n_bits
+
+ def get_fields_flat(self):
+ """Returns a flat list of all the fields in this register"""
+ fields = []
+ for f in self.fields:
+ fields += f.get_fields_flat()
+ return fields
+
+ def get_field_flat(self, linear_idx):
+ """Returns a specific field at a linear index position in
+ the flattened field list"""
+ fields_flat = self.get_fields_flat()
+ return fields_flat[linear_idx]
+
+ def get_n_fields_flat(self):
+ """Returns the number of fields contained in the flat field list"""
+ return len(self.get_fields_flat())
+
+ def get_regs_flat(self):
+ """Returns the a flatt list containing all
+ registers and subregisters"""
+ if isinstance(self.fields[0], Field):
+ return [self]
+ else:
+ regs = []
+ for r in self.fields:
+ regs += r.get_regs_flat()
+ return regs
+
+ def get_reg_flat(self, linear_index):
+ """Returns a specific register at a linear index position in
+ the flattened regiser list"""
+ regs_flat = self.get_regs_flat()
+ return regs_flat[linear_index]
+
+ def get_n_regs_flat(self):
+ """Returns the number of registers contained in
+ the flat register list"""
+ return len(self.get_regs_flat())
+
+ def get_nested_dims(self):
+ """Recursively get dimensions of nested registers (outputs a list)"""
+ dims = []
+ if self.is_multi_reg():
+ dims = self.fields[0].get_nested_dims()
+ return [len(self.fields)] + dims
+
+ def get_nested_params(self):
+ """Recursively get parameters of nested registers (outputs a list)"""
+ params = []
+ if self.is_multi_reg():
+ params = self.fields[0].get_nested_params()
+ return [self.param] + params
+
class MultiReg(Reg):
param = ""
- regs = []
- def __init__(self):
- super.__init__(self)
+ def __init__(self, name):
+ Reg.__init__(self, name)
self.param = ""
- self.regs = []
+
+ def is_multi_reg(self):
+ """Returns true if this is a multireg"""
+ return True
class Window():
@@ -101,3 +190,25 @@
self.wins = []
self.blocks = []
self.params = []
+
+ def get_regs_flat(self):
+ """Returns flattened register list
+ """
+ regs = []
+ for r in self.regs:
+ regs += r.get_regs_flat()
+ return regs
+
+ def get_n_bits(self, bittype=["q"]):
+ """Returns number of bits in this block (including all multiregs and
+ fields). By default this function counts read data bits (bittype "q"),
+ but other bits such as "d", qe", "re", "de" can be counted as well by
+ specifying them in the bittype list argument.
+ """
+ n_bits = 0
+ for r in self.regs:
+ n_bits += r.get_n_bits(bittype)
+ return n_bits
+
+ def get_n_regs_flat(self):
+ return len(self.get_regs_flat())
diff --git a/util/reggen/gen_rtl.py b/util/reggen/gen_rtl.py
index d4197db..be60626 100644
--- a/util/reggen/gen_rtl.py
+++ b/util/reggen/gen_rtl.py
@@ -11,8 +11,8 @@
from mako.template import Template
from pkg_resources import resource_filename
-from .field_enums import HwAccess, SwAccess, SwRdAccess, SwWrAccess
from .data import *
+from .field_enums import HwAccess, SwAccess, SwRdAccess, SwWrAccess
def escape_name(name):
@@ -46,6 +46,7 @@
f.hwaccess = obj["genhwaccess"]
f.hwqe = obj["genhwqe"]
f.hwre = obj["genhwre"]
+ f.hwext = reg.hwext
# resval handling. `genresval` has zero value if `resval` field is defined
# as unknown 'x'
@@ -55,32 +56,48 @@
def parse_reg(obj):
- """Convert OrderedDict register into Register class
+ """Convert OrderedDict register into Register or MultiRegister object.
+ Supports nested MultiRegisters.
"""
+ if 'multireg' in obj:
+ regs = []
+ for genr in obj['multireg']['genregs']:
+ regs += [parse_reg(genr)]
+ # get register properties of the first register in the multireg and
+ # copy them to the parent
+ # since all regs in a multireg have the same props
+ reg = MultiReg(regs[0].get_reg_flat(0))
+ # since this is a multireg, the list of fields can
+ # contain regs or multiregs
+ reg.fields = regs
+ # TODO: need to rework this once the underlying JSON has been changed
+ reg.name = escape_name(obj['multireg']['name'])
+ # TODO: need to reference proper param here such that it can be used
+ # in the package template for the array declaration
+ # reg.param = ...
+ else:
+ reg = Reg(escape_name(obj['name']))
+ reg.offset = obj["genoffset"]
+ reg.fields = []
- reg = Reg()
- reg.name = escape_name(obj['name'])
- reg.offset = obj["genoffset"]
- reg.fields = []
+ reg.hwext = (obj['hwext'] == "true")
+ reg.hwqe = (obj["hwqe"] == "true")
+ reg.hwre = (obj["hwre"] == "true")
+ reg.resval = obj["genresval"]
+ reg.dvrights = obj["gendvrights"]
+ reg.regwen = obj["regwen"].lower()
- reg.hwext = (obj['hwext'] == "true")
- reg.hwqe = (obj["hwqe"] == "true")
- reg.hwre = (obj["hwre"] == "true")
- reg.resval = obj["genresval"]
- reg.dvrights = obj["gendvrights"]
- reg.regwen = obj["regwen"].lower()
+ # Parsing Fields
+ for f in obj["fields"]:
+ field = parse_field(f, reg, len(obj["fields"]))
+ if field != None:
+ reg.fields.append(field)
+ reg.width = max(reg.width, field.msb + 1)
- # Parsing Fields
- for f in obj["fields"]:
- field = parse_field(f, reg, len(obj["fields"]))
- if field != None:
- reg.fields.append(field)
- reg.width = max(reg.width, field.msb + 1)
-
- # TODO(eunchan): Field bitfield overlapping check
- log.info("R[0x%04x]: %s ", reg.offset, reg.name)
- for f in reg.fields:
- log.info(" F[%2d:%2d]: %s", f.msb, f.lsb, f.name)
+ # TODO(eunchan): Field bitfield overlapping check
+ log.info("R[0x%04x]: %s ", reg.offset, reg.name)
+ for f in reg.fields:
+ log.info(" F[%2d:%2d]: %s", f.msb, f.lsb, f.name)
return reg
@@ -139,16 +156,8 @@
if win != None:
block.wins.append(win)
continue
- elif 'multireg' in r:
- for genr in r['multireg']['genregs']:
- reg = parse_reg(genr)
- if reg != None:
- block.regs.append(reg)
- continue
- reg = parse_reg(r)
- if reg != None:
- block.regs.append(reg)
- # mdhayter -- moved logging into parse_regs
+
+ block.regs += [parse_reg(r)]
# Last offset and calculate space
# Later on, it could use block.regs[-1].genoffset
diff --git a/util/reggen/reg_pkg.tpl.sv b/util/reggen/reg_pkg.tpl.sv
index 376adde..b77fbff 100644
--- a/util/reggen/reg_pkg.tpl.sv
+++ b/util/reggen/reg_pkg.tpl.sv
@@ -5,7 +5,7 @@
// Register Package auto-generated by `reggen` containing data structure
<%
- num_regs = len(block.regs)
+ num_regs = block.get_n_regs_flat()
max_regs_char = len("{}".format(num_regs-1))
%>\
package ${block.name}_reg_pkg;
@@ -17,39 +17,45 @@
localparam ${param["type"]} ${param["name"]} = ${param["default"]};
% endfor
-// Register to internal design logic
+/////////////////////////////////////////////////////////////////////
+// Typedefs for multiregs
+/////////////////////////////////////////////////////////////////////
+% for r in block.regs:
+% if r.is_multi_reg() and r.get_n_bits(["q"]):
typedef struct packed {
+ logic [${r.get_field_flat(0).get_n_bits()-1}:0] q;
+ % if r.get_field_flat(0).hwqe:
+ logic qe;
+ % endif
+ % if r.get_field_flat(0).hwre:
+ logic re;
+ % endif
+} ${block.name + "_reg2hw_" + r.name + "_mreg_t"};
+% endif
+% endfor
+
+/////////////////////////////////////////////////////////////////////
+// Register to internal design logic
+/////////////////////////////////////////////////////////////////////
<%
-# directly mirrors below (avoided optimizations to ensure a match)
-# have to do as a python block to avoid inserting blank lines
-# compute number of bits because packed structs are declared msb first
-packbit = 0
-for r in block.regs:
- if len(r.fields) == 1 and r.fields[0].hwaccess in [HwAccess.HRW, HwAccess.HRO]:
- packbit += 1 + r.fields[0].msb - r.fields[0].lsb
- if r.fields[0].hwqe:
- packbit += 1
- if r.fields[0].hwre:
- packbit += 1
- elif len(r.fields) >= 2 and len([f for f in r.fields if f.hwaccess in [HwAccess.HRW, HwAccess.HRO]]):
- for f in r.fields:
- if f.hwaccess in [HwAccess.HRW, HwAccess.HRO]:
- if f.msb != f.lsb:
- packbit += 1 + f.msb - f.lsb
- else:
- packbit += 1
- if r.hwqe:
- packbit += 1
- if r.fields[0].hwre:
- packbit += 1
-nbits = packbit - 1
+nbits = block.get_n_bits(["q","qe","re"]) - 1
packbit = 0
%>
+typedef struct packed {
% for r in block.regs:
- % if len(r.fields) == 1 and r.fields[0].hwaccess in [HwAccess.HRW, HwAccess.HRO]:
+ ######################## multiregister ###########################
+ % if r.is_multi_reg() and r.get_n_bits(["q"]):
+ <%
+ dims = r.get_nested_dims()
+ array_dims = ""
+ for d in dims[1:]:
+ array_dims += "[%d:0]" % (d-1)
+ %>${block.name + "_reg2hw_" + r.name + "_mreg_t"} ${array_dims} ${r.name}; // [${nbits - packbit}:${nbits - (packbit + r.get_n_bits(["q", "qe", "re"]) - 1)}]<% packbit += r.get_n_bits(["q", "qe", "re"]) %>
+ ######################## register with single field ###########################
+ % elif len(r.fields) == 1 and r.get_n_bits(["q"]):
## Only one field, should use register name as it is
struct packed {
- logic [${r.fields[0].msb - r.fields[0].lsb}:0] q; // [${nbits - packbit}:${nbits - (packbit + r.fields[0].msb - r.fields[0].lsb)}]<% packbit += 1 + r.fields[0].msb - r.fields[0].lsb %>
+ logic [${r.fields[0].get_n_bits()-1}:0] q; // [${nbits - packbit}:${nbits - (packbit + r.fields[0].get_n_bits() - 1)}]<% packbit += r.fields[0].get_n_bits() %>
% if r.fields[0].hwqe:
logic qe; // [${nbits - packbit}]<% packbit += 1 %>
% endif
@@ -57,21 +63,22 @@
logic re; // [${nbits - packbit}]<% packbit += 1 %>
% endif
} ${r.name};
- % elif len(r.fields) >= 2 and len([f for f in r.fields if f.hwaccess in [HwAccess.HRW, HwAccess.HRO]]):
+ ######################## register with multiple fields ###########################
+ % elif len(r.fields) >= 2 and r.get_n_bits(["q"]):
struct packed {
% for f in r.fields:
% if f.hwaccess in [HwAccess.HRW, HwAccess.HRO]:
struct packed {
## reg2hw signal based on HW type and virtual?
- % if f.msb != f.lsb:
- logic [${f.msb - f.lsb}:0] q; // [${nbits - packbit}:${nbits - (packbit + f.msb - f.lsb)}]<% packbit += 1 + f.msb - f.lsb %>
+ % if f.get_n_bits() > 1:
+ logic [${f.get_n_bits()-1}:0] q; // [${nbits - packbit}:${nbits - (packbit + f.get_n_bits() - 1)}]<% packbit += f.get_n_bits() %>
% else:
logic q; // [${nbits - packbit}]<% packbit += 1 %>
% endif
% if f.hwqe:
logic qe; // [${nbits - packbit}]<% packbit += 1 %>
% endif
- % if r.fields[0].hwre:
+ % if f.hwre:
logic re; // [${nbits - packbit}]<% packbit += 1 %>
% endif
} ${f.name};
@@ -82,47 +89,60 @@
% endfor
} ${block.name}_reg2hw_t;
-// Internal design logic to register
+/////////////////////////////////////////////////////////////////////
+// Typedefs for multiregs
+/////////////////////////////////////////////////////////////////////
+
+% for r in block.regs:
+% if r.is_multi_reg() and r.get_n_bits(["d"]):
typedef struct packed {
+ logic [${r.get_field_flat(0).get_n_bits()-1}:0] d;
+ % if not r.get_reg_flat(0).hwext:
+ logic de;
+ % endif
+} ${block.name + "_hw2reg_" + r.name + "_mreg_t"};
+% endif
+% endfor
+
+/////////////////////////////////////////////////////////////////////
+// Internal design logic to register
+/////////////////////////////////////////////////////////////////////
<%
-packbit = 0
-for r in block.regs:
- if len(r.fields) == 1 and r.fields[0].hwaccess in [HwAccess.HRW, HwAccess.HWO]:
- packbit += 1 + r.fields[0].msb - r.fields[0].lsb
- if r.hwext == 0:
- packbit += 1
- elif len(r.fields) >= 2 and len([f for f in r.fields if f.hwaccess in [HwAccess.HRW, HwAccess.HWO]]):
- for f in r.fields:
- if f.hwaccess in [HwAccess.HRW, HwAccess.HWO]:
- if f.msb != f.lsb:
- packbit += 1 + f.msb - f.lsb
- else:
- packbit += 1
- if r.hwext == 0:
- packbit += 1
-nbits = packbit - 1
+nbits = block.get_n_bits(["d","de"]) - 1
packbit = 0
%>
+typedef struct packed {
% for r in block.regs:
- % if len(r.fields) == 1 and r.fields[0].hwaccess in [HwAccess.HRW, HwAccess.HWO]:
+ ######################## multiregister ###########################
+ % if r.is_multi_reg() and r.get_n_bits(["d"]):
+ <%
+ dims = r.get_nested_dims()
+ array_dims = ""
+ for d in dims[1:]:
+ array_dims += "[%d:0]" % (d-1)
+ %>${block.name + "_hw2reg_" + r.name + "_mreg_t"} ${array_dims} ${r.name}; // [${nbits - packbit}:${nbits - (packbit + r.get_n_bits(["d", "de"]) - 1)}]<% packbit += r.get_n_bits(["d", "de"]) %>
+ ######################## register with single field ###########################
+ % elif len(r.fields) == 1 and r.get_n_bits(["d"]):
## Only one field, should use register name as it is
struct packed {
- logic [${r.fields[0].msb - r.fields[0].lsb}:0] d; // [${nbits - packbit}:${nbits - (packbit + r.fields[0].msb - r.fields[0].lsb)}]<% packbit += 1 + r.fields[0].msb - r.fields[0].lsb %>
+ logic [${r.fields[0].get_n_bits("d")-1}:0] d; // [${nbits - packbit}:${nbits - (packbit + r.fields[0].get_n_bits("d") - 1)}]<% packbit += r.fields[0].get_n_bits("d") %>
% if r.hwext == 0:
logic de; // [${nbits - packbit}]<% packbit += 1 %>
% endif
} ${r.name};
- % elif len(r.fields) >= 2 and len([f for f in r.fields if f.hwaccess in [HwAccess.HRW, HwAccess.HWO]]):
+ ######################## register with multiple fields ###########################
+ % elif len(r.fields) >= 2 and r.get_n_bits(["d"]):
struct packed {
% for f in r.fields:
% if f.hwaccess in [HwAccess.HRW, HwAccess.HWO]:
struct packed {
- % if f.msb != f.lsb:
- logic [${f.msb - f.lsb}:0] d; // [${nbits - packbit}:${nbits - (packbit + f.msb - f.lsb)}]<% packbit += 1 + f.msb - f.lsb %>
+ ## reg2hw signal based on HW type and virtual?
+ % if f.get_n_bits("d") > 1:
+ logic [${f.get_n_bits("d")-1}:0] d; // [${nbits - packbit}:${nbits - (packbit + f.get_n_bits("d") - 1)}]<% packbit += f.get_n_bits("d") %>
% else:
- logic d; // [${nbits - packbit}]<% packbit += 1 %>
+ logic d; // [${nbits - packbit}]<% packbit += 1 %>
% endif
- % if r.hwext == 0:
+ % if not r.hwext:
logic de; // [${nbits - packbit}]<% packbit += 1 %>
% endif
} ${f.name};
@@ -134,7 +154,7 @@
} ${block.name}_hw2reg_t;
// Register Address
-% for r in block.regs:
+% for r in block.get_regs_flat():
parameter ${block.name.upper()}_${r.name.upper()}_OFFSET = ${block.addr_width}'h ${"%x" % r.offset};
% endfor
@@ -148,14 +168,14 @@
// Register Index
typedef enum int {
-% for r in block.regs:
+% for r in block.get_regs_flat():
${block.name.upper()}_${r.name.upper()}${"" if loop.last else ","}
% endfor
} ${block.name}_id_e;
// Register width information to check illegal writes
- localparam logic [3:0] ${block.name.upper()}_PERMIT [${len(block.regs)}] = '{
-% for i,r in enumerate(block.regs):
+ localparam logic [3:0] ${block.name.upper()}_PERMIT [${block.get_n_regs_flat()}] = '{
+% for i,r in enumerate(block.get_regs_flat()):
<% index_str = "{}".format(i).rjust(max_regs_char) %>\
% if r.width > 16:
4'b 1111${" " if i == num_regs-1 else ","} // index[${index_str}] ${block.name.upper()}_${r.name.upper()}
diff --git a/util/reggen/reg_top.tpl.sv b/util/reggen/reg_top.tpl.sv
index bc26c68..0aa529a 100644
--- a/util/reggen/reg_top.tpl.sv
+++ b/util/reggen/reg_top.tpl.sv
@@ -7,11 +7,10 @@
num_wins = len(block.wins)
num_wins_width = ((num_wins+1).bit_length()) - 1
num_dsp = num_wins + 1
- num_regs = len(block.regs)
- max_regs_char = len("{}".format(num_regs-1))
params = [p for p in block.params if p["local"] == "false"]
+ max_regs_char = len("{}".format(block.get_n_regs_flat()-1))
+ regs_flat = block.get_regs_flat()
%>
-
module ${block.name}_reg_top ${print_param(params)}(
input clk_i,
input rst_ni,
@@ -138,7 +137,7 @@
// Define SW related signals
// Format: <reg>_<field>_{wd|we|qs}
// or <reg>_{wd|we|qs} if field == 1 or 0
- % for r in block.regs:
+ % for r in regs_flat:
% if len(r.fields) == 1:
<%
msb = r.fields[0].msb
@@ -169,41 +168,96 @@
// Register instances
% for r in block.regs:
- // R[${r.name}]: V(${str(r.hwext)})
- % if len(r.fields) == 1:
+ ######################## multiregister ###########################
+ % if r.is_multi_reg():
<%
- f = r.fields[0]
- finst_name = r.name
- fsig_name = r.name
- msb = f.msb
- lsb = f.lsb
- swaccess = f.swaccess
- swrdaccess = f.swrdaccess
- swwraccess = f.swwraccess
- hwaccess = f.hwaccess
- hwqe = f.hwqe
- hwre = f.hwre
- hwext = r.hwext
- resval = f.resval
- regwen = r.regwen
+ mreg_flat = r.get_regs_flat()
+ k = 0
+%>
+ % for sr in mreg_flat:
+ // Subregister ${k} of Multireg ${r.name}
+ // R[${sr.name}]: V(${str(sr.hwext)})
+ % if len(sr.fields) == 1:
+<%
+ f = sr.fields[0]
+ finst_name = sr.name
+ fsig_name = r.name + "[%d]" % k
+ msb = f.msb
+ lsb = f.lsb
+ swaccess = f.swaccess
+ swrdaccess = f.swrdaccess
+ swwraccess = f.swwraccess
+ hwaccess = f.hwaccess
+ hwqe = f.hwqe
+ hwre = f.hwre
+ hwext = sr.hwext
+ resval = f.resval
+ regwen = sr.regwen
+ k = k + 1
%>
${finst_gen(finst_name, fsig_name, msb, lsb, swaccess, swrdaccess, swwraccess, hwaccess, hwqe, hwre, hwext, resval, regwen)}
+ % else:
+ % for f in sr.fields:
+<%
+ finst_name = sr.name + "_" + f.name
+ fsig_name = r.name + "[%d]" % k
+ msb = f.msb
+ lsb = f.lsb
+ swaccess = f.swaccess
+ swrdaccess = f.swrdaccess
+ swwraccess = f.swwraccess
+ hwaccess = f.hwaccess
+ hwqe = f.hwqe
+ hwre = f.hwre
+ hwext = sr.hwext
+ resval = f.resval
+ regwen = sr.regwen
+ k = k + 1
+%>
+ // F[${f.name}]: ${f.msb}:${f.lsb}
+${finst_gen(finst_name, fsig_name, msb, lsb, swaccess, swrdaccess, swwraccess, hwaccess, hwqe, hwre, hwext, resval, regwen)}
+ % endfor
+ % endif
+ ## for: mreg_flat
+ % endfor
+######################## register with single field ###########################
+ % elif len(r.fields) == 1:
+ // R[${r.name}]: V(${str(r.hwext)})
+<%
+ f = r.fields[0]
+ finst_name = r.name
+ fsig_name = r.name
+ msb = f.msb
+ lsb = f.lsb
+ swaccess = f.swaccess
+ swrdaccess = f.swrdaccess
+ swwraccess = f.swwraccess
+ hwaccess = f.hwaccess
+ hwqe = f.hwqe
+ hwre = f.hwre
+ hwext = r.hwext
+ resval = f.resval
+ regwen = r.regwen
+%>
+${finst_gen(finst_name, fsig_name, msb, lsb, swaccess, swrdaccess, swwraccess, hwaccess, hwqe, hwre, hwext, resval, regwen)}
+######################## register with multiple fields ###########################
% else:
+ // R[${r.name}]: V(${str(r.hwext)})
% for f in r.fields:
<%
- finst_name = r.name + "_" + f.name
- fsig_name = r.name + "." + f.name
- msb = f.msb
- lsb = f.lsb
- swaccess = f.swaccess
- swrdaccess = f.swrdaccess
- swwraccess = f.swwraccess
- hwaccess = f.hwaccess
- hwqe = f.hwqe
- hwre = f.hwre
- hwext = r.hwext
- resval = f.resval
- regwen = r.regwen
+ finst_name = r.name + "_" + f.name
+ fsig_name = r.name + "." + f.name
+ msb = f.msb
+ lsb = f.lsb
+ swaccess = f.swaccess
+ swrdaccess = f.swrdaccess
+ swwraccess = f.swwraccess
+ hwaccess = f.hwaccess
+ hwqe = f.hwqe
+ hwre = f.hwre
+ hwext = r.hwext
+ resval = f.resval
+ regwen = r.regwen
%>
// F[${f.name}]: ${f.msb}:${f.lsb}
${finst_gen(finst_name, fsig_name, msb, lsb, swaccess, swrdaccess, swwraccess, hwaccess, hwqe, hwre, hwext, resval, regwen)}
@@ -213,10 +267,11 @@
## for: block.regs
% endfor
- logic [${len(block.regs)-1}:0] addr_hit;
+
+ logic [${len(regs_flat)-1}:0] addr_hit;
always_comb begin
addr_hit = '0;
- % for i,r in enumerate(block.regs):
+ % for i,r in enumerate(regs_flat):
addr_hit[${"{}".format(i).rjust(max_regs_char)}] = (reg_addr == ${block.name.upper()}_${r.name.upper()}_OFFSET);
% endfor
end
@@ -226,12 +281,12 @@
// Check sub-word write is permitted
always_comb begin
wr_err = 1'b0;
- % for i,r in enumerate(block.regs):
+ % for i,r in enumerate(regs_flat):
<% index_str = "{}".format(i).rjust(max_regs_char) %>\
if (addr_hit[${index_str}] && reg_we && (${block.name.upper()}_PERMIT[${index_str}] != (${block.name.upper()}_PERMIT[${index_str}] & reg_be))) wr_err = 1'b1 ;
% endfor
end
- % for i, r in enumerate(block.regs):
+ % for i, r in enumerate(regs_flat):
% if len(r.fields) == 1:
<%
f = r.fields[0]
@@ -264,7 +319,7 @@
always_comb begin
reg_rdata_next = '0;
unique case (1'b1)
- % for i, r in enumerate(block.regs):
+ % for i, r in enumerate(regs_flat):
% if len(r.fields) == 1:
<%
f = r.fields[0]
diff --git a/util/reggen/uvm_reg.tpl.sv b/util/reggen/uvm_reg.tpl.sv
index 249bdb0..40f5f22 100644
--- a/util/reggen/uvm_reg.tpl.sv
+++ b/util/reggen/uvm_reg.tpl.sv
@@ -5,13 +5,14 @@
// UVM Registers auto-generated by `reggen` containing data structure
// Do Not Edit directly
<% from reggen import (gen_dv)
+regs_flat = block.get_regs_flat()
%>\
##// [PY-COMMENT]: function to generate typedefs recursively for blocks
<%def name="typedefs(block)">\
% for b in block.blocks:
${typedefs(b)}
% endfor
-% for r in block.regs:
+% for r in regs_flat:
typedef class ${gen_dv.rcname(block, r)};
% endfor
% for w in block.wins:
@@ -26,7 +27,7 @@
% endfor
// Block: ${block.name}
-% for r in block.regs:
+% for r in regs_flat:
<%
reg_width = block.width
%>\
@@ -108,10 +109,10 @@
% for b in block.blocks:
rand ${gen_dv.bcname(b)} ${b.name};
% endfor
-% if block.regs:
+% if regs_flat:
// registers
% endif
-% for r in block.regs:
+% for r in regs_flat:
rand ${gen_dv.rcname(block, r)} ${r.name};
% endfor
% if block.wins:
@@ -145,11 +146,11 @@
default_map.add_submap(.child_map(${b.name}.default_map),
.offset(base_addr + ${gen_dv.sv_base_addr(b)}));
% endfor
-% if block.regs:
+% if regs_flat:
// create registers
% endif
-% for r in block.regs:
+% for r in regs_flat:
<%
reg_name = r.name
reg_right = r.dvrights