예제 #1
0
    def _read_config(self):
        """
        Read the instrument configuration from self.config_source.
        :return: True if the instrument read a config successfully, raise
        an error if not?
        """
        Instrument._read_config(self)
        _d = self.configd

        # check that the bitstream names are present
        try:
            open(_d['fengine']['bitstream'], 'r').close()
            open(_d['xengine']['bitstream'], 'r').close()
        except IOError:
            self.logger.error('xengine bitstream: '
                              '%s' % _d['xengine']['bitstream'])
            self.logger.error('fengine bitstream: '
                              '%s' % _d['fengine']['bitstream'])
            self.logger.error('One or more bitstream files not found.')
            raise IOError('One or more bitstream files not found.')

        # TODO: Load config values from the bitstream meta information -
        # f per fpga, x per fpga, etc
        self.arp_wait_time = int(_d['FxCorrelator']['arp_wait_time'])
        self.sensor_poll_time = int(_d['FxCorrelator']['sensor_poll_time'])
        self.katcp_port = int(_d['FxCorrelator']['katcp_port'])
        self.f_per_fpga = int(_d['fengine']['f_per_fpga'])
        self.x_per_fpga = int(_d['xengine']['x_per_fpga'])
        self.sample_rate_hz = int(_d['FxCorrelator']['sample_rate_hz'])
        self.adc_demux_factor = int(_d['fengine']['adc_demux_factor'])
        self.accumulation_len = int(_d['xengine']['accumulation_len'])
        self.xeng_accumulation_len = int(_d['xengine']['xeng_accumulation_len'])
        self.n_chans = int(_d['fengine']['n_chans'])
        self.n_antennas = int(_d['fengine']['n_antennas'])
        self.min_load_time = float(_d['fengine']['min_load_time'])

        self.set_stream_destination(
            _d['xengine']['output_destination_ip'],
            int(_d['xengine']['output_destination_port']))
        self.set_meta_destination(_d['xengine']['output_destination_ip'],
                                  int(_d['xengine']['output_destination_port']))
        # get this from the running x-engines?
        self.xeng_clk = int(_d['xengine']['x_fpga_clock'])
        self.xeng_outbits = int(_d['xengine']['xeng_outbits'])

        # the f-engines have this many 10Gbe ports per f-engine
        # unit of operation
        self.ports_per_fengine = int(_d['fengine']['ports_per_fengine'])

        # check if beamformer exists with x-engines
        self.found_beamformer = False
        if 'bengine' in self.configd.keys():
            self.found_beamformer = True

        # set up the hosts and engines based on the configuration in the ini file
        self.fhosts = []
        for host in _d['fengine']['hosts'].split(','):
            host = host.strip()
            fpgahost = fhost_fpga.FpgaFHost.from_config_source(
                host, self.katcp_port, config_source=_d['fengine'])
            self.fhosts.append(fpgahost)

        # choose class (b-engine inherits x-engine functionality)
        if self.found_beamformer:
            _targetClass = bhost_fpga.FpgaBHost
        else:
            _targetClass = xhost_fpga.FpgaXHost
        self.xhosts = []
        for host in _d['xengine']['hosts'].split(','):
            host = host.strip()
            fpgahost = xhost_fpga.FpgaXHost.from_config_source(
                host, self.katcp_port, config_source=_d['xengine'])
            self.xhosts.append(fpgahost)
        self.bhosts = []
        # x-eng host b-eng
        for host in _d['xengine']['hosts'].split(','):
            host = host.strip()
            fpgahost = bhost_fpga.FpgaBHost.from_config_source(
                host, self.katcp_port, config_source=_d['xengine'])
            self.bhosts.append(fpgahost)

        # check that no hosts overlap
        for _fh in self.fhosts:
            for _xh in self.xhosts:
                if _fh.host == _xh.host:
                    self.logger.error('Host %s is assigned to both X- and '
                                      'F-engines' % _fh.host)
                    raise RuntimeError

        # what data sources have we been allocated?
        self._handle_sources()

        # turn the product names into a list
        prodlist = _d['xengine']['output_products'].replace('[', '').replace(']', '').split(',')
        _d['xengine']['output_products'] = []
        for prod in prodlist:
            _d['xengine']['output_products'].append(prod.strip(''))
