Exemple #1
0
    def update_q_coeff(self, dict_sig):
        """
        Update coefficient quantization settings and coefficients.
        
        The new values are written to the fixpoint coefficient dict as
        `fb.fil[0]['fxqc']['QCB']` and
        `fb.fil[0]['fxqc']['b']`.
        """
        logger.debug("update q_coeff - dict_sig:\n{0}".format(
            pprint_log(dict_sig)))
        dict_sig.update({'ui': 'C' + dict_sig['ui']})
        fb.fil[0]['fxqc'].update(self.ui2dict())
        logger.debug("b = {0}".format(pprint_log(fb.fil[0]['fxqc']['b'])))

        self.process_sig_rx(dict_sig)
    def fx_sim_init(self):
        """
        Initialize fix-point simulation: 
            
        - Update the `fxqc_dict` containing all quantization information
        
        - Setup a filter instance for migen simulation
        
        - Request a stimulus signal
        """
        if not hasattr(self.fx_wdg_inst, 'construct_fixp_filter'):
            logger.error(
                'Fixpoint widget has no method "construct_fixp_filter", aborting.'
            )
            self.sig_tx.emit({'sender': __name__, 'fx_sim': 'error'})
            return

        try:
            logger.info("Started HDL fixpoint simulation")
            self.update_fxqc_dict()
            self.fx_wdg_inst.construct_fixp_filter()  # setup filter instance

            dict_sig = {'sender': __name__, 'fx_sim': 'get_stimulus'}
            self.sig_tx.emit(dict_sig)

        except ValueError as e:  # exception
            logger.error('Fixpoint stimulus generation failed for dict\n{0}'
                         '\nwith "{1} "'.format(pprint_log(dict_sig), e))
        return
Exemple #3
0
    def process_sig_rx(self, dict_sig=None):
        """
        Process signals coming from the navigation toolbar and from sig_rx
        """
        logger.debug("SIG_RX - data_changed = {0}, vis = {1}\n{2}"\
                     .format(self.data_changed, self.isVisible(), pprint_log(dict_sig)))

        if self.isVisible():
            if 'data_changed' in dict_sig or 'specs_changed' in dict_sig\
                    or 'home' in dict_sig or self.data_changed:
                self.draw()
                self.data_changed = False
                self.view_changed = False
                self.ui_changed = False
            if 'view_changed' in dict_sig or self.view_changed:
                self.update_view()
                self.view_changed = False
                self.ui_changed = False
            if 'ui_changed' in dict_sig and dict_sig['ui_changed'] == 'resized'\
                    or self.ui_changed:
                self.redraw()
                self.ui_changed = False
        else:
            if 'data_changed' in dict_sig or 'specs_changed' in dict_sig:
                self.data_changed = True
            if 'ui_changed' in dict_sig and dict_sig['ui_changed'] == 'resized':
                self.ui_changed = True
            if 'view_changed' in dict_sig:
                self.view_changed = True
Exemple #4
0
 def log_rx(self, dict_sig=None):
     """
     Enable `self.sig_rx.connect(self.log_rx)` above for debugging.
     """
     if type(dict_sig) == dict:
         logger.warning("SIG_RX\n{0}"\
             .format(pprint_log(dict_sig)))
     else:
         logger.warning("empty dict")  
 def update_fxqc_dict(self):
     """
     Update the fxqc dictionary before simulation / HDL generation starts.
     """
     if self.fx_wdg_found:
         # get a dict with the coefficients and fixpoint settings from fixpoint widget
         if hasattr(self.fx_wdg_inst, "ui2dict"):
             fb.fil[0]['fxqc'].update(self.fx_wdg_inst.ui2dict())
             logger.debug("update fxqc: \n{0}".format(
                 pprint_log(fb.fil[0]['fxqc'])))
     else:
         logger.error("No fixpoint widget found!")
