aboutsummaryrefslogtreecommitdiffstats
path: root/mpm
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2023-06-05 15:44:18 +0200
committerAki Tomita <121511582+atomita-ni@users.noreply.github.com>2023-06-06 16:11:36 -0500
commit50f7d064ea8c6872826ccdf9dc09032539c0e1ca (patch)
tree92e05765e8c01ab4d0b3706a39287af972dad149 /mpm
parentci: Default to internal fileserver for FPGA images (diff)
downloaduhd-50f7d064ea8c6872826ccdf9dc09032539c0e1ca.tar.xz
uhd-50f7d064ea8c6872826ccdf9dc09032539c0e1ca.zip
mpm: x4xx: Enable DBs to have updateable_components
This adds an updateable_components overridable dictionary into the daughterboards base class. On X410, because some of the FPGA compatibility stems from DB-specific components, they are moved into class ZBX.
Diffstat (limited to 'mpm')
-rw-r--r--mpm/python/usrp_mpm/components.py53
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/base.py4
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/zbx.py16
-rw-r--r--mpm/python/usrp_mpm/periph_manager/x4xx.py9
4 files changed, 60 insertions, 22 deletions
diff --git a/mpm/python/usrp_mpm/components.py b/mpm/python/usrp_mpm/components.py
index b79c1d9cb..546ea705a 100644
--- a/mpm/python/usrp_mpm/components.py
+++ b/mpm/python/usrp_mpm/components.py
@@ -13,7 +13,7 @@ import subprocess
from usrp_mpm.rpc_server import no_rpc
-class ZynqComponents(object):
+class ZynqComponents:
"""
Mixin class that update Zynq FPGA and devicetree components.
@@ -82,6 +82,31 @@ class ZynqComponents(object):
version_info[component][version_type] = version
return version_info
+ def _merge_updateable_components(self):
+ """
+ Combines updateable_components from MB and all DBs and returns the
+ merged result.
+ """
+ def merge_dicts(origd, newd):
+ """
+ https://stackoverflow.com/questions/71396284/python-how-to-recursively-merge-2-dictionaries
+ """
+ for key, val in newd.items():
+ if key not in origd:
+ origd[key] = val
+ continue
+ if isinstance(val, dict):
+ if not isinstance(origd[key], dict):
+ origd[key] = {}
+ merge_dicts(origd[key], val)
+ else:
+ origd[key] = val
+ return origd
+ upc = self.updateable_components
+ for dboard in self.dboards:
+ upc = merge_dicts(upc, dboard.updateable_components)
+ return upc
+
def _verify_compatibility(self, filebasename, update_dict):
"""
check whether the given MPM compatibility matches the
@@ -102,18 +127,18 @@ class ZynqComponents(object):
self.log.trace("Compatibility check MPM <-> FPGA via DTS enabled")
dtsfilepath = filebasename + '.dts'
if not os.path.exists(dtsfilepath):
- self.log.warning("DTS file not found: {}, cannot check version of bitfile without DTS.".format(dtsfilepath))
+ self.log.warning(f"DTS file not found: {dtsfilepath}, cannot "
+ f"check version of bitfile without DTS.")
return
- self.log.trace("Parse DTS file {} for version information"\
- .format(dtsfilepath))
+ self.log.trace(f"Parsing DTS file {dtsfilepath} for version information")
fpga_versions = self._parse_dts_version_info_from_file(dtsfilepath)
if not fpga_versions:
self._log_and_raise("no component version information in DTS file")
if 'compatibility' not in update_dict:
self._log_and_raise("MPM FPGA version infos not found")
mpm_versions = update_dict['compatibility']
- self.log.trace("DTS version infos: {}".format(fpga_versions))
- self.log.trace("MPM version infos: {}".format(mpm_versions))
+ self.log.trace(f"DTS version infos: {fpga_versions}")
+ self.log.trace(f"MPM version infos: {mpm_versions}")
try:
for component in mpm_versions.keys():
@@ -160,19 +185,19 @@ class ZynqComponents(object):
self.log.trace(f"Updating FPGA with image at {filepath}"\
" (metadata: `{str(metadata)}')")
file_name, file_extension = os.path.splitext(filepath)
- self.log.trace("file_name: {}".format(file_name))
# Cut off the period from the file extension
file_extension = file_extension[1:].lower()
if file_extension not in ['bit', 'bin']:
self._log_and_raise(f"Invalid FPGA bitfile: {filepath}")
- binfile_path = self.updateable_components['fpga']['path']\
- .format(self.device_info.get('product'))
+ updc = self._merge_updateable_components()
+ assert 'path' in updc['fpga']
+ binfile_path = updc['fpga']['path'].format(self.device_info.get('product'))
- self._verify_compatibility(file_name, self.updateable_components['fpga'])
+ self._verify_compatibility(file_name, updc['fpga'])
if file_extension == "bit":
- self.log.trace("Converting bit to bin file and writing to {}"
- .format(binfile_path))
+ self.log.trace(
+ f"Converting bit to bin file and writing to {binfile_path}")
from usrp_mpm.fpga_bit_to_bin import fpga_bit_to_bin
fpga_bit_to_bin(filepath, binfile_path, flip=True)
elif file_extension == "bin":
@@ -189,12 +214,12 @@ class ZynqComponents(object):
:param filepath: path to new DTS image
:param metadata: Dictionary of strings containing metadata
"""
- dtsfile_path = self.updateable_components['dts']['path'].format(
+ dtsfile_path = self._merge_updateable_components()['dts']['path'].format(
self.device_info.get('product'))
self.log.trace("Updating DTS with image at %s to %s (metadata: %s)",
filepath, dtsfile_path, str(metadata))
shutil.copy(filepath, dtsfile_path)
- dtbofile_path = self.updateable_components['dts']['output'].format(
+ dtbofile_path = self._merge_updateable_components()['dts']['output'].format(
self.device_info.get('product'))
self.log.trace("Compiling to %s...", dtbofile_path)
dtc_command = [
diff --git a/mpm/python/usrp_mpm/dboard_manager/base.py b/mpm/python/usrp_mpm/dboard_manager/base.py
index 46ac63fb5..648b32c2d 100644
--- a/mpm/python/usrp_mpm/dboard_manager/base.py
+++ b/mpm/python/usrp_mpm/dboard_manager/base.py
@@ -34,6 +34,10 @@ class DboardManagerBase:
# maps these keys to actual spidev paths. Also throws a warning/error if
# the SPI configuration is invalid.
spi_chipselect = {}
+ # If the daughterboard adds updateable components, add them there. This can
+ # also be used to amend already existing updateable components, such as the
+ # FPGA.
+ updateable_components = {}
### End of overridables #################################################
def __init__(self, slot_idx, **kwargs):
diff --git a/mpm/python/usrp_mpm/dboard_manager/zbx.py b/mpm/python/usrp_mpm/dboard_manager/zbx.py
index e8c06d1f6..d29abd163 100644
--- a/mpm/python/usrp_mpm/dboard_manager/zbx.py
+++ b/mpm/python/usrp_mpm/dboard_manager/zbx.py
@@ -36,6 +36,22 @@ class ZBX(X4xxDbMixin, DboardManagerBase):
'temperature': 'get_rf_temp_sensor',
}
has_db_flash = True
+ # ZBX depends on two types of RF core implementations which each have
+ # compat versions.
+ updateable_components = {
+ 'fpga': {
+ 'compatibility': {
+ 'rf_core_100m': {
+ 'current': (1, 0),
+ 'oldest': (1, 0),
+ },
+ 'rf_core_400m': {
+ 'current': (1, 0),
+ 'oldest': (1, 0),
+ },
+ }
+ },
+ }
### End of overridables #################################################
### Daughterboard driver/hardware compatibility value
diff --git a/mpm/python/usrp_mpm/periph_manager/x4xx.py b/mpm/python/usrp_mpm/periph_manager/x4xx.py
index 711668fb6..b43edc654 100644
--- a/mpm/python/usrp_mpm/periph_manager/x4xx.py
+++ b/mpm/python/usrp_mpm/periph_manager/x4xx.py
@@ -175,6 +175,7 @@ class x4xx(ZynqComponents, PeriphManagerBase):
}
db_iface = X4xxDboardIface
dboard_eeprom_magic = eeprom_magic
+ # Note: Daughterboard classes also carry updateable_components information.
updateable_components = {
'fpga': {
'callback': "update_fpga",
@@ -194,14 +195,6 @@ class x4xx(ZynqComponents, PeriphManagerBase):
'current': (1, 0),
'oldest': (1, 0),
},
- 'rf_core_100m': {
- 'current': (1, 0),
- 'oldest': (1, 0),
- },
- 'rf_core_400m': {
- 'current': (1, 0),
- 'oldest': (1, 0),
- },
}
},
'dts': {