aboutsummaryrefslogtreecommitdiffstats
path: root/mpm/python/usrp_mpm/periph_manager/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'mpm/python/usrp_mpm/periph_manager/base.py')
-rw-r--r--mpm/python/usrp_mpm/periph_manager/base.py264
1 files changed, 125 insertions, 139 deletions
diff --git a/mpm/python/usrp_mpm/periph_manager/base.py b/mpm/python/usrp_mpm/periph_manager/base.py
index be7600333..4ae30778a 100644
--- a/mpm/python/usrp_mpm/periph_manager/base.py
+++ b/mpm/python/usrp_mpm/periph_manager/base.py
@@ -177,7 +177,7 @@ class PeriphManagerBase(object):
###########################################################################
def __init__(self):
# Note: args is a dictionary.
- assert len(self.pids) > 0
+ assert self.pids
assert self.mboard_eeprom_magic is not None
self.dboards = []
self._default_args = ""
@@ -241,14 +241,17 @@ class PeriphManagerBase(object):
If no EEPROM is defined, returns empty values.
"""
- if len(self.mboard_eeprom_addr):
+ if self.mboard_eeprom_addr:
self.log.trace("Reading EEPROM from address `{}'..."
.format(self.mboard_eeprom_addr))
- if (not get_eeprom_paths(self.mboard_eeprom_addr)):
- raise RuntimeError("No EEPROM found at address `{}'"
- .format(self.mboard_eeprom_addr))
+ eeprom_paths = get_eeprom_paths(self.mboard_eeprom_addr)
+ if not eeprom_paths:
+ self.log.error("Could not identify EEPROM paths for %s!",
+ self.mboard_eeprom_addr)
+ return {}, b''
+ self.log.trace("Found mboard EEPROM path: %s", eeprom_paths[0])
(eeprom_head, eeprom_rawdata) = eeprom.read_eeprom(
- get_eeprom_paths(self.mboard_eeprom_addr)[0],
+ eeprom_paths[0],
self.mboard_eeprom_offset,
eeprom.MboardEEPROM.eeprom_header_format,
eeprom.MboardEEPROM.eeprom_header_keys,
@@ -512,6 +515,22 @@ class PeriphManagerBase(object):
###########################################################################
# Misc device status controls and indicators
###########################################################################
+ 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.
+ """
+ raise NotImplementedError("set_device_id() not implemented.")
+
+ 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.
+ """
+ raise NotImplementedError("get_device_id() not implemented.")
+
def get_init_status(self):
"""
Returns the status of the device after its initialization (that happens
@@ -592,6 +611,20 @@ 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
###########################################################################
@@ -670,64 +703,10 @@ class PeriphManagerBase(object):
self.log.trace("Component info: {}".format(metadata))
# Convert all values to str
return dict([a, str(x)] for a, x in metadata.items())
- else:
- self.log.trace("Component not found in updateable components: {}"
- .format(component_name))
- return {}
-
- ###########################################################################
- # Crossbar control
- ###########################################################################
- @no_claim
- def get_num_xbars(self):
- """
- Returns the number of crossbars instantiated in the current design
- """
- return 1 # FIXME
-
- @no_claim
- def get_num_blocks(self, xbar_index):
- """
- Returns the number of blocks connected to crossbar with index
- xbar_index.
-
- xbar_index -- The index of the crossbar that's being queried.
- docstring for get_num_blocks"""
- # FIXME udev lookup
- xbar_sysfs_path = '/sys/class/rfnoc_crossbar/crossbar{}/nports'.format(
- xbar_index
- )
- return int(open(xbar_sysfs_path).read().strip()) - \
- self.get_base_port(xbar_index)
-
- @no_claim
- def get_base_port(self, xbar_index):
- """
- Returns the index of the first port which is connected to an RFNoC
- block. Example: Assume there are two SFPs connected to the crossbar, and
- one DMA engine for CHDR traffic. The convention would be to connect
- those to ports 0, 1, and 2, respectively. This makes port 3 the first
- block to be connected to an RFNoC block.
-
- xbar_index -- The index of the crossbar that's being queried
- """
- return self.crossbar_base_port
-
- def set_xbar_local_addr(self, xbar_index, local_addr):
- """
- Program crossbar xbar_index to have the local address local_addr.
- """
- # FIXME udev lookup
- xbar_sysfs_path = '/sys/class/rfnoc_crossbar/crossbar{}/local_addr'.format(
- xbar_index
- )
- laddr_value = "0x{:X}".format(local_addr)
- self.log.trace("Setting local address for xbar {} to {}.".format(
- xbar_sysfs_path, laddr_value
- ))
- with open(xbar_sysfs_path, "w") as xbar_file:
- xbar_file.write(laddr_value)
- return True
+ # else:
+ self.log.trace("Component not found in updateable components: {}"
+ .format(component_name))
+ return {}
##########################################################################
# Mboard Sensors
@@ -823,86 +802,44 @@ class PeriphManagerBase(object):
#######################################################################
# Transport API
#######################################################################
- def request_xport(
- self,
- dst_address,
- suggested_src_address,
- xport_type,
- ):
- """
- When setting up a CHDR connection, this is the first call to be
- made. This function will return a list of dictionaries, each
- describing a way to open an CHDR connection. The list of dictionaries
- is sorted by preference, meaning that the caller should use the first
- option, if possible.
- All transports requested are bidirectional.
-
- The callee must maintain a lock on the available CHDR xports. After
- calling request_xport(), the caller needs to pick one of the
- dictionaries, possibly amend data (e.g., if the connection is an
- Ethernet connection, then we need to know the source port, but more
- details on that in commit_xport()'s documentation).
- One way to implement a lock is to simply lock a mutex here and
- unlock it in commit_xport(), even though there are probably more
- nuanced solutions.
+ def get_chdr_link_types(self):
+ """
+ Return a list of ways how the UHD session can connect to this device to
+ initiate CHDR traffic.
- Arguments:
- dst_sid -- The destination part of the connection, i.e., which
- RFNoC block are we connecting to. Example: 0x0230
- suggested_src_sid -- The source part of the connection, i.e.,
- what's the source address of packets going to
- the destination at dst_sid. This is a
- suggestion, MPM can override this. Example:
- 0x0001.
- xport_type -- One of the following strings: CTRL, ASYNC_MSG,
- TX_DATA, RX_DATA. See also xports_type_t in UHD.
-
- The return value is a list of dictionaries. Every dictionary has
- the following key/value pairs:
- - type: Type of transport, e.g., "UDP", "liberio".
- - ipv4 (UDP only): IPv4 address to connect to.
- - port (UDP only): IP port to connect to.
- - send_sid: String version of the SID used for this transport. This is
- the definitive version of the SID, the suggested_src_address
- can be ignored at this point.
- - allocation: This is an integer value which represents a score of
- how much bandwidth is used. Note: Currently does not
- have any unit, is just a counter. Higher numbers mean
- higher utilization. RX means device to UHD, for
- example, committing an RX streamer would increase this
- value.
- This key is optional, MPM does not have to provide it.
- If the allocation affects the preference, it will be
- factored into the order of the results, meaning the
- caller does not strictly have to check its value even if
- the transport option with the smallest allocation is
- preferred.
-
- Note: The dictionary may include other keys which should be ignored,
- or at the very least, kept intact. commit_xport() might be requiring
- them.
- """
- raise NotImplementedError("request_xport() not implemented.")
-
- def commit_xport(self, xport_info):
- """
- When setting up a CHDR connection, this is the second call to be
- made.
+ The return value is a list of strings. Every string is a key for a
+ transport type. Values include:
+ - "udp": Means this device can be reached via UDP
+ - "liberio": Means this device can be reached via Liberio (local DMA)
- Arguments:
- xport_info -- A dictionary (string -> string). The dictionary must
- have been originally created by request_xport(), but
- additional key/value pairs need to be added.
+ The list is filtered based on what the device knows about where the UHD
+ session is. For example, on an N310, it will only either return "UDP"
+ or "Liberio", depending on if we're remotely launching UHD, or locally.
- All transports need to also provide:
- - rx_mtu: In bytes, the max number of bytes going from device to UHD
- - tx_mtu: In bytes, the max number of bytes going from UHD to device
+ In order to get further information about how to connect to the device,
+ the keys returned from this function can be used with
+ get_chdr_link_options().
+ """
+ raise NotImplementedError("get_chdr_link_types() not implemented.")
- UDP transports need to also provide:
- - src_ipv4: IPv4 address the connection is coming from.
- - src_port: IP port the connection is coming from.
+ def get_chdr_link_options(self, xport_type):
"""
- raise NotImplementedError("commit_xport() not implemented.")
+ Returns a list of dictionaries. Every dictionary contains information
+ about one way to connect to this device in order to initiate CHDR
+ traffic.
+
+ The interpretation of the return value is very highly dependant on the
+ transport type (xport_type).
+ For UDP, the every entry of the list has the following keys:
+ - ipv4 (IP Address)
+ - port (UDP port)
+ - link_rate (bps of the link, e.g. 10e9 for 10GigE)
+
+ For Liberio, every entry has the following keys:
+ - tx_dev: TX device (/dev/tx-dma*)
+ - rx_dev: RX device (/dev/rx-dma*)
+ """
+ raise NotImplementedError("get_chdr_link_options() not implemented.")
#######################################################################
# Claimer API
@@ -927,3 +864,52 @@ class PeriphManagerBase(object):
"""
self.log.debug("Device was unclaimed. No actions defined.")
+ #######################################################################
+ # Timekeeper API
+ #######################################################################
+ def get_num_timekeepers(self):
+ """
+ Return the number of timekeepers
+ """
+ raise NotImplementedError("get_num_timekeepers() not implemented.")
+
+ 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.
+ """
+ raise NotImplementedError(
+ "get_ticks_now({}, {}) not implemented.".format(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.
+ """
+ raise NotImplementedError(
+ "set_ticks_last_pps({}, {}, {}) not implemented."
+ .format(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
+ """
+ raise NotImplementedError(
+ "set_tick_period({}) not implemented.".format(tk_idx, period_ns))
+
+ def get_clocks(self):
+ """
+ Gets the RFNoC-related clocks present in the FPGA design
+ """
+ raise NotImplementedError("get_clocks() not implemented.")