def rm_overlay_safe(overlay_name): """ Only remove an overlay if it's already applied. """ if overlay_name in list(list_overlays(applied_only=True).keys()): rm_overlay(overlay_name) else: get_logger("DTO").debug( "Overlay `{}' was not loaded, not removing.".format(overlay_name))
def _get_remote_mac_addr(remote_addr): " Basically an ARP lookup " addrs = ip2.get_neighbours(dst=remote_addr) if len(addrs) > 1: get_logger('get_mac_addr').warning( "More than one device with the same IP address `{}' found. " "Picking entry at random.".format(ip_addr)) if not addrs: return None return addrs[0].get_attr('NDA_LLADDR')
def apply_overlay(overlay_name): """ Applies the given overlay. Does not check if the overlay is loaded. """ get_logger("DTO").trace("Applying overlay `{}'...".format(overlay_name)) overlay_path = os.path.join(SYSFS_OVERLAY_BASE_DIR, overlay_name) if not os.path.exists(overlay_path): os.mkdir(overlay_path) open(os.path.join(SYSFS_OVERLAY_BASE_DIR, overlay_name, 'path'), 'w').write("{}.dtbo".format(overlay_name))
def rm_overlay_safe(overlay_name): """ Only remove an overlay if it's already applied. """ if overlay_name in list(list_overlays(applied_only=True).keys()): rm_overlay(overlay_name) else: get_logger("DTO").debug( "Overlay `{}' was not loaded, not removing.".format(overlay_name) )
def apply_overlay(overlay_name): """ Applies the given overlay. Does not check if the overlay is loaded. """ get_logger("DTO").trace("Applying overlay `{}'...".format(overlay_name)) overlay_path = os.path.join(SYSFS_OVERLAY_BASE_DIR, overlay_name) if not os.path.exists(overlay_path): os.mkdir(overlay_path) open( os.path.join(SYSFS_OVERLAY_BASE_DIR, overlay_name, 'path'), 'w' ).write("{}.dtbo".format(overlay_name))
def _get_remote_mac_addr(remote_addr): " Basically an ARP lookup " addrs = ip2.get_neighbours(dst=remote_addr) if len(addrs) > 1: get_logger('get_mac_addr').warning( "More than one device with the same IP address `{}' found. " "Picking entry at random.".format(ip_addr) ) if not addrs: return None return addrs[0].get_attr('NDA_LLADDR')
def _get_local_mac_addr(ip_addr): " Lookup MAC addr of local device " if_addr = ip2.get_addr( match=lambda x: x.get_attr('IFA_ADDRESS') == ip_addr) if len(if_addr) == 0: return None if len(if_addr) > 1: get_logger('get_mac_addr').warning( "More than one device with the same IP address `{}' found. " "Picking entry at random.".format(ip_addr)) iface_idx = if_addr[0]['index'] if_info = ip2.get_links(iface_idx)[0] return if_info.get_attr('IFLA_ADDRESS')
def get_mac_addr(remote_addr): """ return MAC address of a remote host already discovered or None if no host entry was found """ with IPRoute() as ip2: addrs = ip2.get_neighbours(dst=remote_addr) if len(addrs) > 1: get_logger('get_mac_addr').warning("More than one device with the " "same IP address found. " "Picking entry at random") if not addrs: return None return addrs[0].get_attr('NDA_LLADDR')
def apply_overlay_safe(overlay_name): """ Only apply an overlay if it's not yet applied. Finally, checks that the overlay was applied and throws an exception if not. """ if is_applied(overlay_name): get_logger("DTO").debug( "Overlay `{}' was already applied, not applying again.".format( overlay_name)) else: apply_overlay(overlay_name) if not is_applied(overlay_name): raise RuntimeError("Failed to apply overlay `{}'".format(overlay_name))
def _get_local_mac_addr(ip_addr): " Lookup MAC addr of local device " if_addr = ip2.get_addr( match=lambda x: x.get_attr('IFA_ADDRESS') == ip_addr ) if len(if_addr) == 0: return None if len(if_addr) > 1: get_logger('get_mac_addr').warning( "More than one device with the same IP address `{}' found. " "Picking entry at random.".format(ip_addr) ) iface_idx = if_addr[0]['index'] if_info = ip2.get_links(iface_idx)[0] return if_info.get_attr('IFLA_ADDRESS')
def do_update_cpld(filename, daughterboards): """ Carry out update process for the CPLD :param filename: path (on device) to the new CPLD image :param daughterboards: iterable containing dboard numbers to update :return: True on success, False otherwise """ logger = get_logger('update_cpld') logger.info("Programming CPLD of dboards {} with image {}".format(daughterboards, filename)) if not daughterboards: logger.error("Invalid daughterboard selection.") return False if not os.path.exists(filename): logger.error("CPLD image file {} not found".format(filename)) return False if not check_fpga_state(): logger.error("CPLD lines are routed through fabric, FPGA is not programmed, giving up") return False regs = MboardRegsControl('mboard-regs', logger) compat_maj = regs.get_compat_number()[0] mode = 'axi_bitq' if compat_maj > 3 else 'sysfsgpio' logger.info("FPGA has compatibilty number {} using {}".format(compat_maj, mode)) config = CONFIGS[mode] if check_openocd_files(config['files'], logger=logger): logger.trace("Found required OpenOCD files.") else: # check_openocd_files logs errors return False for dboard in daughterboards: logger.info("Updating daughterboard slot {}...".format(dboard)) if mode == 'sysfsgpio': cmd = ["openocd", "-f", (config['files'][int(dboard, 10)]).strip(), "-f", (config['files'][2]).strip(), "-c", config['cmd'] % filename] else: uio_id = find_axi_bitq_uio(int(dboard, 10)) if uio_id < 0: logger.error("Failed to find axi_bitq uio devices, \ make sure overlays are up to date") continue cmd = ["openocd", "-c", config['cmd'][0] % (uio_id, AXI_BITQ_BUS_CLK, AXI_BITQ_ADAPTER_SPEED), "-f", (config['files'][0]).strip(), "-c", config['cmd'][1] % filename] logger.trace("Update CPLD CMD: {}".format(" ".join(cmd))) subprocess.call(cmd) logger.trace("Done programming CPLD...") return True
def __init__(self, label=None, path=None, length=None, read_only=True, offset=None): self.log = get_logger('UIO') if label is None: self._path = path self.log.trace("Using UIO device `{0}'".format(path)) uio_device = os.path.split(path)[-1] self.log.trace("Getting map info for UIO device `{0}'".format(uio_device)) map_info = get_uio_map_info(uio_device, 0) # Python can't tell the size of a uio device by itself assert length is not None else: self.log.trace("Using UIO device by label `{0}'".format(label)) self._path, map_info = find_uio_device(label, self.log) # TODO If we ever support multiple maps, check if this is correct... offset = offset or map_info['offset'] assert offset == 0 # ...and then remove this line length = length or map_info['size'] self.log.trace("UIO device is being opened read-{0}.".format( "only" if read_only else "write")) if self._path is None: self.log.error("Could not find a UIO device for label {0}".format(label)) raise RuntimeError("Could not find a UIO device for label {0}".format(label)) self._read_only = read_only # Our UIO objects are managed in C++ land, which gives us more granular control over # opening and closing self._uio = lib.types.mmap_regs_iface(self._path, length, offset, self._read_only, False) # Reference counter for safely __enter__ and __exit__-ing self._ref_count = 0
def __init__(self): # Note: args is a dictionary. assert len(self.pids) > 0 assert self.mboard_eeprom_magic is not None self.dboards = [] self._default_args = "" # Set up logging self.log = get_logger('PeriphManager') self.claimed = False try: self._eeprom_head, self._eeprom_rawdata = \ self._read_mboard_eeprom() self.mboard_info = self._get_mboard_info(self._eeprom_head) self.log.info("Device serial number: {}" .format(self.mboard_info.get('serial', 'n/a'))) self.dboard_infos = self._get_dboard_eeprom_info() self.device_info = \ self.generate_device_info( self._eeprom_head, self.mboard_info, self.dboard_infos ) except Exception as ex: self.log.error("Failed to initialize device: %s", str(ex)) self._device_initialized = False self._initialization_status = str(ex) super(PeriphManagerBase, self).__init__()
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 self.dboards = [] self._default_args = "" # Set up logging self.log = get_logger('PeriphManager') self.claimed = False try: self._eeprom_head, self._eeprom_rawdata = \ self._read_mboard_eeprom() self.mboard_info = self._get_mboard_info(self._eeprom_head) self.log.info("Device serial number: {}" .format(self.mboard_info.get('serial', 'n/a'))) self.dboard_infos = self._get_dboard_eeprom_info() self.device_info = \ self.generate_device_info( self._eeprom_head, self.mboard_info, self.dboard_infos ) except BaseException as ex: self.log.error("Failed to initialize device: %s", str(ex)) self._device_initialized = False self._initialization_status = str(ex) super(PeriphManagerBase, self).__init__()
def __init__(self, identifiers, use_mask, ddr, init_value=0, parent_dev=None): assert (use_mask & ddr) == ddr self.log = get_logger("SysFSGPIO") self._identifiers = identifiers self._use_mask = use_mask self._ddr = ddr self._init_value = init_value self.log.trace( "Generating SysFSGPIO object for identifiers `{}'...".format( identifiers)) self._gpio_dev, self._map_info = \ find_gpio_device(identifiers, parent_dev, self.log) if self._gpio_dev is None: error_msg = \ "Could not find GPIO device with identifiers `{}'.".format(identifiers) self.log.error(error_msg) raise RuntimeError(error_msg) self.log.trace("GPIO base number is {}".format( self._map_info.get("sys_number"))) self._base_gpio = self._map_info.get("sys_number") self.init(self._map_info['ngpio'], self._base_gpio, self._use_mask, self._ddr, self._init_value)
def __init__(self, regs_iface, freq=None, parent_log=None): self.log = \ parent_log.getChild("ADF400x") if parent_log is not None \ else get_logger("ADF400x") self.regs_iface = regs_iface assert hasattr(self.regs_iface, 'transfer24_8') self.transfer24_8 = regs_iface.transfer24_8 # Instantiate our own copy of the register mapping and update some values self.adf400x_regs = ADF400xRegs() # N counter = fVCO/PFD self.adf400x_regs.n_counter = 4 self.adf400x_regs.charge_pump_current_1 = 7 self.adf400x_regs.charge_pump_current_2 = 7 # Set MUXOUT to Digital Lock Detect self.adf400x_regs.muxout = ADF400xRegs.MUXOUT_DLD self.adf400x_regs.counter_reset = ADF400xRegs.COUNTER_RESET_NORMAL self.adf400x_regs.phase_detector_polarity = ADF400xRegs.PHASE_DETECTOR_POLARITY_POS # Turn on Charge Pump self.adf400x_regs.charge_pump_mode = ADF400xRegs.CHARGE_PUMP_NORMAL # Set the N counter if freq is None: freq = DEFAULT_REF_CLOCK_FREQ self._set_ref_counter(freq) # Now initialize the ADF400x self.program_regs()
def __init__(self, args): # Note: args is a dictionary. assert len(self.pids) > 0 assert self.mboard_eeprom_magic is not None self.dboards = [] # Set up logging self.log = get_logger('PeriphManager') self.claimed = False # The _init_args are a check for the args that passed into init(). This # should always be a dictionary (or dictionary-like object). self._init_args = {} try: self._init_mboard_with_eeprom() self._default_args = self._update_default_args(args) self.log.debug("Using default args: {}".format(self._default_args)) self._init_mboard_overlays(self._eeprom_head, self._default_args) override_db_pids_str = self._default_args.get('override_db_pids') if override_db_pids_str: override_db_pids = [ int(x, 0) for x in override_db_pids_str.split(",") ] else: override_db_pids = [] self._init_dboards(override_db_pids, self._default_args) self._device_initialized = True self._initialization_status = "No errors." except Exception as ex: self.log.error("Failed to initialize device: %s", str(ex)) self._device_initialized = False self._initialization_status = str(ex)
def __init__(self, slot_idx, **kwargs): super(Magnesium, self).__init__(slot_idx, **kwargs) self.log = get_logger("Magnesium-{}".format(slot_idx)) self.log.trace("Initializing Magnesium daughterboard, slot index %d", self.slot_idx) self.rev = int(self.device_info['rev']) self.log.trace("This is a rev: {}".format(chr(65 + self.rev))) # This is a default ref clock freq, it must be updated before init() is # called! self.ref_clock_freq = None # These will get updated during init() self.master_clock_rate = None self.current_jesd_rate = None # Predeclare some attributes to make linter happy: self.lmk = None self._port_expander = None self.mykonos = None self.eeprom_fs = None self.eeprom_path = None self.cpld = None self._init_args = {} # Now initialize all peripherals. If that doesn't work, put this class # into a non-functional state (but don't crash, or we can't talk to it # any more): try: self._init_periphs() self._periphs_initialized = True except Exception as ex: self.log.error("Failed to initialize peripherals: %s", str(ex)) self._periphs_initialized = False
def __init__( self, regs_iface, lmk, phase_dac, offset, radio_clk_freq, ref_clk_freq, fine_delay_step, init_pdac_word, target_values, dac_spi_addr_val, slot_idx ): self._iface = regs_iface self.log = get_logger("Sync-{}".format(slot_idx)) self.slot_idx = slot_idx self.peek32 = lambda addr: self._iface.peek32(addr + offset) self.poke32 = lambda addr, data: self._iface.poke32(addr + offset, data) self.lmk = lmk self.phase_dac = phase_dac self.radio_clk_freq = radio_clk_freq self.ref_clk_freq = ref_clk_freq self.fine_delay_step = fine_delay_step self.current_phase_dac_word = init_pdac_word self.lmk_vco_freq = self.lmk.get_vco_freq() self.target_values = target_values self.dac_spi_addr_val = dac_spi_addr_val self.meas_clk_freq = 170.542641116e6 # Bump this whenever we stop supporting older FPGA images or boards. # YYMMDDHH self.oldest_compat_version = 0x17060111 # Bump this whenever changes are made to this MPM host code. self.current_version = 0x18011210
def do_update_cpld(filename, updater_mode): """ Carry out update process for the CPLD :param filename: path (on device) to the new CPLD image :param updater_mode: the updater method to use- Either flash or legacy :return: True on success, False otherwise """ assert updater_mode in ('legacy', 'flash'), \ f"Invalid updater method {updater_mode} given" logger = get_logger('update_cpld') logger.info("Programming CPLD of mboard with image {} using {} mode" .format(filename, updater_mode)) if not os.path.exists(filename): logger.error("CPLD image file {} not found".format(filename)) return False if updater_mode == 'legacy': return jtag_cpld_update(filename, logger) if updater_mode == 'flash': cpld_spi_node = dt_symbol_get_spidev('mb_cpld') regs = MboardCPLD(cpld_spi_node, logger) reconfig_engine_offset = 0x40 cpld_min_revision = 0x19100108 flash_control = Max10CpldFlashCtrl(logger, regs, reconfig_engine_offset, cpld_min_revision) return flash_control.update(filename) return False
def apply_overlay_safe(overlay_name): """ Only apply an overlay if it's not yet applied. Finally, checks that the overlay was applied and throws an exception if not. """ if is_applied(overlay_name): get_logger("DTO").debug( "Overlay `{}' was already applied, not applying again.".format( overlay_name ) ) else: apply_overlay(overlay_name) if not is_applied(overlay_name): raise RuntimeError("Failed to apply overlay `{}'".format(overlay_name))
def __init__(self, slot_idx, **kwargs): DboardManagerBase.__init__(self, slot_idx, **kwargs) self.log = get_logger("ZBX-{}".format(slot_idx)) self.log.trace("Initializing ZBX daughterboard, slot index %d", self.slot_idx) # local variable to track if PLL ref clock is enabled for the CPLD logic self._clock_enabled = False # Interface with MB HW if 'db_iface' not in kwargs: self.log.error("Required DB Iface was not provided!") raise RuntimeError("Required DB Iface was not provided!") self.db_iface = kwargs['db_iface'] self.eeprom_symbol = f"db{slot_idx}_eeprom" eeprom = self._get_eeprom() self._assert_rev_compatibility(eeprom["rev_compat"]) # Initialize daughterboard CPLD control self.poke_cpld = self.db_iface.poke_db_cpld self.peek_cpld = self.db_iface.peek_db_cpld self.regs = zbx_cpld_regs_t() self._spi_addr = self.regs.SPI_READY_addr self._enable_base_power() # Check register map compatibility self._check_compat_version() self.log.debug("ZBX CPLD build git hash: %s", self._get_cpld_git_hash()) # Power up the DB self._enable_power() # enable PLL reference clock self.reset_clock(False) self._cpld_set_safe_defaults()
def __init__(self, label=None, path=None, length=None, read_only=True, offset=None): self.log = get_logger('UIO') if label is None: self._path = path self.log.trace("Using UIO device `{0}'".format(path)) uio_device = os.path.split(path)[-1] self.log.trace("Getting map info for UIO device `{0}'".format(uio_device)) map_info = get_uio_map_info(uio_device, 0) # Python can't tell the size of a uio device by itself assert length is not None else: self.log.trace("Using UIO device by label `{0}'".format(label)) self._path, map_info = find_uio_device(label, self.log) if self._path is None or map_info is None: self.log.error("Could not find a UIO device for label {0}".format(label)) raise RuntimeError("Could not find a UIO device for label {0}".format(label)) # TODO If we ever support multiple maps, check if this is correct... offset = offset or map_info['offset'] assert offset == 0 # ...and then remove this line length = length or map_info['size'] self.log.trace("UIO device is being opened read-{0}.".format( "only" if read_only else "write")) self._read_only = read_only # Our UIO objects are managed in C++ land, which gives us more granular control over # opening and closing self._uio = lib.types.mmap_regs_iface(self._path, length, offset, self._read_only, False) # Reference counter for safely __enter__ and __exit__-ing self._ref_count = 0
def __init__(self, slot_idx, **kwargs): DboardManagerBase.__init__(self, slot_idx, **kwargs) self.log = get_logger("Rhodium-{}".format(slot_idx)) self.log.trace("Initializing Rhodium daughterboard, slot index %d", self.slot_idx) self.rev = int(self.device_info['rev']) self.log.trace("This is a rev: {}".format(chr(65 + self.rev))) # This is a default ref clock freq, it must be updated before init() is # called! self.ref_clock_freq = None # These will get updated during init() self.master_clock_rate = None self.sampling_clock_rate = None self.current_jesd_rate = None # Predeclare some attributes to make linter happy: self.lmk = None self._port_expander = None self._lo_dist = None self.cpld = None # If _init_args is None, it means that init() hasn't yet been called. self._init_args = None # Now initialize all peripherals. If that doesn't work, put this class # into a non-functional state (but don't crash, or we can't talk to it # any more): try: self._init_periphs() self._periphs_initialized = True except Exception as ex: self.log.error("Failed to initialize peripherals: %s", str(ex)) self._periphs_initialized = False
def __init__(self, args): # Logger is initialized in super().__init__ but we need config values # before we call that config_log = get_logger("PeriphConfig") if 'config' in args: config_path = args['config'] config_log.info("Loading config from {}".format(config_path)) self.config = Config.from_path(config_log, config_path) else: config_log.warn("No config specified, using default") self.config = Config.default() self.device_id = 1 self.description = self.config.hardware.description self.mboard_info = { "type": self.config.hardware.uhd_device_type, "product": self.config.hardware.product, "simulated": "True" } self.pids = { int(self.config.hardware.pid): self.config.hardware.product } # This uses the description, mboard_info, and pids super().__init__() self.chdr_endpoint = ChdrEndpoint(self.log, self.config) # Unlike the real hardware drivers, if there is an exception here, # we just crash. No use missing an error when testing. self._init_peripherals(args) self.init_dboards(args) if not args.get('skip_boot_init', False): self.init(args)
def __init__(self, peeker_poker32, base_addr=None, bus_clk_rate=None): assert hasattr(peeker_poker32, 'peek32') \ and callable(peeker_poker32.peek32) assert hasattr(peeker_poker32, 'poke32') \ and callable(peeker_poker32.poke32) self.log = get_logger("AuroraCore") self._regs = peeker_poker32 base_addr = base_addr or 0 self.log.debug( "Base address in register space is: 0x{:04X}".format(base_addr)) self.poke32 = lambda addr, data: self._regs.poke32( addr + base_addr, data) self.peek32 = lambda addr: self._regs.peek32(addr + base_addr) self.mac_ctrl = 0x000 self.set_mac_ctrl(self.mac_ctrl) time.sleep(.5) self.bus_clk_rate = bus_clk_rate if self.bus_clk_rate is None: self.bus_clk_rate = self.DEFAULT_BUS_CLK_RATE self.log.warning("Unspecified bus clock rate. Assuming default " "rate of {} MHz.".format(self.bus_clk_rate / 1e6)) else: self.log.debug("Bus clock rate: {} MHz.".format(self.bus_clk_rate / 1e6)) self.bist_max_time_limit = math.floor(2**48 / self.bus_clk_rate) - 1 self.log.debug("BIST max time limit: {} s".format( self.bist_max_time_limit)) self.log.debug("Status of PHY link: 0x{:08X}".format( self.read_phy_ctrl_status())) if not self.is_phy_link_up(): raise RuntimeError("PHY link not up. Check connectors.")
def __init__(self, regs_iface, parent_log=None): self.log = \ parent_log.getChild("LMK05318") if parent_log is not None \ else get_logger("LMK05318") self.regs_iface = regs_iface assert hasattr(self.regs_iface, 'peek8') assert hasattr(self.regs_iface, 'poke8') self.peek8 = regs_iface.peek8
def __init__(self, slot_idx, log=None): self.dt_symbol = 'db{}_flash'.format(slot_idx) self.overlay = self.dt_symbol if log is None: self.log = get_logger("DBFlash") else: self.log = log.getChild("DBFlash") self.initialized = False
def __init__(self, regs_iface, parent_log=None): self.log = \ parent_log.getChild("LMK04828") if parent_log is not None \ else get_logger("LMK04828") self.regs_iface = regs_iface assert hasattr(self.regs_iface, 'peek8') assert hasattr(self.regs_iface, 'poke8') self.poke8 = regs_iface.poke8 self.peek8 = regs_iface.peek8
def __init__(self): # Make a logger try: self.log = get_logger('GPSDIface') except AssertionError: from usrp_mpm.mpmlog import get_main_logger self.log = get_main_logger('GPSDIface') # Make a socket to connect to GPSD self.gpsd_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def __init__(self, jesdcore, slot_idx=0, **kwargs): def validate_config(): """ This function validates the configuration parameters' ranges. """ assert (0 <= self.prescale) and (self.prescale <= 31) assert self.rxout_div in (1, 2, 4, 8, 16) assert self.rx_int_datawidth in (16, 20, 32, 40) assert self.eq_mode.upper() in ('LPM', 'DFE') self.log.debug( "Valid Eye Scan configuration: prescale=%d rxout_div=%d" " rx_int_datawidth=%d eq_mode=%s", self.prescale, self.rxout_div, self.rx_int_datawidth, self.eq_mode) # self.slot_idx = slot_idx self.log = get_logger("EyeScanTool-{}".format(self.slot_idx)) self.log.info("Initializing Eye Scan Tool...") self.jesdcore = jesdcore assert hasattr(self.jesdcore, 'set_drp_target') assert hasattr(self.jesdcore, 'disable_drp_target') assert hasattr(self.jesdcore, 'drp_access') # Some global parameters defined. # # Control the prescaling of the sample count to keep both sample # count and error count in reasonable precision within the 16-bit # register range. # Valid values: from 0 to 31. self.prescale = 0 # # QPLL/CPLL output clock divider D for the RX datapath. # Valid values: 1, 2, 4, 8, 16. self.rxout_div = 1 # # Defines the width of valid data on Rdata and Sdata buses. # Valid values: 16, 20, 32, 40. self.rx_int_datawidth = 16 # # Equalizer mode: LPM linear eq. or DFE eq. # When in DFE mode (RXLPMEN=0), due to the unrolled first DFE tap, # two separate eye scan measurements are needed, one at +UT and # one at -UT, to measure the TOTAL BER at a given vertical and # horizontal offset. # Valid values = 'LPM', 'DFE'. self.eq_mode = 'LPM' # # Overwrite the default configuration parameters with the ones given # by the user (host) through kwargs. for key, new_val in list(kwargs.items()): if hasattr(self, key) and (new_val != getattr(self, key)): self.log.trace( "Overwriting {0}... default:{1} user:{2}".format( key, getattr(self, key), new_val)) setattr(self, key, new_val) # Validate configuration attributes' values. validate_config()
def __init__(self, regs_iface, parent_log=None): self.log = \ parent_log.getChild("LMK04832") if parent_log is not None \ else get_logger("LMK04832") self.regs_iface = regs_iface assert hasattr(self.regs_iface, 'peek8') assert hasattr(self.regs_iface, 'poke8') self.poke8 = regs_iface.poke8 self.peek8 = regs_iface.peek8 self.enable_3wire_spi = False
def jtag_cpld_update(filename, logger): """ Update the MB CPLD via dedicated JTAG lines in the FPGA Note: To use this update mechanism, a FPGA image with JTAG lines must be loaded. """ if logger is None: logger = get_logger('update_cpld') if not check_fpga_state(): logger.error("CPLD lines are routed through fabric, " "FPGA is not programmed, giving up") return False mode = 'axi_bitq' config = CONFIGS[mode] if not filename.endswith('svf'): logger.warning('The legacy JTAG programming mechanism expects ' '.svf files. The CPLD file being used may be incorrect.') if check_openocd_files(config['files'], logger=logger): logger.trace("Found required OpenOCD files.") else: # check_openocd_files logs errors return False uio_id = find_axi_bitq_uio() if uio_id is None or uio_id < 0: logger.error('Failed to find axi_bitq uio devices. '\ 'Make sure overlays are up to date') return False try: gpios = get_gpio_controls() except RuntimeError as ex: logger.error('Could not open GPIO required for JTAG programming!'\ ' {}'.format(ex)) return False enable_jtag_gpio(gpios) cmd = ["openocd", "-c", config['cmd'][0] % (uio_id, AXI_BITQ_BUS_CLK, AXI_BITQ_ADAPTER_SPEED), "-f", (config['files'][0]).strip(), "-c", config['cmd'][1] % filename] logger.trace("Update CPLD CMD: {}".format(" ".join(cmd))) subprocess.call(cmd) # Disable JTAG dual-purpose pins to CPLD after reprogramming enable_jtag_gpio(gpios, disable=True) logger.trace("Done programming CPLD...") return True
def __init__(self, jesdcore, slot_idx=0, **kwargs): def validate_config(): """ This function validates the configuration parameters' ranges. """ assert (0 <= self.prescale) and (self.prescale <= 31) assert self.rxout_div in (1, 2, 4, 8, 16) assert self.rx_int_datawidth in (16, 20, 32, 40) assert self.eq_mode.upper() in ('LPM', 'DFE') self.log.debug("Valid Eye Scan configuration: prescale=%d rxout_div=%d" " rx_int_datawidth=%d eq_mode=%s", self.prescale, self.rxout_div, self.rx_int_datawidth, self.eq_mode) # self.slot_idx = slot_idx self.log = get_logger("EyeScanTool-{}".format(self.slot_idx)) self.log.info("Initializing Eye Scan Tool...") self.jesdcore = jesdcore assert hasattr(self.jesdcore, 'set_drp_target') assert hasattr(self.jesdcore, 'disable_drp_target') assert hasattr(self.jesdcore, 'drp_access') # Some global parameters defined. # # Control the prescaling of the sample count to keep both sample # count and error count in reasonable precision within the 16-bit # register range. # Valid values: from 0 to 31. self.prescale = 0 # # QPLL/CPLL output clock divider D for the RX datapath. # Valid values: 1, 2, 4, 8, 16. self.rxout_div = 1 # # Defines the width of valid data on Rdata and Sdata buses. # Valid values: 16, 20, 32, 40. self.rx_int_datawidth = 16 # # Equalizer mode: LPM linear eq. or DFE eq. # When in DFE mode (RXLPMEN=0), due to the unrolled first DFE tap, # two separate eye scan measurements are needed, one at +UT and # one at -UT, to measure the TOTAL BER at a given vertical and # horizontal offset. # Valid values = 'LPM', 'DFE'. self.eq_mode = 'LPM' # # Overwrite the default configuration parameters with the ones given # by the user (host) through kwargs. for key, new_val in list(kwargs.items()): if hasattr(self, key) and (new_val != getattr(self, key)): self.log.trace("Overwriting {0}... default:{1} user:{2}" .format(key, getattr(self, key), new_val)) setattr(self, key, new_val) # Validate configuration attributes' values. validate_config()
def do_update_cpld(filename, daughterboards, updater_mode): """ Carry out update process for the CPLD :param filename: path (on device) to the new CPLD image :param daughterboards: iterable containing dboard numbers to update :param updater_mode: the updater method to use- Either flash or legacy (JTAG) :return: True on success, False otherwise """ assert updater_mode in ('flash', 'legacy'), \ f"Invalid updater method {updater_mode} given" logger = get_logger('update_cpld') logger.info( "Programming CPLD of dboards {} with image {} using {} mode".format( daughterboards, filename, updater_mode)) if not daughterboards: logger.error("Invalid daughterboard selection.") return False if not os.path.exists(filename): logger.error("CPLD image file {} not found".format(filename)) return False if not check_fpga_state(logger=logger): logger.error( "CPLD lines are routed through fabric, FPGA is not programmed, giving up" ) return False if updater_mode == 'legacy': return jtag_cpld_update(filename, daughterboards, logger) # updater_mode == flash: for dboard in daughterboards: dboard = int(dboard, 10) logger.info("Updating daughterboard slot {}...".format(dboard)) # enable required daughterboard clock cpld_spi_node = dt_symbol_get_spidev('mb_cpld') cpld_control = MboardCPLD(cpld_spi_node, logger) cpld_control.enable_daughterboard_support_clock(dboard, enable=True) # setup flash configuration engine and required register access label = "ctrlport-mboard-regs" ctrlport_regs = CtrlportRegs(label, logger) regs = ctrlport_regs.get_db_cpld_iface(dboard) flash_control = Max10CpldFlashCtrl(logger, regs, RECONFIG_ENGINE_OFFSET, CPLD_MIN_REVISION) success = flash_control.update(filename) # disable clock cpld_control.enable_daughterboard_support_clock(dboard, enable=False) if not success: return success return True
def __init__(self, regs, slot_idx=0, **kwargs): self.regs = regs self.log = get_logger("NIJESD204bCore-{}".format(slot_idx)) assert hasattr(self.regs, 'peek32') assert hasattr(self.regs, 'poke32') # Initialize the driver's attributes with the default value, or a user-given # value if the attribute key exists in kwargs. for key, default_value in iteritems(self.JESDCORE_DEFAULTS): setattr(self, key, kwargs.get(key, default_value)) assert type(getattr(self, key)) == type(default_value), \ "Invalid type for attribute {}".format(key) self.log.trace("Initialized attribute {0} = {1}." .format(key, getattr(self, key)))
def __init__(self, regs, slot_idx=0, **kwargs): self.regs = regs self.log = get_logger("NIJESD204bCore-{}".format(slot_idx)) assert hasattr(self.regs, 'peek32') assert hasattr(self.regs, 'poke32') # Initialize the driver's attributes with the default value, or a user-given # value if the attribute key exists in kwargs. for key, default_value in iteritems(self.JESDCORE_DEFAULTS): setattr(self, key, kwargs.get(key, default_value)) assert type(getattr(self, key)) == type(default_value), \ "Invalid type for attribute {}".format(key) self.log.trace("Initialized attribute {0} = {1}.".format( key, getattr(self, key)))
def __init__(self, slot_idx, **kwargs): super().__init__(slot_idx, **kwargs) self.log = get_logger("sim_db-{}".format(slot_idx)) self.device_info = { 'pid': to_native_str(self.__class__.pids[0]), 'serial': to_native_str("todo:serial-here"), 'rev': to_native_str("1"), 'eeprom_version': to_native_str('0') } self.rev = int(self.device_info['rev']) self.log.trace("This is a rev: {}".format(chr(65 + self.rev))) self._make_extra_methods()
def __init__(self, slot_idx, **kwargs): super(EISCAT, self).__init__(slot_idx, **kwargs) self.log = get_logger("EISCAT-{}".format(slot_idx)) self.log.trace("Initializing EISCAT daughterboard, slot index {}".format(self.slot_idx)) self.initialized = False self.ref_clock_freq = 10e6 # This is the only supported clock rate # Define some attributes so that PyLint stays quiet: self.radio_regs = None self.jesd_cores = None self.lmk = None self.adcs = [] self.dboard_clk_control = None self.clock_synchronizer = None self._spi_ifaces = None
def __init__(self, devicepath, mountpoint, options=None, log=None): assert isinstance(devicepath, str) assert isinstance(mountpoint, str) assert isinstance(options, list) self.devicepath = devicepath self.mountpoint = mountpoint self.options = options if log is None: self.log = get_logger("Mount") else: self.log = log.getChild("Mount") self.log.trace( "Early initialization: devicepath={}, mountpoint={}, options={}". format(devicepath, mountpoint, options))
def __init__(self, slot_idx, **kwargs): self.log = get_logger('dboardManager') self.slot_idx = slot_idx if 'eeprom_md' not in kwargs: self.log.debug("No EEPROM metadata given!") # In C++, we can only handle dicts if all the values are of the # same type. So we must convert them all to strings here: self.device_info = { key: to_native_str(kwargs.get('eeprom_md', {}).get(key, 'n/a')) for key in ('pid', 'serial', 'rev', 'eeprom_version') } self.log.trace("Dboard device info: `{}'".format(self.device_info)) self._spi_nodes = self._init_spi_nodes(kwargs.get('spi_nodes', []), self.spi_chipselect) self.log.debug("spidev device node map: {}".format(self._spi_nodes))
def check_fpga_state(which=0): """ Check if the FPGA is operational :param which: the FPGA to check """ logger = get_logger('update_cpld') try: context = pyudev.Context() fpga_mgrs = [dev for dev in context.list_devices(subsystem="fpga_manager")] if fpga_mgrs: state = fpga_mgrs[which].attributes.asstring('state') logger.trace("FPGA State: {}".format(state)) return state == "operating" except OSError as ex: logger.error("Error while checking FPGA status: {}".format(ex)) return False
def __init__(self, slot_idx, **kwargs): self.log = get_logger('dboardManager') self.slot_idx = slot_idx if 'eeprom_md' not in kwargs: self.log.debug("No EEPROM metadata given!") # In C++, we can only handle dicts if all the values are of the # same type. So we must convert them all to strings here: self.device_info = { key: to_native_str(kwargs.get('eeprom_md', {}).get(key, 'n/a')) for key in ('pid', 'serial', 'rev', 'eeprom_version') } self.log.trace("Dboard device info: `{}'".format(self.device_info)) self._spi_nodes = self._init_spi_nodes( kwargs.get('spi_nodes', []), self.spi_chipselect ) self.log.debug("spidev device node map: {}".format(self._spi_nodes))
def __init__(self, regs_iface, parent_log=None): self.log = \ parent_log.getChild("DS125DF410") if parent_log is not None \ else get_logger("DS125DF410") self.regs_iface = regs_iface # Set channel select register to control set self.regs_iface.poke8(0xFF, 0) # Probe chip ID chip_id = self.regs_iface.peek8(0x01) assert chip_id == 0xd1 self.log.debug("Probed DS125DF410 retimer") for chan in ALL_CHANS: self._set_chan_select(chan) # Reset channel registers self.regs_iface.poke8(0x00, 0x04) # Enable DFE mode self.regs_iface.poke8(0x1E, 0xE1) self.regs_iface.poke8(0x31, 0x40)
def __init__(self, args): # Note: args is a dictionary. assert len(self.pids) > 0 assert self.mboard_eeprom_magic is not None self.dboards = [] # Set up logging self.log = get_logger('PeriphManager') self.claimed = False try: self._eeprom_head, self._eeprom_rawdata = \ self._read_mboard_eeprom() self.mboard_info = self._get_mboard_info(self._eeprom_head) self.log.info("Device serial number: {}" .format(self.mboard_info.get('serial', 'n/a'))) dboard_infos = self._get_dboard_eeprom_info() self.device_info = \ self.generate_device_info( self._eeprom_head, self.mboard_info, dboard_infos ) self._default_args = self._update_default_args(args) self.log.debug("Using default args: {}".format(self._default_args)) self._init_mboard_overlays() override_db_pids_str = self._default_args.get('override_db_pids') if override_db_pids_str: override_db_pids = [ int(x, 0) for x in override_db_pids_str.split(",") ] else: override_db_pids = [] self._init_dboards( dboard_infos, override_db_pids, self._default_args ) self._device_initialized = True self._initialization_status = "No errors." except Exception as ex: self.log.error("Failed to initialize device: %s", str(ex)) self._device_initialized = False self._initialization_status = str(ex) super(PeriphManagerBase, self).__init__()
def find_axi_bitq_uio(dboard): """ Find the AXI Bitq UIO device :param dboard: the dboard, can be either 0 or 1 """ assert dboard < 2 and dboard >= 0 label = 'dboard-jtag-%u' % dboard logger = get_logger('update_cpld') try: context = pyudev.Context() uios = [dev for dev in context.list_devices(subsystem="uio")] for uio in uios: uio_label = uio.attributes.asstring('maps/map0/name') logger.trace("UIO label: {}, match: {} number: {}".format( uio_label, uio_label == label, uio.sys_number)) if uio_label == label: return int(uio.sys_number) except OSError as ex: logger.error("Error while looking for axi_bitq uio nodes: {}".format(ex)) return -1
def __init__(self, slot_idx, **kwargs): super(Neon, self).__init__(slot_idx, **kwargs) self.log = get_logger("Neon-{}".format(slot_idx)) self.log.trace("Initializing Neon daughterboard, slot index %d", self.slot_idx) self.rev = int(self.device_info['rev']) self.log.trace("This is a rev: {}".format(chr(65 + self.rev))) # These will get updated during init() self.master_clock_rate = None # Predeclare some attributes to make linter happy: self.catalina = None self.eeprom_fs = None self.eeprom_path = None # Now initialize all peripherals. If that doesn't work, put this class # into a non-functional state (but don't crash, or we can't talk to it # any more): try: self._init_periphs() self._periphs_initialized = True except Exception as ex: self.log.error("Failed to initialize peripherals: %s", str(ex)) self._periphs_initialized = False
def __init__(self, identifiers, use_mask, ddr, init_value=0, parent_dev=None): assert (use_mask & ddr) == ddr self.log = get_logger("SysFSGPIO") self._identifiers = identifiers self._use_mask = use_mask self._ddr = ddr self._init_value = init_value self.log.trace("Generating SysFSGPIO object for identifiers `{}'..." .format(identifiers)) self._gpio_dev, self._map_info = \ find_gpio_device(identifiers, parent_dev, self.log) if self._gpio_dev is None: error_msg = \ "Could not find GPIO device with identifiers `{}'.".format(identifiers) self.log.error(error_msg) raise RuntimeError(error_msg) self.log.trace("GPIO base number is {}" .format(self._map_info.get("sys_number"))) self._base_gpio = self._map_info.get("sys_number") self.init(self._map_info['ngpio'], self._base_gpio, self._use_mask, self._ddr, self._init_value)
def __init__(self, peeker_poker32, base_addr=None, bus_clk_rate=None): assert hasattr(peeker_poker32, 'peek32') \ and callable(peeker_poker32.peek32) assert hasattr(peeker_poker32, 'poke32') \ and callable(peeker_poker32.poke32) self.log = get_logger("AuroraCore") self._regs = peeker_poker32 base_addr = base_addr or 0 self.log.debug("Base address in register space is: 0x{:04X}".format( base_addr )) self.poke32 = lambda addr, data: self._regs.poke32( addr + base_addr, data ) self.peek32 = lambda addr: self._regs.peek32(addr + base_addr) self.mac_ctrl = 0x000 self.set_mac_ctrl(self.mac_ctrl) time.sleep(.5) self.bus_clk_rate = bus_clk_rate if self.bus_clk_rate is None: self.bus_clk_rate = self.DEFAULT_BUS_CLK_RATE self.log.warning("Unspecified bus clock rate. Assuming default " "rate of {} MHz.".format(self.bus_clk_rate/1e6)) else: self.log.debug("Bus clock rate: {} MHz.".format( self.bus_clk_rate/1e6 )) self.bist_max_time_limit = math.floor(2**48/self.bus_clk_rate)-1 self.log.debug("BIST max time limit: {} s".format( self.bist_max_time_limit )) self.log.debug("Status of PHY link: 0x{:08X}".format( self.read_phy_ctrl_status() )) if not self.is_phy_link_up(): raise RuntimeError("PHY link not up. Check connectors.")
def __init__(self, label): self.log = get_logger(label) self._regs = UIO(label=label, read_only=False) self.poke32 = self._regs.poke32 self.peek32 = self._regs.peek32
def __init__( self, regs_iface, lmk, phase_dac, offset, radio_clk_freq, ref_clk_freq, fine_delay_step, init_pdac_word, dac_spi_addr_val, pps_in_pipe_ext_delay, pps_in_pipe_dynamic_delay, slot_idx ): self._iface = regs_iface self.log = get_logger("Sync-{}".format(slot_idx)) self.slot_idx = slot_idx self.peek32 = lambda addr: self._iface.peek32(addr + offset) self.poke32 = lambda addr, data: self._iface.poke32(addr + offset, data) self.lmk = lmk self.phase_dac = phase_dac self.radio_clk_freq = radio_clk_freq self.ref_clk_freq = ref_clk_freq self.fine_delay_step = fine_delay_step self.current_phase_dac_word = init_pdac_word self.lmk_vco_freq = self.lmk.get_vco_freq() self.dac_spi_addr_val = dac_spi_addr_val self.meas_clk_freq = None self.target_values = [] # Output PPS static delay is the minimum number of radio_clk cycles from the SP-t # rising edge to when PPS appears on the output of the trigger passing module in # the radio_clk domain. 2 cycles are from the trigger crossing structure and # 2 are from the double-synchronizer that crosses the PPS output into the # no-reset domain from the async reset domain of the TDC. self.PPS_OUT_PIPE_STATIC_DELAY = 2+2 # Output PPS variable delay is programmable by this module to between 0 and 15 # radio_clk cycles. The combination of static and variable delays make up the # total delay from SP-t rising edge to the PPS in the radio_clk domain. self.pps_out_pipe_var_delay = 0 # Input PPS delay (in ref_clk cycles) is recorded here and only changes when # the TDC structure changes. This represents the number of ref_clk cycles from # PPS arriving at the input of the TDC to when the RP/-t pulse occurs. There are # static delays and dynamic delays. Dynamic delay is 0-15 additional cycles. # Default for older drivers was a total of 5 cycles. Increase the dynamic delay # to delay the RP/SP pulsers start with respect to the Reset Pulser. self.PPS_IN_PIPE_STATIC_DELAY = 4 self.pps_in_pipe_dynamic_delay = pps_in_pipe_dynamic_delay # 0-15 # External input PPS delay is a target-specific value, typically 3 ref_clk cycles. # This represents the number of ref_clk cycles from when PPS is first captured # by the ref_clk to when PPS arrives at the input of the TDC. self.pps_in_pipe_ext_delay = pps_in_pipe_ext_delay self.tdc_rev = 1 # update theses lists whenever more rates are supported self.SUPPORTED_PULSE_RATES = [1e6, 1.25e6, 1.2288e6] # order matters here! self.SUPPORTED_REF_CLK_FREQS = [10e6, 20e6, 25e6, 62.5e6] if self.ref_clk_freq not in self.SUPPORTED_REF_CLK_FREQS: self.log.error("Clock synchronizer does not support the selected reference " "clock frequency. Selected rate: {:.2f} MHz".format( self.ref_clk_freq*1e-6)) raise RuntimeError("TDC does not support the selected reference clock rate!") self.supported_radio_clk_freqs = [104e6, 122.88e6, 125e6, 153.6e6, 156.25e6, \ 200e6, 245.76e6, 250e6] if self.radio_clk_freq not in self.supported_radio_clk_freqs: self.log.error("Clock synchronizer does not support the selected radio clock" " frequency. Selected rate: {:.2f} MHz".format( self.radio_clk_freq*1e-6)) raise RuntimeError("TDC does not support the selected radio clock rate!") # Bump this whenever we stop supporting older FPGA images or boards. # YYMMDDHH self.oldest_compat_version = 0x17060111 # Bump this whenever changes are made to this MPM host code. self.current_version = 0x18032916 self.check_core() self.configured = False
def rm_overlay(overlay_name): """ Removes the given overlay. Does not check if the overlay is loaded. """ get_logger("DTO").trace("Removing overlay `{}'...".format(overlay_name)) os.rmdir(os.path.join(SYSFS_OVERLAY_BASE_DIR, overlay_name))