[reggen] Add support for non-homogenous multiregs
diff --git a/util/reggen/data.py b/util/reggen/data.py
index 4ad732d..cb30b89 100644
--- a/util/reggen/data.py
+++ b/util/reggen/data.py
@@ -4,6 +4,14 @@
from .field_enums import HwAccess, SwAccess, SwRdAccess, SwWrAccess
+# helper funtion that strips trailing number from name
+# TODO: this is a workaround, should solve this in validate.py
+def _get_basename(name):
+ outname = ""
+ for (k, c) in enumerate(name[::-1]):
+ if not str.isdigit(c):
+ return name[0:len(name)-k]
+ return ""
class Field():
"""Field in a register.
@@ -54,6 +62,8 @@
def get_fields_flat(self):
return [self]
+ def get_basename(self):
+ return _get_basename(self.name)
class Reg():
name = ""
@@ -66,6 +76,7 @@
regwen = ""
fields = []
width = 0 # indicate register size
+ ishomog = 0
def __init__(self, name=""):
self.name = name
@@ -78,6 +89,7 @@
self.regwen = ""
self.fields = []
self.width = 0
+ self.ishomog = 0
def is_multi_reg(self):
"""Returns true if this is a multireg"""
@@ -137,10 +149,14 @@
"""Recursively get dimensions of nested registers (outputs a list)"""
# return length of flattened field array if this is a regular register,
# or if this is the last multiregister level in a nested multiregister
- if not isinstance(self, MultiReg) or \
- isinstance(self, MultiReg) and \
- not isinstance(self.fields[0], MultiReg):
+ if not isinstance(self, MultiReg):
dims = [len(self.get_fields_flat())]
+ if isinstance(self, MultiReg) and \
+ not isinstance(self.fields[0], MultiReg):
+ if self.ishomog:
+ dims = [len(self.get_fields_flat())]
+ else:
+ dims = [len(self.fields)]
else:
# nested multiregister case
dims = [len(self.fields)] + self.fields[0].get_nested_dims()
@@ -155,6 +171,9 @@
params += self.fields[0].get_nested_params()
return params
+ def get_basename(self):
+ return _get_basename(self.name)
+
class MultiReg(Reg):
param = ""
@@ -220,3 +239,11 @@
def get_n_regs_flat(self):
return len(self.get_regs_flat())
+
+ def contains_multiregs(self):
+ """Returns true if there are multiregs in this block
+ """
+ for r in self.regs:
+ if isinstance(r, MultiReg):
+ return True
+ return False
diff --git a/util/reggen/gen_rtl.py b/util/reggen/gen_rtl.py
index be60626..3aaa949 100644
--- a/util/reggen/gen_rtl.py
+++ b/util/reggen/gen_rtl.py
@@ -70,6 +70,8 @@
# since this is a multireg, the list of fields can
# contain regs or multiregs
reg.fields = regs
+ # a homogenous multireg contains only one single field that is replicated
+ reg.ishomog = len(obj['multireg']['fields']) == 1
# 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
diff --git a/util/reggen/reg_pkg.tpl.sv b/util/reggen/reg_pkg.tpl.sv
index ed0bd28..98877f2 100644
--- a/util/reggen/reg_pkg.tpl.sv
+++ b/util/reggen/reg_pkg.tpl.sv
@@ -17,11 +17,14 @@
localparam ${param["type"]} ${param["name"]} = ${param["default"]};
% endfor
+% if block.contains_multiregs():
/////////////////////////////////////////////////////////////////////
// Typedefs for multiregs
/////////////////////////////////////////////////////////////////////
+
% for r in block.regs:
-% if r.is_multi_reg() and r.get_n_bits(["q"]):
+ ## in this case we have a homogeneous multireg, with only one replicated field
+ % if r.is_multi_reg() and r.get_n_bits(["q"]) and r.ishomog:
typedef struct packed {
logic [${r.get_field_flat(0).get_n_bits()-1}:0] q;
% if r.get_field_flat(0).hwqe:
@@ -31,9 +34,49 @@
logic re;
% endif
} ${block.name + "_reg2hw_" + r.name + "_mreg_t"};
-% endif
+ ## in this case we have an inhomogeneous multireg, with several different fields per register
+ % elif r.is_multi_reg() and r.get_n_bits(["q"]) and not r.ishomog:
+typedef struct packed {
+ % for f in r.get_reg_flat(0).fields:
+ struct packed {
+ logic [${f.get_n_bits()-1}:0] q;
+ % if f.hwqe:
+ logic qe;
+ % endif
+ % if f.hwre:
+ logic re;
+ % endif
+ } ${f.get_basename()};
+ %endfor
+} ${block.name + "_reg2hw_" + r.name + "_mreg_t"};
+ %endif
% endfor
+% for r in block.regs:
+ ## in this case we have a homogeneous multireg, with only one replicated field
+ % if r.is_multi_reg() and r.get_n_bits(["d"]) and r.ishomog:
+typedef struct packed {
+ logic [${r.get_field_flat(0).get_n_bits(["d"])-1}:0] d;
+ % if not r.get_reg_flat(0).hwext:
+ logic de;
+ % endif
+} ${block.name + "_hw2reg_" + r.name + "_mreg_t"};
+ ## in this case we have an inhomogeneous multireg, with several different fields per register
+ % elif r.is_multi_reg() and r.get_n_bits(["d"]) and not r.ishomog:
+typedef struct packed {
+ % for f in r.get_reg_flat(0).fields:
+ struct packed {
+ logic [${f.get_n_bits(["d"])-1}:0] d;
+ % if not r.hwext:
+ logic de;
+ % endif
+ } ${f.get_basename()};
+ %endfor
+} ${block.name + "_hw2reg_" + r.name + "_mreg_t"};
+ % endif
+% endfor
+
+% endif
/////////////////////////////////////////////////////////////////////
// Register to internal design logic
/////////////////////////////////////////////////////////////////////
@@ -89,21 +132,6 @@
} ${block.name}_reg2hw_t;
/////////////////////////////////////////////////////////////////////
-// 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
/////////////////////////////////////////////////////////////////////
<%
diff --git a/util/reggen/reg_top.tpl.sv b/util/reggen/reg_top.tpl.sv
index 0aa529a..7531b51 100644
--- a/util/reggen/reg_top.tpl.sv
+++ b/util/reggen/reg_top.tpl.sv
@@ -200,7 +200,11 @@
% for f in sr.fields:
<%
finst_name = sr.name + "_" + f.name
- fsig_name = r.name + "[%d]" % k
+ if r.ishomog:
+ fsig_name = r.name + "[%d]" % k
+ k = k + 1
+ else:
+ fsig_name = r.name + "[%d]" % k + "." + f.get_basename()
msb = f.msb
lsb = f.lsb
swaccess = f.swaccess
@@ -212,11 +216,14 @@
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
+<%
+ if not r.ishomog:
+ k += 1
+%>
% endif
## for: mreg_flat
% endfor