aboutsummaryrefslogtreecommitdiffstats
path: root/mpm
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2019-09-09 16:29:32 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 12:21:33 -0800
commit025ffdce3475585b3f65e955af32afbab9181e13 (patch)
treefaea7b200ec2fa09d61224f21dd8aa7302b011b4 /mpm
parentd76cca76dd7699ed224b38cd30146c25ad2ac1f8 (diff)
downloaduhd-025ffdce3475585b3f65e955af32afbab9181e13.tar.gz
uhd-025ffdce3475585b3f65e955af32afbab9181e13.tar.bz2
uhd-025ffdce3475585b3f65e955af32afbab9181e13.zip
mpm: Move common mboard regs code to common location
This assumes an existence of mboard_regs_control in PeriphManagerBase and implements most TK controls there. All the *_periphs.py files can now use a common class for registers, including the TK access, but also git hash, build date, and device ID access. This also fixes two issues: - set_timekeeper_time() and set_tick_period() had a bug that would incorrectly calculate the upper 32 bits of their respective registers. - N3xx had a bug that would swap around set time now and next PPS. This got auto-fixed because the common code never had this bug.
Diffstat (limited to 'mpm')
-rw-r--r--mpm/python/usrp_mpm/periph_manager/CMakeLists.txt1
-rw-r--r--mpm/python/usrp_mpm/periph_manager/base.py55
-rw-r--r--mpm/python/usrp_mpm/periph_manager/common.py209
-rw-r--r--mpm/python/usrp_mpm/periph_manager/e31x.py70
-rw-r--r--mpm/python/usrp_mpm/periph_manager/e31x_periphs.py196
-rw-r--r--mpm/python/usrp_mpm/periph_manager/e320.py70
-rw-r--r--mpm/python/usrp_mpm/periph_manager/e320_periphs.py189
-rw-r--r--mpm/python/usrp_mpm/periph_manager/n3xx.py74
-rw-r--r--mpm/python/usrp_mpm/periph_manager/n3xx_periphs.py144
9 files changed, 272 insertions, 736 deletions
diff --git a/mpm/python/usrp_mpm/periph_manager/CMakeLists.txt b/mpm/python/usrp_mpm/periph_manager/CMakeLists.txt
index 987bc184b..4f8520c12 100644
--- a/mpm/python/usrp_mpm/periph_manager/CMakeLists.txt
+++ b/mpm/python/usrp_mpm/periph_manager/CMakeLists.txt
@@ -11,6 +11,7 @@ set(USRP_MPM_FILES ${USRP_MPM_FILES})
set(USRP_MPM_PERIPHMGR_FILES
${CMAKE_CURRENT_SOURCE_DIR}/__init__.py.in
${CMAKE_CURRENT_SOURCE_DIR}/base.py
+ ${CMAKE_CURRENT_SOURCE_DIR}/common.py
${CMAKE_CURRENT_SOURCE_DIR}/n3xx.py
${CMAKE_CURRENT_SOURCE_DIR}/n3xx_periphs.py
${CMAKE_CURRENT_SOURCE_DIR}/e320.py
diff --git a/mpm/python/usrp_mpm/periph_manager/base.py b/mpm/python/usrp_mpm/periph_manager/base.py
index 4ae30778a..5e5d3889e 100644
--- a/mpm/python/usrp_mpm/periph_manager/base.py
+++ b/mpm/python/usrp_mpm/periph_manager/base.py
@@ -176,6 +176,8 @@ class PeriphManagerBase(object):
# Device initialization (at MPM startup)
###########################################################################
def __init__(self):
+ # This gets set in the child class
+ self.mboard_regs_control = None
# Note: args is a dictionary.
assert self.pids
assert self.mboard_eeprom_magic is not None
@@ -513,7 +515,7 @@ class PeriphManagerBase(object):
self.log.trace("Teardown called for Peripheral Manager base.")
###########################################################################
- # Misc device status controls and indicators
+ # RFNoC and Device info
###########################################################################
def set_device_id(self, device_id):
"""
@@ -521,7 +523,8 @@ class PeriphManagerBase(object):
The device ID is used to identify the RFNoC components associated with
this motherboard.
"""
- raise NotImplementedError("set_device_id() not implemented.")
+ self.log.debug("Setting device ID to `{}'".format(device_id))
+ self.mboard_regs_control.set_device_id(device_id)
def get_device_id(self):
"""
@@ -529,8 +532,28 @@ class PeriphManagerBase(object):
The device ID is used to identify the RFNoC components associated with
this motherboard.
"""
- raise NotImplementedError("get_device_id() not implemented.")
+ return self.mboard_regs_control.get_device_id()
+
+ def get_proto_ver(self):
+ """
+ Return RFNoC protocol version
+ """
+ proto_ver = self.mboard_regs_control.get_proto_ver()
+ self.log.debug("RFNoC protocol version supported by this device is {}".format(proto_ver))
+ return proto_ver
+
+ def get_chdr_width(self):
+ """
+ Return RFNoC CHDR width
+ """
+ chdr_width = self.mboard_regs_control.get_chdr_width()
+ self.log.debug("CHDR width supported by the device is {}".format(chdr_width))
+ return chdr_width
+
+ ###########################################################################
+ # Misc device status controls and indicators
+ ###########################################################################
def get_init_status(self):
"""
Returns the status of the device after its initialization (that happens
@@ -611,20 +634,6 @@ class PeriphManagerBase(object):
"""
return [dboard.device_info for dboard in self.dboards]
- @no_claim
- def get_proto_ver(self):
- """
- Return RFNoC protocol version
- """
- raise NotImplementedError("get_proto_ver() not implemented.")
-
- @no_claim
- def get_chdr_width(self):
- """
- Return RFNoC CHDR width
- """
- raise NotImplementedError("get_chdr_width() not implemented.")
-
###########################################################################
# Component updating
###########################################################################
@@ -871,7 +880,7 @@ class PeriphManagerBase(object):
"""
Return the number of timekeepers
"""
- raise NotImplementedError("get_num_timekeepers() not implemented.")
+ return self.mboard_regs_control.get_num_timekeepers()
def get_timekeeper_time(self, tk_idx, last_pps):
"""
@@ -881,8 +890,7 @@ class PeriphManagerBase(object):
tk_idx: Index of timekeeper
next_pps: If True, get time at last PPS. Otherwise, get time now.
"""
- raise NotImplementedError(
- "get_ticks_now({}, {}) not implemented.".format(tk_idx, last_pps))
+ return self.mboard_regs_control.get_timekeeper_time(tk_idx, last_pps)
def set_timekeeper_time(self, tk_idx, ticks, next_pps):
"""
@@ -893,9 +901,7 @@ class PeriphManagerBase(object):
ticks: Time in ticks
next_pps: If True, set time at next PPS. Otherwise, set time now.
"""
- raise NotImplementedError(
- "set_ticks_last_pps({}, {}, {}) not implemented."
- .format(tk_idx, ticks, next_pps))
+ self.mboard_regs_control.set_timekeeper_time(tk_idx, ticks, next_pps)
def set_tick_period(self, tk_idx, period_ns):
"""
@@ -905,8 +911,7 @@ class PeriphManagerBase(object):
tk_idx: Index of timekeeper
period_ns: Period in nanoseconds
"""
- raise NotImplementedError(
- "set_tick_period({}) not implemented.".format(tk_idx, period_ns))
+ self.mboard_regs_control.set_tick_period(tk_idx, period_ns)
def get_clocks(self):
"""
diff --git a/mpm/python/usrp_mpm/periph_manager/common.py b/mpm/python/usrp_mpm/periph_manager/common.py
new file mode 100644
index 000000000..e09be835e
--- /dev/null
+++ b/mpm/python/usrp_mpm/periph_manager/common.py
@@ -0,0 +1,209 @@
+#
+# Copyright 2019 Ettus Research, a National Instruments Brand
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+"""
+Common code for all MPM devices
+"""
+
+import datetime
+from usrp_mpm.sys_utils.uio import UIO
+
+class MboardRegsCommon(object):
+ """
+ Parent class for mboard regs that are common between *all* MPM devices
+ """
+ # pylint: disable=bad-whitespace
+ # Global Registers
+ MB_COMPAT_NUM = 0x0000
+ MB_DATESTAMP = 0x0004
+ MB_GIT_HASH = 0x0008
+ MB_SCRATCH = 0x000C
+ MB_DEVICE_ID = 0x0010
+ MB_RFNOC_INFO = 0x0014
+ MB_NUM_TIMEKEEPERS = 0x0048
+ # Timekeeper registers
+ MB_TIME_NOW_LO = 0x1000
+ MB_TIME_NOW_HI = 0x1004
+ MB_TIME_EVENT_LO = 0x1008
+ MB_TIME_EVENT_HI = 0x100C
+ MB_TIME_CTRL = 0x1010
+ MB_TIME_LAST_PPS_LO = 0x1014
+ MB_TIME_LAST_PPS_HI = 0x1018
+ MB_TIME_BASE_PERIOD_LO = 0x101C
+ MB_TIME_BASE_PERIOD_HI = 0x1020
+ MB_TIMEKEEPER_OFFSET = 12
+ # Bitfield locations for the MB_RFNOC_INFO register.
+ MB_RFNOC_INFO_PROTO_VER = 0
+ MB_RFNOC_INFO_CHDR_WIDTH = 16
+ # pylint: enable=bad-whitespace
+
+ def __init__(self, label, log):
+ self.log = log.getChild('MBRegs')
+ self.regs = UIO(
+ label=label,
+ read_only=False
+ )
+ self.poke32 = self.regs.poke32
+ self.peek32 = self.regs.peek32
+
+ ###########################################################################
+ # Device ID
+ ###########################################################################
+ def set_device_id(self, device_id):
+ """
+ Set device ID
+ """
+ with self.regs:
+ self.log.trace("Writing MB_DEVICE_ID with 0x{:08X}".format(device_id))
+ return self.poke32(self.MB_DEVICE_ID, device_id)
+
+ def get_device_id(self):
+ """
+ Get device ID
+ """
+ with self.regs:
+ regs_val = self.peek32(self.MB_DEVICE_ID)
+ device_id = regs_val & 0x0000ffff
+ self.log.trace("Read MB_DEVICE_ID 0x{:08X}".format(device_id))
+ return device_id
+
+ ###########################################################################
+ # FPGA Identification
+ ###########################################################################
+ def get_compat_number(self):
+ """get FPGA compat number
+
+ This function reads back FPGA compat number.
+ The return is a tuple of 2 numbers:
+ (major compat number, minor compat number)
+ """
+ with self.regs:
+ compat_number = self.peek32(self.MB_COMPAT_NUM)
+ minor = compat_number & 0xff
+ major = (compat_number>>16) & 0xff
+ return (major, minor)
+
+ def get_build_timestamp(self):
+ """
+ Returns the build date/time for the FPGA image.
+ The return value is a datetime string in ISO 8601 format
+ (YYYY-MM-DD HH:MM:SS.mmmmmm)
+ """
+ with self.regs:
+ datestamp_rb = self.peek32(self.MB_DATESTAMP)
+ if datestamp_rb > 0:
+ dt_str = datetime.datetime(
+ year=((datestamp_rb>>17)&0x3F)+2000,
+ month=(datestamp_rb>>23)&0x0F,
+ day=(datestamp_rb>>27)&0x1F,
+ hour=(datestamp_rb>>12)&0x1F,
+ minute=(datestamp_rb>>6)&0x3F,
+ second=((datestamp_rb>>0)&0x3F))
+ self.log.trace("FPGA build timestamp: {}".format(str(dt_str)))
+ return str(dt_str)
+ # Compatibility with FPGAs without datestamp capability
+ return ''
+
+ def get_git_hash(self):
+ """
+ Returns the GIT hash for the FPGA build.
+ The return is a tuple of 2 numbers:
+ (short git hash, string: dirty/clean)
+ """
+ with self.regs:
+ git_hash_rb = self.peek32(self.MB_GIT_HASH)
+ git_hash = git_hash_rb & 0x0FFFFFFF
+ tree_dirty = ((git_hash_rb & 0xF0000000) > 0)
+ dirtiness_qualifier = 'dirty' if tree_dirty else 'clean'
+ self.log.trace("FPGA build GIT Hash: {:07x} ({})".format(
+ git_hash, dirtiness_qualifier))
+ return (git_hash, dirtiness_qualifier)
+
+ def get_proto_ver(self):
+ """
+ Return RFNoC protocol version
+ """
+ with self.regs:
+ reg_val = self.peek32(self.MB_RFNOC_INFO)
+ proto_ver = (reg_val & 0x0000ffff) >> self.MB_RFNOC_INFO_PROTO_VER
+ self.log.trace("Read RFNOC_PROTO_VER 0x{:08X}".format(proto_ver))
+ return proto_ver
+
+ def get_chdr_width(self):
+ """
+ Return RFNoC CHDR width
+ """
+ with self.regs:
+ reg_val = self.peek32(self.MB_RFNOC_INFO)
+ chdr_width = (reg_val & 0xffff0000) >> self.MB_RFNOC_INFO_CHDR_WIDTH
+ self.log.trace("Read RFNOC_CHDR_WIDTH 0x{:08X}".format(chdr_width))
+ return chdr_width
+
+ ###########################################################################
+ # Timekeeper API
+ ###########################################################################
+ def get_num_timekeepers(self):
+ """
+ Return the number of timekeepers
+ """
+ with self.regs:
+ return self.peek32(self.MB_NUM_TIMEKEEPERS)
+
+ def get_timekeeper_time(self, tk_idx, last_pps):
+ """
+ Get the time in ticks
+
+ Arguments:
+ tk_idx: Index of timekeeper
+ next_pps: If True, get time at last PPS. Otherwise, get time now.
+ """
+ addr_lo = \
+ (self.MB_TIME_LAST_PPS_LO if last_pps else self.MB_TIME_NOW_LO) + \
+ tk_idx * self.MB_TIMEKEEPER_OFFSET
+ addr_hi = addr_lo + 4
+ with self.regs:
+ time_lo = self.peek32(addr_lo)
+ time_hi = self.peek32(addr_hi)
+ return (time_hi << 32) | time_lo
+
+ def set_timekeeper_time(self, tk_idx, ticks, next_pps):
+ """
+ Set the time in ticks
+
+ Arguments:
+ tk_idx: Index of timekeeper
+ ticks: Time in ticks
+ next_pps: If True, set time at next PPS. Otherwise, set time now.
+ """
+ addr_lo = \
+ self.MB_TIME_EVENT_LO + tk_idx * self.MB_TIMEKEEPER_OFFSET
+ addr_hi = addr_lo + 4
+ addr_ctrl = \
+ self.MB_TIME_CTRL + tk_idx * self.MB_TIMEKEEPER_OFFSET
+ time_lo = ticks & 0xFFFFFFFF
+ time_hi = (ticks >> 32) & 0xFFFFFFFF
+ time_ctrl = 0x2 if next_pps else 0x1
+ self.log.trace("Setting time on timekeeper %d to %d %s", tk_idx, ticks,
+ ("on next pps" if next_pps else "now"))
+ with self.regs:
+ self.poke32(addr_lo, time_lo)
+ self.poke32(addr_hi, time_hi)
+ self.poke32(addr_ctrl, time_ctrl)
+
+ def set_tick_period(self, tk_idx, period_ns):
+ """
+ Set the time per tick in nanoseconds (tick period)
+
+ Arguments:
+ tk_idx: Index of timekeeper
+ period_ns: Period in nanoseconds
+ """
+ addr_lo = self.MB_TIME_BASE_PERIOD_LO + tk_idx * self.MB_TIMEKEEPER_OFFSET
+ addr_hi = addr_lo + 4
+ period_lo = period_ns & 0xFFFFFFFF
+ period_hi = (period_ns >> 32) & 0xFFFFFFFF
+ with self.regs:
+ self.poke32(addr_lo, period_lo)
+ self.poke32(addr_hi, period_hi)
diff --git a/mpm/python/usrp_mpm/periph_manager/e31x.py b/mpm/python/usrp_mpm/periph_manager/e31x.py
index 573e75d55..8ba8ff034 100644
--- a/mpm/python/usrp_mpm/periph_manager/e31x.py
+++ b/mpm/python/usrp_mpm/periph_manager/e31x.py
@@ -509,39 +509,6 @@ class e31x(ZynqComponents, PeriphManagerBase):
})
return device_info
- def set_device_id(self, device_id):
- """
- Sets the device ID for this motherboard.
- The device ID is used to identify the RFNoC components associated with
- this motherboard.
- """
- self.log.debug("Setting device ID to `{}'".format(device_id))
- self.mboard_regs_control.set_device_id(device_id)
-
- def get_device_id(self):
- """
- Gets the device ID for this motherboard.
- The device ID is used to identify the RFNoC components associated with
- this motherboard.
- """
- return self.mboard_regs_control.get_device_id()
-
- def get_proto_ver(self):
- """
- Return RFNoC protocol version
- """
- proto_ver = self.mboard_regs_control.get_proto_ver()
- self.log.debug("RFNoC protocol version supported by this device is {}".format(proto_ver))
- return proto_ver
-
- def get_chdr_width(self):
- """
- Return RFNoC CHDR width
- """
- chdr_width = self.mboard_regs_control.get_chdr_width()
- self.log.debug("CHDR width supported by the device is {}".format(chdr_width))
- return chdr_width
-
###########################################################################
# Clock/Time API
###########################################################################
@@ -738,43 +705,6 @@ class e31x(ZynqComponents, PeriphManagerBase):
#######################################################################
# Timekeeper API
#######################################################################
- def get_num_timekeepers(self):
- """
- Return the number of timekeepers
- """
- return self.mboard_regs_control.get_num_timekeepers()
-
- def get_timekeeper_time(self, tk_idx, last_pps):
- """
- Get the time in ticks
-
- Arguments:
- tk_idx: Index of timekeeper
- next_pps: If True, get time at last PPS. Otherwise, get time now.
- """
- return self.mboard_regs_control.get_timekeeper_time(tk_idx, last_pps)
-
- def set_timekeeper_time(self, tk_idx, ticks, next_pps):
- """
- Set the time in ticks
-
- Arguments:
- tk_idx: Index of timekeeper
- ticks: Time in ticks
- next_pps: If True, set time at next PPS. Otherwise, set time now.
- """
- self.mboard_regs_control.set_timekeeper_time(tk_idx, ticks, next_pps)
-
- def set_tick_period(self, tk_idx, period_ns):
- """
- Set the time per tick in nanoseconds (tick period)
-
- Arguments:
- tk_idx: Index of timekeeper
- period_ns: Period in nanoseconds
- """
- self.mboard_regs_control.set_tick_period(tk_idx, period_ns)
-
def get_clocks(self):
"""
Gets the RFNoC-related clocks present in the FPGA design
diff --git a/mpm/python/usrp_mpm/periph_manager/e31x_periphs.py b/mpm/python/usrp_mpm/periph_manager/e31x_periphs.py
index 330cd830e..84c60d2ce 100644
--- a/mpm/python/usrp_mpm/periph_manager/e31x_periphs.py
+++ b/mpm/python/usrp_mpm/periph_manager/e31x_periphs.py
@@ -1,5 +1,6 @@
#
# Copyright 2018 Ettus Research, a National Instruments Company
+# Copyright 2019 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
@@ -7,11 +8,10 @@
E310 peripherals
"""
-import datetime
-import math
from usrp_mpm.sys_utils.sysfs_gpio import SysFSGPIO, GPIOBank
-from usrp_mpm.sys_utils.uio import UIO
+from usrp_mpm.periph_manager.common import MboardRegsCommon
+# pylint: disable=too-few-public-methods
class FrontpanelGPIO(GPIOBank):
"""
Abstraction layer for the front panel GPIO
@@ -27,18 +27,14 @@ class FrontpanelGPIO(GPIOBank):
0xFF, # use_mask
ddr
)
+# pylint: enable=too-few-public-methods
-class MboardRegsControl(object):
+class MboardRegsControl(MboardRegsCommon):
"""
Control the FPGA Motherboard registers
"""
+ # pylint: disable=bad-whitespace
# Motherboard registers
- MB_COMPAT_NUM = 0x0000
- MB_DATESTAMP = 0x0004
- MB_GIT_HASH = 0x0008
- MB_SCRATCH = 0x000C
- MB_DEVICE_ID = 0x0010
- MB_RFNOC_INFO = 0x0014
MB_CLOCK_CTRL = 0x0018
MB_XADC_RB = 0x001C
MB_BUS_CLK_RATE = 0x0020
@@ -51,26 +47,12 @@ class MboardRegsControl(object):
MB_GPS_STATUS = 0x003C
MB_DBOARD_CTRL = 0x0040
MB_DBOARD_STATUS = 0x0044
- MB_NUM_TIMEKEEPERS = 0x0048
- # Timekeeper registers
- MB_TIME_NOW_LO = 0x1000
- MB_TIME_NOW_HI = 0x1004
- MB_TIME_EVENT_LO = 0x1008
- MB_TIME_EVENT_HI = 0x100C
- MB_TIME_CTRL = 0x1010
- MB_TIME_LAST_PPS_LO = 0x1014
- MB_TIME_LAST_PPS_HI = 0x1018
- MB_TIME_BASE_PERIOD_LO = 0x101C
- MB_TIME_BASE_PERIOD_HI = 0x1020
- MB_TIMEKEEPER_OFFSET = 12
-
- # Bitfield locations for the MB_RFNOC_INFO register.
- MB_RFNOC_INFO_PROTO_VER = 0
- MB_RFNOC_INFO_CHDR_WIDTH = 16
# Bitfield locations for the MB_CLOCK_CTRL register.
MB_CLOCK_CTRL_PPS_SEL_INT = 0
MB_CLOCK_CTRL_PPS_SEL_EXT = 1
+ # FIXME: This value is probably wrong
+ MB_CLOCK_CTRL_PPS_SEL_GPS = 2
MB_CLOCK_CTRL_REF_CLK_LOCKED = 2
# Bitfield locations for the MB_GPS_CTRL register.
@@ -94,48 +76,10 @@ class MboardRegsControl(object):
# Bitfield locations for the MB_DBOARD_STATUS register.
MB_DBOARD_STATUS_RX_LOCK = 6
MB_DBOARD_STATUS_TX_LOCK = 7
+ # pylint: enable=bad-whitespace
def __init__(self, label, log):
- self.log = log
- self.regs = UIO(
- label=label,
- read_only=False
- )
- self.poke32 = self.regs.poke32
- self.peek32 = self.regs.peek32
-
- def get_compat_number(self):
- """get FPGA compat number
-
- This function reads back FPGA compat number.
- The return is a tuple of
- 2 numbers: (major compat number, minor compat number )
- """
- with self.regs:
- compat_number = self.peek32(self.MB_COMPAT_NUM)
- minor = compat_number & 0xff
- major = (compat_number>>16) & 0xff
- return (major, minor)
-
- def get_proto_ver(self):
- """
- Return RFNoC protocol version
- """
- with self.regs:
- reg_val = self.peek32(self.MB_RFNOC_INFO)
- proto_ver = (reg_val & 0x0000ffff) >> self.MB_RFNOC_INFO_PROTO_VER
- self.log.trace("Read RFNOC_PROTO_VER 0x{:08X}".format(proto_ver))
- return proto_ver
-
- def get_chdr_width(self):
- """
- Return RFNoC CHDR width
- """
- with self.regs:
- reg_val = self.peek32(self.MB_RFNOC_INFO)
- chdr_width = (reg_val & 0xffff0000) >> self.MB_RFNOC_INFO_CHDR_WIDTH
- self.log.trace("Read RFNOC_CHDR_WIDTH 0x{:08X}".format(chdr_width))
- return chdr_width
+ MboardRegsCommon.__init__(self, label, log)
def set_fp_gpio_master(self, value):
"""set driver for front panel GPIO
@@ -173,61 +117,6 @@ class MboardRegsControl(object):
with self.regs:
return self.peek32(self.MB_GPIO_RADIO_SRC) & 0xffffff
- def set_device_id(self, device_id):
- """
- Set device ID
- """
- with self.regs:
- self.log.trace("Writing MB_DEVICE_ID with 0x{:08X}".format(device_id))
- return self.poke32(self.MB_DEVICE_ID, device_id)
-
- def get_device_id(self):
- """
- Get device ID
- """
- with self.regs:
- regs_val = self.peek32(self.MB_DEVICE_ID)
- device_id = regs_val & 0x0000ffff
- self.log.trace("Read MB_DEVICE_ID 0x{:08X}".format(device_id))
- return device_id
-
- def get_build_timestamp(self):
- """
- Returns the build date/time for the FPGA image.
- The return is datetime string with the ISO 8601 format
- (YYYY-MM-DD HH:MM:SS.mmmmmm)
- """
- with self.regs:
- datestamp_rb = self.peek32(self.MB_DATESTAMP)
- if datestamp_rb > 0:
- dt_str = datetime.datetime(
- year=((datestamp_rb>>17)&0x3F)+2000,
- month=(datestamp_rb>>23)&0x0F,
- day=(datestamp_rb>>27)&0x1F,
- hour=(datestamp_rb>>12)&0x1F,
- minute=(datestamp_rb>>6)&0x3F,
- second=((datestamp_rb>>0)&0x3F))
- self.log.trace("FPGA build timestamp: {}".format(str(dt_str)))
- return str(dt_str)
- else:
- # Compatibility with FPGAs without datestamp capability
- return ''
-
- def get_git_hash(self):
- """
- Returns the GIT hash for the FPGA build.
- The return is a tuple of
- 2 numbers: (short git hash, bool: is the tree dirty?)
- """
- with self.regs:
- git_hash_rb = self.peek32(self.MB_GIT_HASH)
- git_hash = git_hash_rb & 0x0FFFFFFF
- tree_dirty = ((git_hash_rb & 0xF0000000) > 0)
- dirtiness_qualifier = 'dirty' if tree_dirty else 'clean'
- self.log.trace("FPGA build GIT Hash: {:07x} ({})".format(
- git_hash, dirtiness_qualifier))
- return (git_hash, dirtiness_qualifier)
-
def set_time_source(self, time_source):
"""
Set time source
@@ -261,71 +150,6 @@ class MboardRegsControl(object):
else:
assert False, "Cannot set to invalid clock source: {}".format(clock_source)
- def get_num_timekeepers(self):
- """
- Return the number of timekeepers
- """
- with self.regs:
- return self.peek32(self.MB_NUM_TIMEKEEPERS)
-
- def get_timekeeper_time(self, tk_idx, last_pps):
- """
- Get the time in ticks
-
- Arguments:
- tk_idx: Index of timekeeper
- next_pps: If True, get time at last PPS. Otherwise, get time now.
- """
- addr_lo = \
- (self.MB_TIME_LAST_PPS_LO if last_pps else self.MB_TIME_NOW_LO) + \
- tk_idx * self.MB_TIMEKEEPER_OFFSET
- addr_hi = addr_lo + 4
- with self.regs:
- time_lo = self.peek32(addr_lo)
- time_hi = self.peek32(addr_hi)
- return time_hi << 32 | time_lo
-
-
- def set_timekeeper_time(self, tk_idx, ticks, next_pps):
- """
- Set the time in ticks
-
- Arguments:
- tk_idx: Index of timekeeper
- ticks: Time in ticks
- next_pps: If True, set time at next PPS. Otherwise, set time now.
- """
- addr_lo = \
- self.MB_TIME_EVENT_LO + tk_idx * self.MB_TIMEKEEPER_OFFSET
- addr_hi = addr_lo + 4
- addr_ctrl = \
- self.MB_TIME_CTRL + tk_idx * self.MB_TIMEKEEPER_OFFSET
- time_lo = ticks & 0xFFFFFFFF
- time_hi = (ticks > 32) & 0xFFFFFFFF
- time_ctrl = 0x2 if next_pps else 0x1
- self.log.trace("Setting time on timekeeper %d to %d %s", tk_idx, ticks,
- ("on next pps" if next_pps else "now"))
- with self.regs:
- self.poke32(addr_lo, time_lo)
- self.poke32(addr_hi, time_hi)
- self.poke32(addr_ctrl, time_ctrl)
-
- def set_tick_period(self, tk_idx, period_ns):
- """
- Set the time per tick in nanoseconds (tick period)
-
- Arguments:
- tk_idx: Index of timekeeper
- period_ns: Period in nanoseconds
- """
- addr_lo = self.MB_TIME_BASE_PERIOD_LO + tk_idx * self.MB_TIMEKEEPER_OFFSET
- addr_hi = addr_lo + 4
- period_lo = period_ns & 0xFFFFFFFF
- period_hi = (period_ns > 32) & 0xFFFFFFFF
- with self.regs:
- self.poke32(addr_lo, period_lo)
- self.poke32(addr_hi, period_hi)
-
def get_fpga_type(self):
"""
Reads the type of the FPGA image currently loaded
diff --git a/mpm/python/usrp_mpm/periph_manager/e320.py b/mpm/python/usrp_mpm/periph_manager/e320.py
index d48f90cbd..90cc1c049 100644
--- a/mpm/python/usrp_mpm/periph_manager/e320.py
+++ b/mpm/python/usrp_mpm/periph_manager/e320.py
@@ -410,39 +410,6 @@ class e320(ZynqComponents, PeriphManagerBase):
})
return device_info
- def set_device_id(self, device_id):
- """
- Sets the device ID for this motherboard.
- The device ID is used to identify the RFNoC components associated with
- this motherboard.
- """
- self.log.debug("Setting device ID to `{}'".format(device_id))
- self.mboard_regs_control.set_device_id(device_id)
-
- def get_device_id(self):
- """
- Gets the device ID for this motherboard.
- The device ID is used to identify the RFNoC components associated with
- this motherboard.
- """
- return self.mboard_regs_control.get_device_id()
-
- def get_proto_ver(self):
- """
- Return RFNoC protocol version
- """
- proto_ver = self.mboard_regs_control.get_proto_ver()
- self.log.debug("RFNoC protocol version supported by this device is {}".format(proto_ver))
- return proto_ver
-
- def get_chdr_width(self):
- """
- Return RFNoC CHDR width
- """
- chdr_width = self.mboard_regs_control.get_chdr_width()
- self.log.debug("CHDR width supported by the device is {}".format(chdr_width))
- return chdr_width
-
###########################################################################
# Clock/Time API
###########################################################################
@@ -753,43 +720,6 @@ class e320(ZynqComponents, PeriphManagerBase):
#######################################################################
# Timekeeper API
#######################################################################
- def get_num_timekeepers(self):
- """
- Return the number of timekeepers
- """
- return self.mboard_regs_control.get_num_timekeepers()
-
- def get_timekeeper_time(self, tk_idx, last_pps):
- """
- Get the time in ticks
-
- Arguments:
- tk_idx: Index of timekeeper
- next_pps: If True, get time at last PPS. Otherwise, get time now.
- """
- return self.mboard_regs_control.get_timekeeper_time(tk_idx, last_pps)
-
- def set_timekeeper_time(self, tk_idx, ticks, next_pps):
- """
- Set the time in ticks
-
- Arguments:
- tk_idx: Index of timekeeper
- ticks: Time in ticks
- next_pps: If True, set time at next PPS. Otherwise, set time now.
- """
- self.mboard_regs_control.set_timekeeper_time(tk_idx, ticks, next_pps)
-
- def set_tick_period(self, tk_idx, period_ns):
- """
- Set the time per tick in nanoseconds (tick period)
-
- Arguments:
- tk_idx: Index of timekeeper
- period_ns: Period in nanoseconds
- """
- self.mboard_regs_control.set_tick_period(tk_idx, period_ns)
-
def get_clocks(self):
"""
Gets the RFNoC-related clocks present in the FPGA design
diff --git a/mpm/python/usrp_mpm/periph_manager/e320_periphs.py b/mpm/python/usrp_mpm/periph_manager/e320_periphs.py
index cad5c39ad..8dcd5a9ba 100644
--- a/mpm/python/usrp_mpm/periph_manager/e320_periphs.py
+++ b/mpm/python/usrp_mpm/periph_manager/e320_periphs.py
@@ -7,10 +7,9 @@
E320 peripherals
"""
-import datetime
import math
from usrp_mpm.sys_utils.sysfs_gpio import SysFSGPIO, GPIOBank
-from usrp_mpm.sys_utils.uio import UIO
+from usrp_mpm.periph_manager.common import MboardRegsCommon
# Map register values to SFP transport types
E320_SFP_TYPES = {
@@ -43,17 +42,12 @@ class FrontpanelGPIO(GPIOBank):
ddr
)
-class MboardRegsControl(object):
+class MboardRegsControl(MboardRegsCommon):
"""
Control the FPGA Motherboard registers
"""
+ # pylint: disable=bad-whitespace
# Motherboard registers
- MB_COMPAT_NUM = 0x0000
- MB_DATESTAMP = 0x0004
- MB_GIT_HASH = 0x0008
- MB_SCRATCH = 0x000C
- MB_DEVICE_ID = 0x0010
- MB_RFNOC_INFO = 0x0014
MB_CLOCK_CTRL = 0x0018
MB_XADC_RB = 0x001C
MB_BUS_CLK_RATE = 0x0020
@@ -66,22 +60,7 @@ class MboardRegsControl(object):
MB_GPS_STATUS = 0x003C
MB_DBOARD_CTRL = 0x0040
MB_DBOARD_STATUS = 0x0044
- MB_NUM_TIMEKEEPERS = 0x0048
- # Timekeeper registers
- MB_TIME_NOW_LO = 0x1000
- MB_TIME_NOW_HI = 0x1004
- MB_TIME_EVENT_LO = 0x1008
- MB_TIME_EVENT_HI = 0x100C
- MB_TIME_CTRL = 0x1010
- MB_TIME_LAST_PPS_LO = 0x1014
- MB_TIME_LAST_PPS_HI = 0x1018
- MB_TIME_BASE_PERIOD_LO = 0x101C
- MB_TIME_BASE_PERIOD_HI = 0x1020
- MB_TIMEKEEPER_OFFSET = 12
-
- # Bitfield locations for the MB_RFNOC_INFO register.
- MB_RFNOC_INFO_PROTO_VER = 0
- MB_RFNOC_INFO_CHDR_WIDTH = 16
+ # pylint: enable=bad-whitespace
# Bitfield locations for the MB_CLOCK_CTRL register.
MB_CLOCK_CTRL_PPS_SEL_INT = 0
@@ -116,64 +95,7 @@ class MboardRegsControl(object):
MB_DBOARD_STATUS_TX_LOCK = 7
def __init__(self, label, log):
- self.log = log
- self.regs = UIO(
- label=label,
- read_only=False
- )
- self.poke32 = self.regs.poke32
- self.peek32 = self.regs.peek32
-
- def get_compat_number(self):
- """get FPGA compat number
-
- This function reads back FPGA compat number.
- The return is a tuple of
- 2 numbers: (major compat number, minor compat number )
- """
- with self.regs:
- compat_number = self.peek32(self.MB_COMPAT_NUM)
- minor = compat_number & 0xff
- major = (compat_number>>16) & 0xff
- return (major, minor)
-
- def set_device_id(self, device_id):
- """
- Set device ID
- """
- with self.regs:
- self.log.trace("Writing MB_DEVICE_ID with 0x{:08X}".format(device_id))
- return self.poke32(self.MB_DEVICE_ID, device_id)
-
- def get_device_id(self):
- """
- Get device ID
- """
- with self.regs:
- reg_val = self.peek32(self.MB_DEVICE_ID)
- device_id = reg_val & 0x0000ffff
- self.log.trace("Read MB_DEVICE_ID 0x{:08X}".format(device_id))
- return device_id
-
- def get_proto_ver(self):
- """
- Return RFNoC protocol version
- """
- with self.regs:
- reg_val = self.peek32(self.MB_RFNOC_INFO)
- proto_ver = (reg_val & 0x0000ffff) >> self.MB_RFNOC_INFO_PROTO_VER
- self.log.trace("Read RFNOC_PROTO_VER 0x{:08X}".format(proto_ver))
- return proto_ver;
-
- def get_chdr_width(self):
- """
- Return RFNoC CHDR width
- """
- with self.regs:
- reg_val = self.peek32(self.MB_RFNOC_INFO)
- chdr_width = (reg_val & 0xffff0000) >> self.MB_RFNOC_INFO_CHDR_WIDTH
- self.log.trace("Read RFNOC_CHDR_WIDTH 0x{:08X}".format(chdr_width))
- return chdr_width
+ MboardRegsCommon.__init__(self, label, log)
def enable_fp_gpio(self, enable):
""" Enable front panel GPIO buffers and power supply
@@ -261,43 +183,6 @@ class MboardRegsControl(object):
with self.regs:
return self.peek32(self.MB_GPIO_RADIO_SRC) & 0xffffff
- def get_build_timestamp(self):
- """
- Returns the build date/time for the FPGA image.
- The return is datetime string with the ISO 8601 format
- (YYYY-MM-DD HH:MM:SS.mmmmmm)
- """
- with self.regs:
- datestamp_rb = self.peek32(self.MB_DATESTAMP)
- if datestamp_rb > 0:
- dt_str = datetime.datetime(
- year=((datestamp_rb>>17)&0x3F)+2000,
- month=(datestamp_rb>>23)&0x0F,
- day=(datestamp_rb>>27)&0x1F,
- hour=(datestamp_rb>>12)&0x1F,
- minute=(datestamp_rb>>6)&0x3F,
- second=((datestamp_rb>>0)&0x3F))
- self.log.trace("FPGA build timestamp: {}".format(str(dt_str)))
- return str(dt_str)
- else:
- # Compatibility with FPGAs without datestamp capability
- return ''
-
- def get_git_hash(self):
- """
- Returns the GIT hash for the FPGA build.
- The return is a tuple of
- 2 numbers: (short git hash, bool: is the tree dirty?)
- """
- with self.regs:
- git_hash_rb = self.peek32(self.MB_GIT_HASH)
- git_hash = git_hash_rb & 0x0FFFFFFF
- tree_dirty = ((git_hash_rb & 0xF0000000) > 0)
- dirtiness_qualifier = 'dirty' if tree_dirty else 'clean'
- self.log.trace("FPGA build GIT Hash: {:07x} ({})".format(
- git_hash, dirtiness_qualifier))
- return (git_hash, dirtiness_qualifier)
-
def set_time_source(self, time_source, ref_clk_freq):
"""
Set time source
@@ -469,67 +354,3 @@ class MboardRegsControl(object):
self.log.trace("RX RF PLL locked")
return locked
- def get_num_timekeepers(self):
- """
- Return the number of timekeepers
- """
- with self.regs:
- return self.peek32(self.MB_NUM_TIMEKEEPERS)
-
- def get_timekeeper_time(self, tk_idx, last_pps):
- """
- Get the time in ticks
-
- Arguments:
- tk_idx: Index of timekeeper
- next_pps: If True, get time at last PPS. Otherwise, get time now.
- """
- addr_lo = \
- (self.MB_TIME_LAST_PPS_LO if last_pps else self.MB_TIME_NOW_LO) + \
- tk_idx * self.MB_TIMEKEEPER_OFFSET
- addr_hi = addr_lo + 4
- with self.regs:
- time_lo = self.peek32(addr_lo)
- time_hi = self.peek32(addr_hi)
- return time_hi << 32 | time_lo
-
-
- def set_timekeeper_time(self, tk_idx, ticks, next_pps):
- """
- Set the time in ticks
-
- Arguments:
- tk_idx: Index of timekeeper
- ticks: Time in ticks
- next_pps: If True, set time at next PPS. Otherwise, set time now.
- """
- addr_lo = \
- self.MB_TIME_EVENT_LO + tk_idx * self.MB_TIMEKEEPER_OFFSET
- addr_hi = addr_lo + 4
- addr_ctrl = \
- self.MB_TIME_CTRL + tk_idx * self.MB_TIMEKEEPER_OFFSET
- time_lo = ticks & 0xFFFFFFFF
- time_hi = (ticks > 32) & 0xFFFFFFFF
- time_ctrl = 0x2 if next_pps else 0x1
- self.log.trace("Setting time on timekeeper %d to %d %s", tk_idx, ticks,
- ("on next pps" if next_pps else "now"))
- with self.regs:
- self.poke32(addr_lo, time_lo)
- self.poke32(addr_hi, time_hi)
- self.poke32(addr_ctrl, time_ctrl)
-
- def set_tick_period(self, tk_idx, period_ns):
- """
- Set the time per tick in nanoseconds (tick period)
-
- Arguments:
- tk_idx: Index of timekeeper
- period_ns: Period in nanoseconds
- """
- addr_lo = self.MB_TIME_BASE_PERIOD_LO + tk_idx * self.MB_TIMEKEEPER_OFFSET
- addr_hi = addr_lo + 4
- period_lo = period_ns & 0xFFFFFFFF
- period_hi = (period_ns > 32) & 0xFFFFFFFF
- with self.regs:
- self.poke32(addr_lo, period_lo)
- self.poke32(addr_hi, period_hi)
diff --git a/mpm/python/usrp_mpm/periph_manager/n3xx.py b/mpm/python/usrp_mpm/periph_manager/n3xx.py
index 5510b846d..fc9a91e7d 100644
--- a/mpm/python/usrp_mpm/periph_manager/n3xx.py
+++ b/mpm/python/usrp_mpm/periph_manager/n3xx.py
@@ -43,6 +43,7 @@ N32X_DEFAULT_QSFP_DRIVER_PRESET = 'Optical'
N32X_QSFP_I2C_LABEL = 'qsfp-i2c'
N3XX_FPGA_COMPAT = (7, 0)
N3XX_MONITOR_THREAD_INTERVAL = 1.0 # seconds
+N3XX_BUS_CLK = 200e6
# Import daughterboard PIDs from their respective classes
MG_PID = Magnesium.pids[0]
@@ -525,39 +526,6 @@ class n3xx(ZynqComponents, PeriphManagerBase):
})
return device_info
- def set_device_id(self, device_id):
- """
- Sets the device ID for this motherboard.
- The device ID is used to identify the RFNoC components associated with
- this motherboard.
- """
- self.log.debug("Setting device ID to `{}'".format(device_id))
- self.mboard_regs_control.set_device_id(device_id)
-
- def get_device_id(self):
- """
- Gets the device ID for this motherboard.
- The device ID is used to identify the RFNoC components associated with
- this motherboard.
- """
- return self.mboard_regs_control.get_device_id()
-
- def get_proto_ver(self):
- """
- Return RFNoC protocol version
- """
- proto_ver = self.mboard_regs_control.get_proto_ver()
- self.log.debug("RFNoC protocol version supported by this device is {}".format(proto_ver))
- return proto_ver
-
- def get_chdr_width(self):
- """
- Return RFNoC CHDR width
- """
- chdr_width = self.mboard_regs_control.get_chdr_width()
- self.log.debug("CHDR width supported by the device is {}".format(chdr_width))
- return chdr_width
-
###########################################################################
# Clock/Time API
###########################################################################
@@ -1051,43 +1019,6 @@ class n3xx(ZynqComponents, PeriphManagerBase):
#######################################################################
# Timekeeper API
#######################################################################
- def get_num_timekeepers(self):
- """
- Return the number of timekeepers
- """
- return self.mboard_regs_control.get_num_timekeepers()
-
- def get_timekeeper_time(self, tk_idx, last_pps):
- """
- Get the time in ticks
-
- Arguments:
- tk_idx: Index of timekeeper
- next_pps: If True, get time at last PPS. Otherwise, get time now.
- """
- return self.mboard_regs_control.get_timekeeper_time(tk_idx, last_pps)
-
- def set_timekeeper_time(self, tk_idx, ticks, next_pps):
- """
- Set the time in ticks
-
- Arguments:
- tk_idx: Index of timekeeper
- ticks: Time in ticks
- next_pps: If True, set time at next PPS. Otherwise, set time now.
- """
- self.mboard_regs_control.set_timekeeper_time(tk_idx, ticks, next_pps)
-
- def set_tick_period(self, tk_idx, period_ns):
- """
- Set the time per tick in nanoseconds (tick period)
-
- Arguments:
- tk_idx: Index of timekeeper
- period_ns: Period in nanoseconds
- """
- self.mboard_regs_control.set_tick_period(tk_idx, period_ns)
-
def get_clocks(self):
"""
Gets the RFNoC-related clocks present in the FPGA design
@@ -1100,7 +1031,6 @@ class n3xx(ZynqComponents, PeriphManagerBase):
},
{
'name': 'bus_clk',
- 'freq': str(200e6),
+ 'freq': str(N3XX_BUS_CLK),
}
]
-
diff --git a/mpm/python/usrp_mpm/periph_manager/n3xx_periphs.py b/mpm/python/usrp_mpm/periph_manager/n3xx_periphs.py
index 9b83816c4..ef2372e62 100644
--- a/mpm/python/usrp_mpm/periph_manager/n3xx_periphs.py
+++ b/mpm/python/usrp_mpm/periph_manager/n3xx_periphs.py
@@ -1,5 +1,6 @@
#
# Copyright 2018 Ettus Research, a National Instruments Company
+# Copyright 2019 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
@@ -7,12 +8,11 @@
N3xx peripherals
"""
-import datetime
from usrp_mpm import lib
from usrp_mpm.sys_utils.sysfs_gpio import SysFSGPIO, GPIOBank
-from usrp_mpm.sys_utils.uio import UIO
from usrp_mpm.sys_utils import i2c_dev
from usrp_mpm.chips.ds125df410 import DS125DF410
+from usrp_mpm.periph_manager.common import MboardRegsCommon
# Map register values to SFP transport types
N3XX_SFP_TYPES = {
@@ -160,41 +160,20 @@ class BackpanelGPIO(GPIOBank):
0x7, # ddr
)
-class MboardRegsControl(object):
+class MboardRegsControl(MboardRegsCommon):
"""
Control the FPGA Motherboard registers
"""
- # Motherboard registers
- MB_COMPAT_NUM = 0x0000
- MB_DATESTAMP = 0x0004
- MB_GIT_HASH = 0x0008
- MB_SCRATCH = 0x000C
- MB_DEVICE_ID = 0x0010
- MB_RFNOC_INFO = 0x0014
- MB_CLOCK_CTRL = 0x0018
- MB_XADC_RB = 0x001C
- MB_BUS_CLK_RATE = 0x0020
- MB_BUS_COUNTER = 0x0024
- MB_SFP0_INFO = 0x0028
- MB_SFP1_INFO = 0x002C
- MB_GPIO_MASTER = 0x0030
- MB_GPIO_RADIO_SRC = 0x0034
- MB_NUM_TIMEKEEPERS = 0x0048
- # Timekeeper registers
- MB_TIME_NOW_LO = 0x1000
- MB_TIME_NOW_HI = 0x1004
- MB_TIME_EVENT_LO = 0x1008
- MB_TIME_EVENT_HI = 0x100C
- MB_TIME_CTRL = 0x1010
- MB_TIME_LAST_PPS_LO = 0x1014
- MB_TIME_LAST_PPS_HI = 0x1018
- MB_TIME_BASE_PERIOD_LO = 0x101C
- MB_TIME_BASE_PERIOD_HI = 0x1020
- MB_TIMEKEEPER_OFFSET = 12
-
- # Bitfield locations for the MB_RFNOC_INFO register.
- MB_RFNOC_INFO_PROTO_VER = 0
- MB_RFNOC_INFO_CHDR_WIDTH = 16
+ # pylint: disable=bad-whitespace
+ # Motherboard registers (on top of the ones in MboardRegsCommon)
+ MB_CLOCK_CTRL = 0x0018
+ MB_XADC_RB = 0x001C
+ MB_BUS_CLK_RATE = 0x0020
+ MB_BUS_COUNTER = 0x0024
+ MB_SFP0_INFO = 0x0028
+ MB_SFP1_INFO = 0x002C
+ MB_GPIO_MASTER = 0x0030
+ MB_GPIO_RADIO_SRC = 0x0034
# Bitfield locations for the MB_CLOCK_CTRL register.
MB_CLOCK_CTRL_PPS_SEL_INT_10 = 0 # pps_sel is one-hot encoded!
@@ -207,66 +186,10 @@ class MboardRegsControl(object):
MB_CLOCK_CTRL_MEAS_CLK_RESET = 12 # set to 1 to reset mmcm, default is 0
MB_CLOCK_CTRL_MEAS_CLK_LOCKED = 13 # locked indication for meas_clk mmcm
MB_CLOCK_CTRL_DISABLE_REF_CLK = 16 # to disable the ref_clk, write a '1'
+ # pylint: enable=bad-whitespace
def __init__(self, label, log):
- self.log = log
- self.regs = UIO(
- label=label,
- read_only=False
- )
- self.poke32 = self.regs.poke32
- self.peek32 = self.regs.peek32
-
- def get_compat_number(self):
- """get FPGA compat number
-
- This function reads back FPGA compat number.
- The return is a tuple of
- 2 numbers: (major compat number, minor compat number )
- """
- with self.regs:
- compat_number = self.peek32(self.MB_COMPAT_NUM)
- minor = compat_number & 0xff
- major = (compat_number>>16) & 0xff
- return (major, minor)
-
- def set_device_id(self, device_id):
- """
- Set device ID
- """
- with self.regs:
- self.log.trace("Writing MB_DEVICE_ID with 0x{:08X}".format(device_id))
- return self.poke32(self.MB_DEVICE_ID, device_id)
-
- def get_device_id(self):
- """
- Get device ID
- """
- with self.regs:
- reg_val = self.peek32(self.MB_DEVICE_ID)
- device_id = reg_val & 0x0000ffff
- self.log.trace("Read MB_DEVICE_ID 0x{:08X}".format(device_id))
- return device_id
-
- def get_proto_ver(self):
- """
- Return RFNoC protocol version
- """
- with self.regs:
- reg_val = self.peek32(self.MB_RFNOC_INFO)
- proto_ver = (reg_val & 0x0000ffff) >> self.MB_RFNOC_INFO_PROTO_VER
- self.log.trace("Read RFNOC_PROTO_VER 0x{:08X}".format(proto_ver))
- return proto_ver;
-
- def get_chdr_width(self):
- """
- Return RFNoC CHDR width
- """
- with self.regs:
- reg_val = self.peek32(self.MB_RFNOC_INFO)
- chdr_width = (reg_val & 0xffff0000) >> self.MB_RFNOC_INFO_CHDR_WIDTH
- self.log.trace("Read RFNOC_CHDR_WIDTH 0x{:08X}".format(chdr_width))
- return chdr_width
+ MboardRegsCommon.__init__(self, label, log)
def set_fp_gpio_master(self, value):
"""set driver for front panel GPIO
@@ -308,43 +231,6 @@ class MboardRegsControl(object):
with self.regs:
return self.peek32(self.MB_GPIO_RADIO_SRC) & 0xffffff
- def get_build_timestamp(self):
- """
- Returns the build date/time for the FPGA image.
- The return is datetime string with the ISO 8601 format
- (YYYY-MM-DD HH:MM:SS.mmmmmm)
- """
- with self.regs:
- datestamp_rb = self.peek32(self.MB_DATESTAMP)
- if datestamp_rb > 0:
- dt_str = datetime.datetime(
- year=((datestamp_rb>>17)&0x3F)+2000,
- month=(datestamp_rb>>23)&0x0F,
- day=(datestamp_rb>>27)&0x1F,
- hour=(datestamp_rb>>12)&0x1F,
- minute=(datestamp_rb>>6)&0x3F,
- second=((datestamp_rb>>0)&0x3F))
- self.log.trace("FPGA build timestamp: {}".format(str(dt_str)))
- return str(dt_str)
- else:
- # Compatibility with FPGAs without datestamp capability
- return ''
-
- def get_git_hash(self):
- """
- Returns the GIT hash for the FPGA build.
- The return is a tuple of
- 2 numbers: (short git hash, bool: is the tree dirty?)
- """
- with self.regs:
- git_hash_rb = self.peek32(self.MB_GIT_HASH)
- git_hash = git_hash_rb & 0x0FFFFFFF
- tree_dirty = ((git_hash_rb & 0xF0000000) > 0)
- dirtiness_qualifier = 'dirty' if tree_dirty else 'clean'
- self.log.trace("FPGA build GIT Hash: {:07x} ({})".format(
- git_hash, dirtiness_qualifier))
- return (git_hash, dirtiness_qualifier)
-
def set_time_source(self, time_source, ref_clk_freq):
"""
Set time source