diff options
Diffstat (limited to 'mpm/python/usrp_mpm/simulator')
-rw-r--r-- | mpm/python/usrp_mpm/simulator/CMakeLists.txt | 2 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/simulator/chdr_endpoint.py | 3 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/simulator/config.py | 80 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/simulator/hardware_presets.py | 10 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/simulator/rfnoc_graph.py | 6 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/simulator/sim_dboard.py | 34 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/simulator/sim_dboard_catalina.py | 33 |
7 files changed, 124 insertions, 44 deletions
diff --git a/mpm/python/usrp_mpm/simulator/CMakeLists.txt b/mpm/python/usrp_mpm/simulator/CMakeLists.txt index 21f281e52..ef3c9bc8c 100644 --- a/mpm/python/usrp_mpm/simulator/CMakeLists.txt +++ b/mpm/python/usrp_mpm/simulator/CMakeLists.txt @@ -12,7 +12,7 @@ set(USRP_MPM_FILES ${USRP_MPM_FILES}) set(USRP_MPM_SIMULATOR_FILES ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_SOURCE_DIR}/sim_dboard.py - ${CMAKE_CURRENT_SOURCE_DIR}/sim_dboard_catalina.py + ${CMAKE_CURRENT_SOURCE_DIR}/hardware_presets.py ${CMAKE_CURRENT_SOURCE_DIR}/chdr_endpoint.py ${CMAKE_CURRENT_SOURCE_DIR}/noc_block_regs.py ${CMAKE_CURRENT_SOURCE_DIR}/rfnoc_graph.py diff --git a/mpm/python/usrp_mpm/simulator/chdr_endpoint.py b/mpm/python/usrp_mpm/simulator/chdr_endpoint.py index 17d707ae7..bca7f9c69 100644 --- a/mpm/python/usrp_mpm/simulator/chdr_endpoint.py +++ b/mpm/python/usrp_mpm/simulator/chdr_endpoint.py @@ -36,7 +36,8 @@ class ChdrEndpoint: self.send_queue = SelectableQueue() self.send_wrapper = SendWrapper(self.send_queue) - self.graph = RFNoCGraph(self.get_default_nodes(), self.log, 1, self.send_wrapper, CHDR_W) + self.graph = RFNoCGraph(self.get_default_nodes(), self.log, 0, self.send_wrapper, + CHDR_W, config.hardware.rfnoc_device_type) self.thread = Thread(target=self.socket_worker, daemon=True) self.thread.start() diff --git a/mpm/python/usrp_mpm/simulator/config.py b/mpm/python/usrp_mpm/simulator/config.py index a5f07950d..6698f9fd0 100644 --- a/mpm/python/usrp_mpm/simulator/config.py +++ b/mpm/python/usrp_mpm/simulator/config.py @@ -12,6 +12,47 @@ it identifies itself as. import configparser from .sample_source import sinks, sources, NullSamples +from .hardware_presets import presets +import numbers + +class HardwareDescriptor: + """This class contains the various magic numbers that are needed to + identify specific hardware to UHD + """ + def __init__(self, product, uhd_device_type, description, pid, serial_num, dboard_class, rfnoc_device_type): + """ + product -> MPM Product, stored in PeriphManager.mboard_info['product'] + e.g. "e320", "b200" + uhd_device_type -> A device_type string recognized by UHD's device discovery. + This is the same identifier that goes into --args=type="..." + e.g. "e3xx", "n3xx" + description -> MPM description, user visible. Stored in PeriphManager.description + pid -> motherboard pid, stored as a key in PeriphManager.pids + e.g. 0xE320 + serial_num -> Device Specific serial number. + e.g. "3196D2A" + dboard_class -> Python class which should be instantiated as a daughterboard + rfnoc_device_type -> Device Type read from NoC Core Registers + see defaults.hpp:device_type_t + e.g. 0xE320, 0xA300 + """ + self.product = product + self.uhd_device_type = uhd_device_type + self.description = description + self.pid = pid + self.serial_num = serial_num + self.dboard_class = dboard_class + self.rfnoc_device_type = rfnoc_device_type + + @classmethod + def from_dict(cls, dict): + return cls(dict['product'], + dict['uhd_device_type'], + dict['description'], + dict['pid'], + dict['serial_num'], + dict['dboard_class'], + dict['rfnoc_device_type']) class Config: """This class represents a configuration file for the usrp simulator. @@ -24,18 +65,41 @@ class Config: sample_source.py). The other key value pairs in the section are passed to the source/sink constructor as strings through **kwargs """ - def __init__(self, source_gen, sink_gen): + def __init__(self, source_gen, sink_gen, hardware): self.source_gen = source_gen self.sink_gen = sink_gen + self.hardware = hardware @classmethod - def from_path(cls, path): + def from_path(cls, log, path): """Parse a config .ini file from a path""" parser = configparser.ConfigParser() parser.read(path) - source_gen = Config._read_sample_section(parser['sample.source'], sources) - sink_gen = Config._read_sample_section(parser['sample.sink'], sinks) - return cls(source_gen, sink_gen) + source_gen = NullSamples + # Here we read data from a section and then pop it. + # For some reason, you can't iterate over a section (needed to make a dict), + # after its been popped. + if 'sample.source' in parser: + source_gen = Config._read_sample_section(parser['sample.source'], sources) + parser.pop('sample.source') + sink_gen = NullSamples + if 'sample.sink' in parser: + sink_gen = Config._read_sample_section(parser['sample.sink'], sinks) + parser.pop('sample.sink') + hardware_section = dict(parser['hardware']) + preset_name = hardware_section.get('preset', None) + hardware_preset = presets[preset_name].copy() if preset_name is not None else {} + hardware_preset.update(hardware_section) + hardware = HardwareDescriptor.from_dict(hardware_preset) + parser.pop('hardware') + for unused_section in parser: + # Python sticks this into all config files + if unused_section == 'DEFAULT': + continue + # This helps stop you from shooting yourself in the foot when you add + # the [sampel.sink] section + log.warning("Unrecognized section in config file: {}".format(unused_section)) + return cls(source_gen, sink_gen, hardware) @staticmethod def _read_sample_section(section, lookup): @@ -49,4 +113,8 @@ class Config: @classmethod def default(cls): """Return a default config""" - return cls(NullSamples, NullSamples) + hardware = dict(presets['E320']) + # For the uninitiated, this is how you spell Fake Device in hex + hardware['serial_num'] = "FA4EDE7" + hardware = HardwareDescriptor.from_dict(hardware) + return cls(NullSamples, NullSamples, hardware) diff --git a/mpm/python/usrp_mpm/simulator/hardware_presets.py b/mpm/python/usrp_mpm/simulator/hardware_presets.py new file mode 100644 index 000000000..b6747bb88 --- /dev/null +++ b/mpm/python/usrp_mpm/simulator/hardware_presets.py @@ -0,0 +1,10 @@ +presets = {} + +presets['E320'] = { + 'product': "e320", + 'uhd_device_type': "e3xx", + 'description': "E320-Series Device - SIMULATED", + 'pid': 0xE320, + 'dboard_class': "SimulatedCatalinaDboard", + 'rfnoc_device_type': 0xE320 +} diff --git a/mpm/python/usrp_mpm/simulator/rfnoc_graph.py b/mpm/python/usrp_mpm/simulator/rfnoc_graph.py index ada6e70b0..a2b536ed2 100644 --- a/mpm/python/usrp_mpm/simulator/rfnoc_graph.py +++ b/mpm/python/usrp_mpm/simulator/rfnoc_graph.py @@ -148,7 +148,7 @@ class RFNoCGraph: It serves as an interface between the ChdrEndpoint and the individual blocks/nodes. """ - def __init__(self, graph_list, log, device_id, send_wrapper, chdr_w): + def __init__(self, graph_list, log, device_id, send_wrapper, chdr_w, rfnoc_device_id): self.log = log.getChild("Graph") self.device_id = device_id self.stream_spec = StreamSpec() @@ -173,8 +173,8 @@ class RFNoCGraph: (NocBlockPort(0, 1), StreamEndpointPort(0, 1)) ] self.regs = NocBlockRegs(self.log, 1 << 16, True, 1, [radio], len(self.stream_ep), 1, - 0xE320, adj_list, 8, 1, self.get_stream_spec, self.radio_tx_cmd, - self.radio_tx_stop) + rfnoc_device_id, adj_list, 8, 1, self.get_stream_spec, + self.radio_tx_cmd, self.radio_tx_stop) def radio_tx_cmd(self, sep_block_id): """Triggers the creation of a ChdrOutputStream in the ChdrEndpoint using diff --git a/mpm/python/usrp_mpm/simulator/sim_dboard.py b/mpm/python/usrp_mpm/simulator/sim_dboard.py index a264eae9c..90f8be724 100644 --- a/mpm/python/usrp_mpm/simulator/sim_dboard.py +++ b/mpm/python/usrp_mpm/simulator/sim_dboard.py @@ -7,6 +7,11 @@ from usrp_mpm.dboard_manager import DboardManagerBase from usrp_mpm.mpmlog import get_logger from usrp_mpm.mpmutils import to_native_str +registry = {} + +def register_dboard_class(cls): + registry[cls.__name__] = cls + class SimulatedDboardBase(DboardManagerBase): """ A class to simulate daughterboards in a simulated device. @@ -57,3 +62,32 @@ class SimulatedDboardBase(DboardManagerBase): self.log.debug("Called {} with args: {}".format(prop_name, args)) return func(*args) setattr(self, prop_name, wrapped_func) + +class SimulatedCatalinaDboard(SimulatedDboardBase): + pids = [0x0110] + + extra_methods = [ + ("set_gain", lambda target, gain: gain), + ("catalina_tune", lambda which, freq: freq), + ("set_bw_filter", lambda which, freq: freq), + "set_dc_offset_auto", + "set_iq_balance_auto", + "set_agc", + "set_active_chains", + "set_timing_mode", + "data_port_loopback" + ] + + def __init__(self, slot_idx, clock_rate_cb, **kwargs): + super().__init__(slot_idx, **kwargs) + self.clock_rate_cb = clock_rate_cb + self.master_clock_rate = 122.88e6 + + def get_master_clock_rate(self): + return self.master_clock_rate + + def set_catalina_clock_rate(self, rate): + self.clock_rate_cb(rate) + return rate + +register_dboard_class(SimulatedCatalinaDboard) diff --git a/mpm/python/usrp_mpm/simulator/sim_dboard_catalina.py b/mpm/python/usrp_mpm/simulator/sim_dboard_catalina.py deleted file mode 100644 index 4e46d1410..000000000 --- a/mpm/python/usrp_mpm/simulator/sim_dboard_catalina.py +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright 2020 Ettus Research, a National Instruments Brand -# -# SPDX-License-Identifier: GPL-3.0-or-later -# -from .sim_dboard import SimulatedDboardBase - -class SimulatedCatalinaDboard(SimulatedDboardBase): - pids = [0x0110] - - extra_methods = [ - ("set_gain", lambda target, gain: gain), - ("catalina_tune", lambda which, freq: freq), - ("set_bw_filter", lambda which, freq: freq), - "set_dc_offset_auto", - "set_iq_balance_auto", - "set_agc", - "set_active_chains", - "set_timing_mode", - "data_port_loopback" - ] - - def __init__(self, slot_idx, clock_rate_cb, **kwargs): - super().__init__(slot_idx, **kwargs) - self.clock_rate_cb = clock_rate_cb - self.master_clock_rate = 122.88e6 - - def get_master_clock_rate(self): - return self.master_clock_rate - - def set_catalina_clock_rate(self, rate): - self.clock_rate_cb(rate) - return rate |