Exemple #6
0
    def process_sig_rx(self, dict_sig=None):
        """
        Process signals coming from sig_rx
        """
        logger.info("sig_rx:\n{0}".format(pprint_log(dict_sig)))

        if dict_sig['sender'] == __name__:
            logger.debug("Infinite Loop!")
        elif 'data_changed' in dict_sig:
            self.load_dict()
        elif 'ui_changed' in dict_sig and dict_sig['ui_changed'] == 'csv':
            self.ui._set_load_save_icons()
        elif 'fx_sim' in dict_sig and dict_sig['fx_sim'] == 'specs_changed':
            self.qdict2ui()
Exemple #7
0
    def process_sig_rx(self, dict_sig=None, propagate=False):
        """
        Process signals coming in via subwidgets and sig_rx
        
        All signals terminate here unless the flag `propagate=True`.
        
        The sender name of signals coming in from local subwidgets is changed to
        its parent widget (`input_specs`) to prevent infinite loops.

        """
        logger.debug("Processing {0}: {1}".format(type(dict_sig).__name__, dict_sig))
        if dict_sig['sender'] == __name__:
            logger.debug("Stopped infinite loop:\n{0}\tpropagate={1}"\
                           .format(pprint_log(dict_sig),propagate))
            return
        elif 'view_changed' in dict_sig:
            self.f_specs.load_dict()
            self.t_specs.load_dict()
        elif 'specs_changed' in dict_sig:
            self.f_specs.sort_dict_freqs()
            self.t_specs.f_specs.sort_dict_freqs()
            self.color_design_button("changed")
        elif 'filt_changed' in dict_sig:
            # Changing the filter design requires updating UI because number or
            # kind of input fields changes -> call update_UI
            self.update_UI(dict_sig)
            self.color_design_button("changed")
        elif 'data_changed' in dict_sig:
            if dict_sig['data_changed'] == 'filter_loaded':
                """
                Called when a new filter has been LOADED:
                Pass new filter data from the global filter dict by
                specifically calling SelectFilter.load_dict()
                """
                self.sel_fil.load_dict() # update select_filter widget
            # Pass new filter data from the global filter dict & set button = "ok"
            self.load_dict() 

        if propagate:
            # local signals are propagated with the name of this widget,
            # global signals terminate here
            dict_sig.update({'sender':__name__})
            self.sig_tx.emit(dict_sig)
Exemple #8
0
    def process_sig_rx(self, dict_sig=None):
        logger.debug("sig_rx:\n{0}".format(pprint_log(dict_sig)))
        # check whether anything needs to be done locally
        # could also check here for 'quant', 'ovfl', 'WI', 'WF' (not needed at the moment)
        if 'ui' in dict_sig:
            if dict_sig['ui'] == 'cmbW':
                cmbW = qget_cmb_box(self.wdg_w_accu.cmbW, data=False)
                self.wdg_w_accu.ledWF.setEnabled(cmbW == 'man')
                self.wdg_w_accu.ledWI.setEnabled(cmbW == 'man')
                if cmbW in {'full', 'auto'}:
                    self.dict2ui()
                    self.sig_tx.emit({
                        'sender': __name__,
                        'specs_changed': 'cmbW'
                    })
                else:
                    return

            dict_sig.update({'sender': __name__})

        self.sig_tx.emit(dict_sig)
Exemple #9
0
    def __init__(self):
        p = fb.fil[0]['fxqc']

        # ------------- Define I/Os -------------------------------------------
        self.i = Signal((p['QI']['W'], True))  # input signal
        self.o = Signal((p['QO']['W'], True))  # output signal

        ###
        muls = []  # list for partial products b_i * x_i
        DW = int(np.ceil(np.log2(len(p['b']))))  # word growth
        # word format for sum of partial products b_i * x_i
        QP = {
            'WI': p['QI']['WI'] + p['QCB']['WI'] + DW,
            'WF': p['QI']['WF'] + p['QCB']['WF']
        }
        QP.update({'W': QP['WI'] + QP['WF'] + 1})

        src = self.i  # first register is connected to input signal

        for b in p['b']:
            sreg = Signal((p['QI']['W'], True))  # create chain of registers
            self.sync += sreg.eq(src)  # with input word length
            src = sreg
            muls.append(int(b) * sreg)

        logger.debug("b = {0}\nW(b) = {1}".format(pprint_log(p['b']),
                                                  p['QCB']['W']))

        # saturation logic doesn't make much sense with a FIR filter, this is
        # just for demonstration
        sum_full = Signal((QP['W'], True))
        self.sync += sum_full.eq(reduce(
            add, muls))  # sum of multiplication products

        # rescale from full product format to accumulator format
        sum_accu = Signal((p['QA']['W'], True))
        self.comb += sum_accu.eq(rescale(self, sum_full, QP, p['QA']))

        # rescale from accumulator format to output width
        self.comb += self.o.eq(rescale(self, sum_accu, p['QA'], p['QO']))
