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
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
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!")
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()
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)
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)
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']))
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