예제 #2
0
    def _read_config(self):
        """
        Read the instrument configuration from self.config_source.
        :return: True if the instrument read a config successfully, raise an error if not?
        """
        Instrument._read_config(self)

        if use_demo_fengine:
            self.configd['fengine']['bitstream'] = '/srv/bofs/feng/feng_rx_test_2014_Jul_22_1556.fpg'

        # check that the bitstream names are present
        try:
            open(self.configd['fengine']['bitstream'], 'r').close()
            open(self.configd['xengine']['bitstream'], 'r').close()
        except IOError:
            LOGGER.error('One or more bitstream files not found.')
            raise IOError('One or more bitstream files not found.')

        # TODO: Load config values from the bitstream meta information

        self.katcp_port = int(self.configd['FxCorrelator']['katcp_port'])
        self.f_per_fpga = int(self.configd['fengine']['f_per_fpga'])
        self.x_per_fpga = int(self.configd['xengine']['x_per_fpga'])
        self.sample_rate_hz = int(self.configd['FxCorrelator']['sample_rate_hz'])
        self.accumulation_len = int(self.configd['xengine']['accumulation_len'])
        self.txip_str = self.configd['xengine']['output_destination_ip']
        self.txport = int(self.configd['xengine']['output_destination_port'])

        # TODO: Work on the logic of sources->engines->hosts

        # 2 pols per FPGA on this initial design, but should be mutable
        self.inputs_per_fengine = int(self.configd['fengine']['inputs_per_fengine'])

        # what antenna ids have we been allocated?
        self.source_names = self.configd['fengine']['source_names'].strip().split(',')
        self.source_mcast = []
        mcast = self.configd['fengine']['source_mcast_ips'].strip().split(',')
        for address in mcast:
            bits = address.split(':')
            port = int(bits[1])
            address, number = bits[0].split('+')
            self.source_mcast.append((address, int(number), int(port)))
        comparo = self.source_mcast[0][1]
        assert comparo == 3, 'F-engines should be receiving from 4 streams.'
        for mcast_addresses in self.source_mcast:
            assert mcast_addresses[1] == comparo, 'All f-engines should be receiving from 4 streams.'

        if len(self.source_names) != len(self.source_mcast):
            raise RuntimeError('We have different numbers of sources and multicast groups. Problem.')

        # set up the hosts and engines based on the config
        self.fhosts = []
        self.xhosts = []
        for hostconfig, hostlist in [(self.configd['fengine'], self.fhosts), (self.configd['xengine'], self.xhosts)]:
            hosts = hostconfig['hosts'].strip().split(',')
            for host in hosts:
                host = host.strip()
                fpgahost = FpgaHost(host, self.katcp_port, hostconfig['bitstream'], connect=True)
                hostlist.append(fpgahost)
        if len(self.source_names) != len(self.fhosts):
            raise RuntimeError('We have different numbers of sources and f-engine hosts. Problem.')
        for fnum, fhost in enumerate(self.fhosts):
            # TODO - logic for inputs vs fengines
            for ctr in range(0, self.inputs_per_fengine):
                engine = FengineCasperFpga(fhost, ctr, self.source_names[fnum], self.configd)
                fhost.add_engine(engine)
        for xnum, xhost in enumerate(self.xhosts):
            for ctr in range(0, self.x_per_fpga):
                engine = XengineCasperFpga(xhost, ctr, self.configd)
                xhost.add_engine(engine)

        # SPEAD receiver
        self.spead_tx = spead.Transmitter(spead.TransportUDPtx(self.configd['xengine']['rx_meta_ip'],
                                                               int(self.configd['xengine']['rx_udp_port'])))
        self.spead_ig = spead.ItemGroup()

        # done
        return True
예제 #3
0
    def _read_config(self):
        """
        Read the instrument configuration from self.config_source.
        :return:
        """
        Instrument._read_config(self)
        _d = self.configd

        # check that the bitstream names are present
        try:
            open(_d['fengine']['bitstream'], 'r').close()
            open(_d['xengine']['bitstream'], 'r').close()
        except IOError:
            self.logger.error('xengine bitstream: '
                              '%s' % _d['xengine']['bitstream'])
            self.logger.error('fengine bitstream: '
                              '%s' % _d['fengine']['bitstream'])
            self.logger.error('One or more bitstream files not found.')
            raise IOError('One or more bitstream files not found.')

        # TODO: Load config values from the bitstream meta information -
        # f per fpga, x per fpga, etc
        _fxcorr_d = self.configd['FxCorrelator']
        self.arp_wait_time = int(_fxcorr_d['arp_wait_time'])
        self.sensor_poll_time = int(_fxcorr_d['sensor_poll_time'])
        self.katcp_port = int(_fxcorr_d['katcp_port'])
        self.sample_rate_hz = int(_fxcorr_d['sample_rate_hz'])
        self.timestamp_bits = int(_fxcorr_d['timestamp_bits'])
        self.time_jitter_allowed_ms = int(_fxcorr_d['time_jitter_allowed_ms'])
        self.time_offset_allowed_s = int(_fxcorr_d['time_offset_allowed_s'])
        try:
            self.post_switch_delay = int(_fxcorr_d['switch_delay'])
        except KeyError:
            self.post_switch_delay = 10

        _feng_d = self.configd['fengine']
        self.adc_demux_factor = int(_feng_d['adc_demux_factor'])
        self.n_chans = int(_feng_d['n_chans'])
        self.n_antennas = int(_feng_d['n_antennas'])
        self.min_load_time = float(_feng_d['min_load_time'])
        self.f_per_fpga = int(_feng_d['f_per_fpga'])
        self.ports_per_fengine = int(_feng_d['ports_per_fengine'])
        self.analogue_bandwidth = int(_feng_d['bandwidth'])
        self.true_cf = float(_feng_d['true_cf'])
        self.quant_format = _feng_d['quant_format']
        self.adc_bitwidth = int(_feng_d['sample_bits'])
        self.fft_shift = int(_feng_d['fft_shift'])

        try:
            self.qdr_ct_error_threshold = int(_feng_d['qdr_ct_error_threshold'])
        except KeyError:
            self.qdr_ct_error_threshold = 100
        try:
            self.qdr_cd_error_threshold = int(_feng_d['qdr_cd_error_threshold'])
        except KeyError:
            self.qdr_cd_error_threshold = 100

        _xeng_d = self.configd['xengine']
        self.x_per_fpga = int(_xeng_d['x_per_fpga'])
        self.accumulation_len = int(_xeng_d['accumulation_len'])
        self.xeng_accumulation_len = int(_xeng_d['xeng_accumulation_len'])
        try:
            self.qdr_vacc_error_threshold = int(
                _xeng_d['qdr_vacc_error_threshold'])
        except KeyError:
            self.qdr_vacc_error_threshold = 100

        # get this from the running x-engines?
        self.xeng_clk = int(_xeng_d['x_fpga_clock'])
        self.xeng_outbits = int(_xeng_d['xeng_outbits'])

        # check if beamformer exists with x-engines
        self.found_beamformer = False
        if 'bengine' in self.configd.keys():
            self.found_beamformer = True
            self.beng_outbits = 8

        # set up hosts and engines based on the configuration in the ini file
        _targetClass = fhost_fpga.FpgaFHost
        self.fhosts = []
        for host in _feng_d['hosts'].split(','):
            host = host.strip()
            fpgahost = _targetClass.from_config_source(host, self.katcp_port,
                                                       config_source=_feng_d)
            self.fhosts.append(fpgahost)

        # choose class (b-engine inherits x-engine functionality)
        if self.found_beamformer:
            _targetClass = bhost_fpga.FpgaBHost
        else:
            _targetClass = xhost_fpga.FpgaXHost
        self.xhosts = []
        hostlist = _xeng_d['hosts'].split(',')
        for hostindex, host in enumerate(hostlist):
            host = host.strip()
            fpgahost = _targetClass.from_config_source(
                host, hostindex, self.katcp_port, config_source=_xeng_d)
            self.xhosts.append(fpgahost)

        # check that no hosts overlap
        for _fh in self.fhosts:
            for _xh in self.xhosts:
                if _fh.host == _xh.host:
                    self.logger.error('Host %s is assigned to '
                                      'both X- and F-engines' % _fh.host)
                    raise RuntimeError

        # update the list of baselines on this system
        self.baselines = utils.baselines_from_config(config=self.configd)

        # what data sources have we been allocated?
        self._handle_sources()

        # turn the stream names into a list
        prodlist = _xeng_d['output_products'].replace('[', '')
        prodlist = prodlist.replace(']', '').split(',')
        _xeng_d['output_products'] = [prod.strip(' ') for prod in prodlist]