def readout(self, no_data_timeout=None): '''Readout thread continuously reading SRAM. Readout thread, which uses read_data() and appends data to self._data_deque (collection.deque). ''' logging.debug('Starting %s' % (self.readout_thread.name, )) curr_time = get_float_time() time_wait = 0.0 while not self.force_stop.wait(time_wait if time_wait >= 0.0 else 0.0): try: time_read = time() if no_data_timeout and curr_time + no_data_timeout < get_float_time( ): raise NoDataTimeout( 'Received no data for %0.1f second(s)' % no_data_timeout) data = self.read_data() except Exception: no_data_timeout = None # raise exception only once if self.errback: self.errback(sys.exc_info()) else: raise if self.stop_readout.is_set(): break else: data_words = data.shape[0] if data_words > 0: last_time, curr_time = self.update_timestamp() status = 0 if self.callback: self._data_deque.append( (data, last_time, curr_time, status)) if self.fill_buffer: self._data_buffer.append( (data, last_time, curr_time, status)) self._words_per_read.append(data_words) elif self.stop_readout.is_set(): break else: self._words_per_read.append(0) finally: time_wait = self.readout_interval - (time() - time_read) if self._calculate.is_set(): self._calculate.clear() self._result.put(sum(self._words_per_read)) if self.callback: self._data_deque.append(None) # last item, will stop worker logging.debug('Stopped %s' % (self.readout_thread.name, ))
def update_timestamp(self, fifo): curr_time = get_float_time() last_time = self.timestamp[fifo] if last_time is None: last_time = curr_time self.timestamp[fifo] = curr_time return last_time, curr_time
def readout(self, fifo, no_data_timeout=None): '''Readout thread continuously reading FIFO. Readout thread, which uses read_raw_data_from_fifo() and appends data to self._fifo_data_deque (collection.deque). ''' logging.info('Starting readout thread for %s', fifo) time_last_data = time() time_wait = 0.0 empty_reads = 0 while not self.force_stop[fifo].wait( time_wait if time_wait >= 0.0 else 0.0): time_read = time() try: if no_data_timeout and time_last_data + no_data_timeout < get_float_time( ): raise NoDataTimeout( 'Received no data for %0.1f second(s) from %s' % (no_data_timeout, fifo)) raw_data = self.read_raw_data_from_fifo(fifo) except NoDataTimeout: no_data_timeout = None # raise exception only once if self.errback: self.errback(sys.exc_info()) else: raise except Exception: if self.errback: self.errback(sys.exc_info()) else: raise if self.stop_readout.is_set( ): # in case of a exception, break immediately break else: n_data_words = raw_data.shape[0] if n_data_words > 0: time_last_data = time() empty_reads = 0 time_start_read, time_stop_read = self.update_timestamp( fifo) status = 0 self._fifo_data_deque[fifo].append( (raw_data, time_start_read, time_stop_read, status)) with self._fifo_conditions[fifo]: self._fifo_conditions[fifo].notify_all() elif self.stop_readout.is_set(): if empty_reads == self._n_empty_reads: break else: empty_reads += 1 finally: # ensure that the readout interval does not depend on the processing time of the data # and stays more or less constant over time time_wait = self.readout_interval - (time() - time_read) self._fifo_data_deque[fifo].append( None) # last item, None will stop worker with self._fifo_conditions[fifo]: self._fifo_conditions[fifo].notify_all() logging.info('Stopping readout thread for %s', fifo)
def readout(self, no_data_timeout=None): '''Readout thread continuously reading SRAM. Readout thread, which uses read_data() and appends data to self._data_deque (collection.deque). ''' logging.debug('Starting %s', self.readout_thread.name) curr_time = get_float_time() time_wait = 0.0 while not self.force_stop.wait(time_wait if time_wait >= 0.0 else 0.0): try: time_read = time() if no_data_timeout and curr_time + no_data_timeout < get_float_time(): raise NoDataTimeout('Received no data for %0.1f second(s)' % no_data_timeout) data = self.read_data() except Exception: no_data_timeout = None # raise exception only once if self.errback: self.errback(sys.exc_info()) else: raise if self.stop_readout.is_set(): break else: data_words = data.shape[0] if data_words > 0: last_time, curr_time = self.update_timestamp() status = 0 if self.callback: self._data_deque.append((data, last_time, curr_time, status)) if self.fill_buffer: self._data_buffer.append((data, last_time, curr_time, status)) self._words_per_read.append(data_words) elif self.stop_readout.is_set(): break else: self._words_per_read.append(0) finally: time_wait = self.readout_interval - (time() - time_read) if self._calculate.is_set(): self._calculate.clear() self._result.put(sum(self._words_per_read)) if self.callback: self._data_deque.append(None) # last item, will stop worker logging.debug('Stopped %s', self.readout_thread.name)
def data_words_per_second(self): with self.data_words_per_second_lock: result = [] curr_time = get_float_time() for words_per_read in self._words_per_read: result.append( sum([ item[0] for item in words_per_read if item[1] > (curr_time - self._moving_average_time_period) ]) / float(self._moving_average_time_period)) return result
def update_timestamp(self): curr_time = get_float_time() last_time = self.timestamp self.timestamp = curr_time return last_time, curr_time
def start(self, fifos, callback=None, errback=None, reset_rx=False, reset_fifo=False, fill_buffer=False, no_data_timeout=None, filter_func=None, converter_func=None, fifo_select=None, enabled_fe_channels=None): with self.is_running_lock: if self._is_running: raise RuntimeError( 'FIFO readout threads already started: use stop()') self._is_running = True if isinstance(fifos, basestring): fifos = [fifos] if len(fifos) == 0: raise ValueError('"fifos" parameter is empty.') if len(set(fifos)) != len(fifos): raise ValueError( 'The following strings are occurring multiple times in "fifos": %s' % set([fifo for fifo in fifos if fifos.count(fifo) > 1])) if isinstance(fifo_select, Iterable) and set(fifo_select) - set(fifos): raise ValueError( "The following FIFOs have filters/converters set but are not read out: %s" % (set(fifo_select) - set(fifos))) if isinstance(filter_func, Iterable) or isinstance( converter_func, Iterable) or (isinstance(fifo_select, Iterable) and not isinstance(fifo_select, basestring)): if not isinstance(filter_func, Iterable): raise ValueError('"filter_func" is not iterable.') if not isinstance(converter_func, Iterable): raise ValueError('"converter_func" is not iterable.') if not isinstance(fifo_select, Iterable): raise ValueError('"fifo_select" is not iterable.') if len(filter_func) != len(converter_func): raise ValueError( 'Length of "filter_func" and "converter_func" not equal.' ) if len(filter_func) != len(fifo_select): raise ValueError( 'Length of "filter_func" and "fifo_select" not equal.') if len(converter_func) != len(fifo_select): raise ValueError( 'Length of "converter_func" and "fifo_select" not equal.' ) else: if isinstance(fifo_select, basestring): # convert to iterable filter_func = [filter_func] converter_func = [converter_func] fifo_select = [fifo_select] else: # if fifo_select is None: # adding filters and converters for each FIFO filter_func = [filter_func] * len(fifos) converter_func = [converter_func] * len(fifos) fifo_select = fifos if not (set(fifos) & set(fifo_select)) == set(fifo_select): raise ValueError( '"fifo_select" contains non-existing FIFOs: %s' % (set(fifo_select) & set(fifos))) if enabled_fe_channels is None: self.enabled_fe_channels = [ rx.name for rx in self.dut.get_modules('fei4_rx') ] else: self.enabled_fe_channels = enabled_fe_channels self.fifos = fifos self.callback = callback self.errback = errback self.fill_buffer = fill_buffer self.filter_func = filter_func self.converter_func = converter_func self.fifo_select = fifo_select self._fifo_data_deque = {fifo: deque() for fifo in self.fifos} self._fifo_conditions = {fifo: Condition() for fifo in self.fifos} self._data_deque = [deque() for _ in self.filter_func] self._data_conditions = [Condition() for _ in self.filter_func] self._data_buffer = [deque() for _ in self.filter_func] self.force_stop = {fifo: Event() for fifo in self.fifos} self.timestamp = {fifo: None for fifo in self.fifos} len_deque = int(self._moving_average_time_period / self.readout_interval) curr_time = get_float_time() self._words_per_read = [ deque(iterable=[(0, curr_time, curr_time)] * len_deque, maxlen=len_deque) for _ in self.filter_func ] if reset_rx: self.reset_rx(fe_channels=self.enabled_fe_channels) for fifo in self.fifos: if reset_fifo: self.reset_fifo([fifo]) self.update_timestamp(fifo) fifo_size = self.get_fifo_size(fifo) if fifo_size != 0: logging.warning('%s contains data: FIFO_SIZE = %i', fifo, fifo_size) self.stop_readout.clear() for event in self.force_stop.values(): event.clear() logging.info('Starting FIFO readout...') if self.errback: self.watchdog_thread = Thread(target=self.watchdog, name='WatchdogThread') self.watchdog_thread.daemon = True self.watchdog_thread.start() self.readout_threads = [] self.worker_threads = [] self.writer_threads = [] for fifo in self.fifos: readout_thread = Thread(target=self.readout, name='ReadoutThread %s' % fifo, kwargs={ 'fifo': fifo, 'no_data_timeout': no_data_timeout }) worker_thread = Thread(target=self.worker, name='WorkerThread %s' % fifo, kwargs={'fifo': fifo}) readout_thread.daemon = True worker_thread.daemon = True self.readout_threads.append(readout_thread) self.worker_threads.append(worker_thread) for index, _ in enumerate(self.filter_func): writer_thread = Thread(target=self.writer, name='WriterThread %d' % index, kwargs={ 'index': index, 'no_data_timeout': no_data_timeout }) writer_thread.daemon = True self.writer_threads.append(writer_thread) for writer_thread in self.writer_threads: writer_thread.start() for worker_thread in self.worker_threads: worker_thread.start() for readout_thread in self.readout_threads: self.update_timestamp(fifo) readout_thread.start() # enabling RX channels for fifo in self.fifos: self.update_timestamp(fifo) for fei4_rx_name in self.enabled_fe_channels: self.dut[fei4_rx_name].ENABLE_RX = 1