Exemple #10
0
    def process_sig_rx(self, dict_sig=None):
        """
        Process signals coming from sig_rx
        """
        logger.debug("SIG_RX - data_changed = {0}, vis = {1}\n{2}"\
                     .format(self.data_changed, self.isVisible(), pprint_log(dict_sig)))

        if dict_sig['sender'] == __name__:
            logger.debug("Infinite loop detected (and interrupted)!")
            return
        if self.isVisible():
            if 'data_changed' in dict_sig or self.data_changed:
                self.load_dict()
                self.data_changed = False
            elif 'ui_changed' in dict_sig and dict_sig[
                    'ui_changed'] == 'csv' or self.ui_changed:
                self.ui._set_load_save_icons()
                self.ui_changed = False
        else:
            # TODO: draw wouldn't be necessary for 'view_changed', only update view
            if 'data_changed' in dict_sig:
                self.data_changed = True
            elif 'ui_changed' in dict_sig and dict_sig['ui_changed'] == 'csv':
                self.ui_changed = True
    def fx_sim_set_stimulus(self, dict_sig):
        """
        - Get fixpoint stimulus from `dict_sig` in integer format
          
        - Pass it to the fixpoint filter and calculate the fixpoint response
        
        - Send the reponse to the plotting widget
        """
        try:
            logger.debug(
                'Starting fixpoint simulation with stimulus from "{0}":\n\tfx_stimulus:{1}'
                '\n\tStimuli: Shape {2} of type "{3}"'.format(
                    dict_sig['sender'],
                    pprint_log(dict_sig['fx_stimulus'], tab=" "),
                    np.shape(dict_sig['fx_stimulus']),
                    dict_sig['fx_stimulus'].dtype,
                ))

            # Run fixpoint simulation and return the results as integer values:
            self.fx_results = self.fx_wdg_inst.run_sim(
                dict_sig['fx_stimulus'])  # Run the simulation

            if len(self.fx_results) == 0:
                logger.warning("Fixpoint simulation returned empty results!")
            else:
                logger.debug("fx_results: {0}"\
                            .format(pprint_log(self.fx_results, tab= " ")))
            #TODO: fixed point / integer to float conversion?
            #TODO: color push-button to show state of simulation
            #TODO: add QTimer single shot
