[reggen] Add mubi support into hjson
- This primarily ensures reset values are consistent
- Fixes #8521
Signed-off-by: Timothy Chen <timothytim@google.com>
[reggen] Report error when bit fields are re-used
- Fixes #7566
Signed-off-by: Timothy Chen <timothytim@google.com>
Update used bits check
Signed-off-by: Timothy Chen <timothytim@google.com>
[reggen] Relocate mubi script
- Add to `util/design` area so that it can be directly referenced
by fields.py
Signed-off-by: Timothy Chen <timothytim@google.com>
address comments
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/entropy_src/data/entropy_src.hjson b/hw/ip/entropy_src/data/entropy_src.hjson
index 03fc857..ba0df93 100644
--- a/hw/ip/entropy_src/data/entropy_src.hjson
+++ b/hw/ip/entropy_src/data/entropy_src.hjson
@@ -135,49 +135,55 @@
fields: [
{ bits: "3:0",
name: "ENABLE",
+ mubi: true,
desc: '''
Setting this field to 0xA will enable the ENTROPY_SRC module.
'''
- resval: "0x5"
+ resval: false,
},
{ bits: "7:4",
name: "ENTROPY_DATA_REG_ENABLE",
+ mubi: true,
desc: '''
Setting this field to 0xA will enable reading entropy values from the
ENTROPY_DATA register. This function also requires that the efuse_es_sw_reg_en
input is set.
'''
- resval: "0x5"
+ resval: "false"
},
{ bits: "11:8",
name: "LFSR_ENABLE",
+ mubi: true,
desc: '''
Setting this field to 0xA will enable the ENTROPY_SRC LFSR mode.
'''
- resval: "0x5"
+ resval: false
},
{ bits: "15:12",
name: "BOOT_BYPASS_DISABLE",
+ mubi: true,
desc: '''
Setting this field to 0xA will disables the initial generation of non-FIPS entropy.
'''
- resval: "0x5"
+ resval: false
},
{ bits: "19:16",
name: "HEALTH_TEST_CLR",
+ mubi: true,
desc: '''
Setting this field to 0xA will clear all registers related to the
health test operations.
'''
- resval: "0x5"
+ resval: false
},
{ bits: "23:20",
name: "RNG_BIT_ENABLE",
+ mubi: true,
desc: '''
Setting this field to 0xA enables the single RNG bit mode, where only
one bit is sampled.
'''
- resval: "0x5"
+ resval: false
},
{ bits: "25:24",
name: "RNG_BIT_SEL",
@@ -218,21 +224,23 @@
fields: [
{ bits: "3:0",
name: "ES_ROUTE",
+ mubi: true,
desc: '''
Setting this field to 0xA routes the generated entropy value to the ENTROPY_DATA
register to be read by firmware. When this field is 0x5, the generated
entropy will be forwarded out of this module to the hardware interface.
'''
- resval: "0x5"
+ resval: false
},
{ bits: "7:4",
name: "ES_TYPE",
+ mubi: true,
desc: '''
Setting this field to 0xA will bypass the conditioning logic and bring raw entropy
data to the ENTROPY_DATA register. When 0x5, FIPS compliant entropy
will be brought the ENTROPY_DATA register, after being conditioned.
'''
- resval: "0x5"
+ resval: false
},
]
},
diff --git a/hw/ip/prim/data/prim_mubi.core.tpl b/util/design/data/prim_mubi.core.tpl
similarity index 100%
rename from hw/ip/prim/data/prim_mubi.core.tpl
rename to util/design/data/prim_mubi.core.tpl
diff --git a/hw/ip/prim/data/prim_mubi_dec.sv.tpl b/util/design/data/prim_mubi_dec.sv.tpl
similarity index 100%
rename from hw/ip/prim/data/prim_mubi_dec.sv.tpl
rename to util/design/data/prim_mubi_dec.sv.tpl
diff --git a/hw/ip/prim/data/prim_mubi_pkg.sv.tpl b/util/design/data/prim_mubi_pkg.sv.tpl
similarity index 93%
rename from hw/ip/prim/data/prim_mubi_pkg.sv.tpl
rename to util/design/data/prim_mubi_pkg.sv.tpl
index 5abc940..34dbd5c 100644
--- a/hw/ip/prim/data/prim_mubi_pkg.sv.tpl
+++ b/util/design/data/prim_mubi_pkg.sv.tpl
@@ -12,14 +12,12 @@
package prim_mubi_pkg;
-% for n in range(1, n_max_nibbles + 1):
<%
- nbits = n * 4
- true_val = ''
- false_val = ''
- for k in range(1,n+1):
- true_val = ('A' if (k % 2) else '5') + true_val
- false_val = ('5' if (k % 2) else 'A') + false_val
+import prim_mubi as prim_mubi
+%>\
+% for n in range(1, N_MAX_NIBBLES + 1):
+<%
+ nbits = n * 4
%>\
//////////////////////////////////////////////
// ${nbits} Bit Multibit Type and Functions //
@@ -27,8 +25,8 @@
parameter int MuBi${nbits}Width = ${nbits};
typedef enum logic [MuBi${nbits}Width-1:0] {
- MuBi${nbits}True = ${nbits}'h${true_val}, // enabled
- MuBi${nbits}False = ${nbits}'h${false_val} // disabled
+ MuBi${nbits}True = ${nbits}'h${prim_mubi.mubi_value(True, nbits)}, // enabled
+ MuBi${nbits}False = ${nbits}'h${prim_mubi.mubi_value(False, nbits)} // disabled
} mubi${nbits}_e;
// make a typedef such that this can be used as an intersignal type as well
diff --git a/hw/ip/prim/data/prim_mubi_sender.sv.tpl b/util/design/data/prim_mubi_sender.sv.tpl
similarity index 100%
rename from hw/ip/prim/data/prim_mubi_sender.sv.tpl
rename to util/design/data/prim_mubi_sender.sv.tpl
diff --git a/hw/ip/prim/data/prim_mubi_sync.sv.tpl b/util/design/data/prim_mubi_sync.sv.tpl
similarity index 100%
rename from hw/ip/prim/data/prim_mubi_sync.sv.tpl
rename to util/design/data/prim_mubi_sync.sv.tpl
diff --git a/util/design/prim_mubi.py b/util/design/prim_mubi.py
new file mode 100755
index 0000000..f73ce54
--- /dev/null
+++ b/util/design/prim_mubi.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+r"""Converts mubi mako templates
+"""
+from mako.template import Template
+
+MUBI_PKG_TPL_PATH = "util/design/data/prim_mubi_pkg.sv.tpl"
+MUBI_CORE_TPL_PATH = "util/design/data/prim_mubi.core.tpl"
+MUBI_SENDER_TPL_PATH = "util/design/data/prim_mubi_sender.sv.tpl"
+MUBI_SYNC_TPL_PATH = "util/design/data/prim_mubi_sync.sv.tpl"
+MUBI_DEC_TPL_PATH = "util/design/data/prim_mubi_dec.sv.tpl"
+
+MUBI_PKG_OUT_PATH = "hw/ip/prim/rtl/prim_mubi_pkg.sv"
+MUBI_CORE_OUT_PATH = "hw/ip/prim/prim_mubi.core"
+MUBI_SENDER_OUT_PATH = "hw/ip/prim/rtl/prim_mubi{}_sender.sv"
+MUBI_SYNC_OUT_PATH = "hw/ip/prim/rtl/prim_mubi{}_sync.sv"
+MUBI_DEC_OUT_PATH = "hw/ip/prim/rtl/prim_mubi{}_dec.sv"
+
+N_MAX_NIBBLES = 4
+
+
+def is_width_valid(width):
+ return width % 4 == 0
+
+
+def mubi_value(sel: bool, width: int):
+
+ if is_width_valid(width):
+ nibble = int(width / 4)
+ else:
+ raise ValueError(f'mubi does not support width of {width}')
+
+ true_val = ''
+ false_val = ''
+
+ for k in range(1, nibble + 1):
+ true_val = ('A' if (k % 2) else '5') + true_val
+ false_val = ('5' if (k % 2) else 'A') + false_val
+
+ return true_val if sel else false_val
+
+
+def main():
+
+ tpls = [
+ (MUBI_PKG_TPL_PATH, MUBI_PKG_OUT_PATH),
+ (MUBI_CORE_TPL_PATH, MUBI_CORE_OUT_PATH),
+ ]
+ for tpl, out in tpls:
+ with open(tpl) as inf:
+ reg_tpl = Template(inf.read())
+ with open(out, 'w') as outf:
+ outf.write(reg_tpl.render(n_max_nibbles=N_MAX_NIBBLES))
+
+ tpls = [
+ (MUBI_SENDER_TPL_PATH, MUBI_SENDER_OUT_PATH),
+ (MUBI_SYNC_TPL_PATH, MUBI_SYNC_OUT_PATH),
+ (MUBI_DEC_TPL_PATH, MUBI_DEC_OUT_PATH)
+ ]
+ for tpl, out in tpls:
+ with open(tpl) as inf:
+ reg_tpl = Template(inf.read())
+ for n in range(1, N_MAX_NIBBLES + 1):
+ n_bits = n * 4
+ with open(out.format(n_bits), 'w') as outf:
+ outf.write(reg_tpl.render(n_bits=n_bits))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/util/reggen/field.py b/util/reggen/field.py
index 2f9d0b9..0ce5f37 100644
--- a/util/reggen/field.py
+++ b/util/reggen/field.py
@@ -7,9 +7,11 @@
from .access import SWAccess, HWAccess
from .bits import Bits
from .enum_entry import EnumEntry
-from .lib import (check_keys, check_str, check_name,
+from .lib import (check_keys, check_str, check_name, check_bool,
check_list, check_str_list, check_xint)
from .params import ReggenParams
+from design.prim_mubi import is_width_valid, mubi_value #type: ignore
+
REQUIRED_FIELDS = {
'bits': ['b', "bit or bit range (msb:lsb)"]
@@ -39,6 +41,10 @@
'tags': [
's',
"tags for the field, followed by the format 'tag_name:item1:item2...'"
+ ],
+ 'mubi': [
+ 'b',
+ "boolean flag for whether the field is a multi-bit type"
]
}
@@ -110,14 +116,29 @@
else:
hwaccess = default_hwaccess
+ raw_mubi = rd.get('mubi', False)
+ is_mubi = check_bool(raw_mubi, 'mubi field for {}'.format(where))
+
# Currently internal shadow registers do not support hw write type
if not hwext and shadowed and hwaccess.allows_write():
raise ValueError('Internal Shadow registers do not currently support '
'hardware write')
bits = Bits.from_raw(where, reg_width, params, rd['bits'])
-
raw_resval = rd.get('resval')
+ if is_mubi:
+ # When mubi type, the resval supplied is a boolean which is converted
+ # to a mubi value
+ chk_resval = check_bool(raw_resval, 'resval field for {}'.format(where))
+
+ # Check mubi width is supported
+ if not is_width_valid(bits.width()):
+ raise ValueError(f'mubi field for {name} does not support width '
+ f'of {bits.width()}')
+
+ # Get actual integer value based on mubi selection
+ raw_resval = mubi_value(chk_resval, bits.width())
+
if raw_resval is None:
# The field doesn't define a reset value. Use bits from reg_resval
# if it's defined, otherwise None (which means "x").
diff --git a/util/reggen/register.py b/util/reggen/register.py
index 2692c3d..a9205b9 100644
--- a/util/reggen/register.py
+++ b/util/reggen/register.py
@@ -295,18 +295,31 @@
'fields for {} register'.format(name))
if not raw_fields:
raise ValueError('Register {} has no fields.'.format(name))
- fields = [Field.from_raw(name,
- idx,
- len(raw_fields),
- swaccess,
- hwaccess,
- resval,
- reg_width,
- params,
- hwext,
- shadowed,
- rf)
- for idx, rf in enumerate(raw_fields)]
+
+ fields = []
+ used_bits = 0
+ for idx, rf in enumerate(raw_fields):
+
+ field = (Field.from_raw(name,
+ idx,
+ len(raw_fields),
+ swaccess,
+ hwaccess,
+ resval,
+ reg_width,
+ params,
+ hwext,
+ shadowed,
+ rf))
+
+ overlap_bits = used_bits & field.bits.bitmask()
+ if overlap_bits:
+ raise ValueError(f'Field {field.name} uses bits '
+ f'{overlap_bits:#x} that appear in other '
+ f'fields.')
+
+ used_bits |= field.bits.bitmask()
+ fields.append(field)
raw_uea = rd.get('update_err_alert')
if raw_uea is None: