def program(self, bitstream=None): progfile = bitstream or self.config['fpgfile'] self.logger.info('Programming all SNAPs with %s' % progfile) utils.program_fpgas([feng.fpga for feng in self.fengs], progfile, timeout=300.0) self.r['corr:snap:last_programmed'] = time.ctime()
def program(self, bitstream=None, unprogrammed_only=True): """ Program SNAPs. Inputs: bitstream (str): Path to fpgfile to program. If None, the bitstream described in the current configuration will be used. unprogrammed_only (Boolean): If True, only program boards which aren't yet programmed. Current state is determined by a lazy check for the "adc16_controller" register. If it exists, the board is deemed programmed. """ progfile = bitstream or self.config['fpgfile'] self.logger.info('Programming all SNAPs with %s' % progfile) if unprogrammed_only: to_be_programmed = [] for feng in self.fengs: if 'adc16_controller' not in feng.fpga.listdev(): to_be_programmed += [feng] if len(to_be_programmed) == 0: return else: to_be_programmed = self.fengs utils.program_fpgas([f.fpga for f in to_be_programmed], progfile, timeout=300.0) for f in to_be_programmed: self.r.hset('status:snap:%s' % f.host, 'last_programmed', time.ctime())
def program(self, bitstream=None, unprogrammed_only=True): """ Program SNAPs. Inputs: bitstream (str): Path to fpgfile to program. If None, the bitstream described in the current configuration will be used. unprogrammed_only (Boolean): If True, only program boards which aren't yet programmed. """ TEMP_BITSTREAM_STORE = "/tmp/" progfile = bitstream or self.config['fpgfile'] self.logger.info('Programming all SNAPs with %s' % progfile) if progfile.startswith("redis:"): progfile = progfile.split(":")[-1] try: bitstream = self.r.hget("fpg:%s" % progfile, "fpg") except KeyError: self.logger.error( "FPG file %s not available in redis. Cannot program" % progfile) return progfile = os.path.join(TEMP_BITSTREAM_STORE, progfile) with open(progfile, "wb") as fh: fh.write(bitstream) if unprogrammed_only: to_be_programmed = [] for feng in self.fengs: if not feng.is_programmed(): to_be_programmed += [feng] if len(to_be_programmed) == 0: self.logger.info( "Skipping programming because all boards seem ready") return else: to_be_programmed = self.fengs self.logger.info("Actually programming %s" % ([f.host for f in self.fengs])) utils.program_fpgas([f.fpga for f in to_be_programmed], progfile, timeout=300.0) time.sleep(20) for f in to_be_programmed: self.r.hset('status:snap:%s' % f.host, 'last_programmed', time.ctime())
except AttributeError: raise RuntimeError('No such log level: %s' % log_level) LOGGER = logging.getLogger(__name__) THREADED_FPGA_OP = fpgautils.threaded_fpga_operation THREADED_FPGA_FUNC = fpgautils.threaded_fpga_function # read the config file configd = fpgautils.parse_ini_file(args.config) filter_cfg = configd['filter'] # program the filter boards filter_fpgas = [] for _f in filter_cfg['hosts']: filter_fpgas.append(HOSTCLASS(_f)) fpgautils.program_fpgas(filter_fpgas, progfile=filter_cfg['bitstream'], timeout=15) THREADED_FPGA_FUNC(filter_fpgas, timeout=10, target_function='get_system_information') # set up the fpga comms THREADED_FPGA_OP(filter_fpgas, timeout=10, target_function=(lambda fpga_: fpga_.registers.control.write(gbe_txen=False),)) THREADED_FPGA_OP(filter_fpgas, timeout=10, target_function=(lambda fpga_: fpga_.registers.control.write(gbe_rst=False),)) THREADED_FPGA_OP(filter_fpgas, timeout=10, target_function=(lambda fpga_: fpga_.registers.control.write(status_clr='pulse', gbe_cnt_rst='pulse', cnt_rst='pulse'),)) # where does the filter data go? THREADED_FPGA_OP(filter_fpgas, timeout=5,
def initialise(self, program=True, qdr_cal=True): """ Set up the correlator using the information in the config file. :return: """ # set up the F, X, B and filter handlers self.fops = FEngineOperations(self) self.xops = XEngineOperations(self) # self.bops = BEngineOperations(self) self.filtops = FilterOperations(self) # set up the filter boards if we need to if 'filter' in self.configd: try: self.filtops.initialise(program=program) except Exception as e: raise e # connect to the other hosts that make up this correlator THREADED_FPGA_FUNC(self.fhosts + self.xhosts, timeout=5, target_function='connect') igmp_version = self.configd['FxCorrelator'].get('igmp_version') if igmp_version is not None: self.logger.info('Setting FPGA hosts IGMP version to ' '%s' % igmp_version) THREADED_FPGA_FUNC( self.fhosts + self.xhosts, timeout=5, target_function=( 'set_igmp_version', (igmp_version, ), {})) # if we need to program the FPGAs, do so if program: self.logger.info('Programming FPGA hosts') fpgautils.program_fpgas([(host, host.boffile) for host in (self.fhosts + self.xhosts)], progfile=None, timeout=15) else: self.logger.info('Loading design information') THREADED_FPGA_FUNC(self.fhosts + self.xhosts, timeout=7, target_function='get_system_information') # remove test hardware from designs utils.disable_test_gbes(self) utils.remove_test_objects(self) if program: # cal the qdr on all boards if qdr_cal: self.qdr_calibrate() else: self.logger.info('Skipping QDR cal - are you sure you' ' want to do this?') # init the engines self.fops.initialise() self.xops.initialise() # are there beamformers? if self.found_beamformer: bengops.beng_initialise(self) # for fpga_ in self.fhosts: # fpga_.tap_arp_reload() # for fpga_ in self.xhosts: # fpga_.tap_arp_reload() # subscribe all the engines to the multicast groups self.fops.subscribe_to_multicast() self.xops.subscribe_to_multicast() post_mess_delay = 10 self.logger.info('post mess-with-the-switch delay of ' '%is' % post_mess_delay) time.sleep(post_mess_delay) # force a reset on the f-engines self.fops.sys_reset(sleeptime=1) # reset all counters on fhosts and xhosts self.fops.clear_status_all() self.xops.clear_status_all() # check to see if the f engines are receiving all their data if not self.fops.check_rx(): raise RuntimeError('The f-engines RX have a problem.') # start f-engine TX self.logger.info('Starting f-engine datastream') self.fops.tx_enable() # check that the F-engines are transmitting data correctly if not self.fops.check_tx(): raise RuntimeError('The f-engines TX have a problem.') # check that the X-engines are receiving data if not self.xops.check_rx(): raise RuntimeError('The x-engines RX have a problem.') # arm the vaccs on the x-engines self.xops.vacc_sync() # reset all counters on fhosts and xhosts self.fops.clear_status_all() self.xops.clear_status_all() # set an initialised flag self._initialised = True
def initialise(self, program=True, qdr_cal=True, require_epoch=False): """ Set up the correlator using the information in the config file. :param program: program the FPGA boards if True :param qdr_cal: perform QDR cal if True :param require_epoch: the synch epoch MUST be set before init if True :return: """ # check that the instrument's synch epoch has been set if require_epoch: if self.get_synch_time() == -1: raise RuntimeError('System synch epoch has not been set prior' ' to initialisation!') # set up the F, X, B and filter handlers self.fops = FEngineOperations(self) self.xops = XEngineOperations(self) self.bops = BEngineOperations(self) self.filtops = FilterOperations(self) self.speadops = SpeadOperations(self) # set up the filter boards if we need to if 'filter' in self.configd: try: self.filtops.initialise(program=program) except Exception as e: raise e # connect to the other hosts that make up this correlator THREADED_FPGA_FUNC(self.fhosts + self.xhosts, timeout=5, target_function='connect') igmp_version = self.configd['FxCorrelator'].get('igmp_version') if igmp_version is not None: self.logger.info('Setting FPGA hosts IGMP version ' 'to %s' % igmp_version) THREADED_FPGA_FUNC( self.fhosts + self.xhosts, timeout=5, target_function=('set_igmp_version', (igmp_version, ), {})) # if we need to program the FPGAs, do so if program: self.logger.info('Programming FPGA hosts') fpgautils.program_fpgas([(host, host.boffile) for host in (self.fhosts + self.xhosts)], progfile=None, timeout=15) else: self.logger.info('Loading design information') THREADED_FPGA_FUNC(self.fhosts + self.xhosts, timeout=10, target_function='get_system_information') # remove test hardware from designs utils.disable_test_gbes(self) utils.remove_test_objects(self) # run configuration on the parts of the instrument self.configure() # run post-programming initialisation self._initialise(program, qdr_cal) # reset all counters on fhosts and xhosts self.fops.clear_status_all() self.xops.clear_status_all() # set an initialised flag self._initialised = True