#            self.timer_id = QtCore.QTimer()
#            self.timer_id.setSingleShot(True)
#            # kill simulation after some idle time, also add a button for this
#            self.timer_id.timeout.connect(self.kill_sim)

        except ValueError as e:
            logger.error("Simulator error {0}".format(e))
            self.fx_results = None
            qstyle_widget(self.butSimHDL, "error")
            self.sig_tx.emit({'sender': __name__, 'fx_sim': 'error'})
            return
        except AssertionError as e:
            logger.error('Fixpoint simulation failed for dict\n{0}'
                         '\twith msg. "{1}"\n\tStimuli: Shape {2} of type "{3}"'
                         '\n\tResponse: Shape {4} of type "{5}"'\
                           .format(pprint_log(dict_sig), e,
                                   np.shape(dict_sig['fx_stimulus']),
                                   dict_sig['fx_stimulus'].dtype,
                                   np.shape(self.fx_results),
                                   type(self.fx_results)
                                    ))

            self.fx_results = None
            qstyle_widget(self.butSimHDL, "error")
            self.sig_tx.emit({'sender': __name__, 'fx_sim': 'error'})
            return

        logger.debug("Sending fixpoint results")
        dict_sig = {
            'sender': __name__,
            'fx_sim': 'set_results',
            'fx_results': self.fx_results
        }
        self.sig_tx.emit(dict_sig)
        qstyle_widget(self.butSimHDL, "normal")

        logger.debug("Fixpoint plotting finished")

        return
    def process_sig_rx(self, dict_sig=None, propagate=False):
        """
        Process signals coming in via subwidgets and sig_rx
		
		Play PingPong with a stimulus & plot widget:
        
		2. ``fx_sim_init()``: Request stimulus by sending 'fx_sim':'get_stimulus'
		
		3. ``fx_sim_set_stimulus()``: Receive stimulus from widget in 'fx_sim':'set_stimulus'
			and pass it to HDL object for simulation
		   
		4. Send back HDL response to widget via 'fx_sim':'set_response'

        """

        logger.debug("SIG_RX - vis: {0} | prop: {1}\n{2}"\
                    .format(self.isVisible(), propagate, pprint_log(dict_sig)))
        if dict_sig['sender'] == __name__:
            logger.debug("Infinite loop detected")
            return
        elif 'filt_changed' in dict_sig:
            # update list of available filter topologies here
            self._update_filter_cmb()
        elif 'data_changed' in dict_sig or\
            ('view_changed' in dict_sig and dict_sig['view_changed'] == 'q_coeff'):
            # update fields in the filter topology widget - wordlength may have
            # been changed. Also set RUN button to "changed" in wdg_dict2ui() and
            # enable propagate so that
            self.wdg_dict2ui()
            #self.sig_tx.emit({'sender':__name__, 'fx_sim':'specs_changed'})
        elif 'fx_sim' in dict_sig:
            if dict_sig['fx_sim'] == 'init':
                if self.fx_wdg_found:
                    self.fx_sim_init()
                else:
                    logger.error("No fixpoint widget found!")
                    qstyle_widget(self.butSimHDL, "error")
                    self.sig_tx.emit({'sender': __name__, 'fx_sim': 'error'})

            elif dict_sig['fx_sim'] == 'set_stimulus':
                self.fx_sim_set_stimulus(dict_sig)
            elif dict_sig['fx_sim'] == 'specs_changed':
                # fixpoint specification have been changed somewhere, update ui
                # and set run button to "changed" in wdg_dict2ui()
                self.wdg_dict2ui()
            elif dict_sig['fx_sim'] == 'finish':
                qstyle_widget(self.butSimHDL, "normal")
            else:
                logger.error('Unknown "fx_sim" command option "{0}"\n'
                             '\treceived from "{1}".'.format(
                                 dict_sig['fx_sim'], dict_sig['sender']))
        # ---- Process local widget signals
        elif 'ui' in dict_sig:
            if dict_sig['ui'] == 'butLock':
                if self.wdg_w_input.butLock.isChecked():
                    fb.fil[0]['fxqc']['QO']['WI'] = fb.fil[0]['fxqc']['QI'][
                        'WI']
                    fb.fil[0]['fxqc']['QO']['WF'] = fb.fil[0]['fxqc']['QI'][
                        'WF']
                    fb.fil[0]['fxqc']['QO']['W'] = fb.fil[0]['fxqc']['QI']['W']
                else:
                    return
            elif dict_sig['ui'] in {'WI', 'WF', 'ovfl', 'quant', 'cmbW'}:
                pass
            else:
                logger.warning("Unknown value '{0}' for key 'ui'".format(
                    dict_sig['ui']))
            self.wdg_dict2ui()
            self.sig_tx.emit({'sender': __name__, 'fx_sim': 'specs_changed'})

        if propagate:
            # signals of local subwidgets are propagated,
            # global signals terminate here.
            # The next event in the queue is only handled when control returns
            # from this one
            #dict_sig.update({'sender':__name__})
            self.sig_tx.emit(dict_sig)
            return