Пример #1
0
    def init(self, p, zi: iterable = None) -> None:
        """
        Initialize filter with parameter dict `p` by initialising all registers
        and quantizers.
        This needs to be done every time quantizers or coefficients are updated.

        Parameters
        ----------
        p : dict
            dictionary with coefficients and quantizer settings (see docstring of
            `__init__()` for details)

        zi : array-like
            Initialize `L = len(b)` filter registers. Strictly speaking, `zi[0]` is
            not a register but the current input value.
            When `len(zi) != len(b)`, truncate or fill up with zeros.
            When `zi == None`, all registers are filled with zeros.

        Returns
        -------
        None.
        """
        # logger.error(p)
        self.p = p  # parameter dictionary with coefficients etc.

        if 'q_mul' not in self.p or self.p['q_mul'] is None:
            q_mul = {'Q': '0.15', 'ovfl': 'none', 'quant': 'none'}
        else:
            q_mul = p['q_mul']

        self.b = self.p['b']  # coefficients
        self.L = len(self.b)  # filter length = number of taps
        # create various quantizers
        self.Q_mul = fx.Fixed(q_mul)  # partial products
        self.Q_acc = fx.Fixed(self.p['QA'])  # accumulator
        self.Q_O = fx.Fixed(self.p['QO'])  # output
        self.N_over_filt = 0  # initialize overflow counter TODO: not used yet?

        # Initialize vectors (also speeds up calculation for large arrays)
        self.xbq = np.zeros(len(self.b))  # partial products

        if zi is None:
            self.zi = np.zeros(self.L - 1)
        else:  # initialize filter memory and fill up with zeros
            if len(zi) == self.L - 1:
                self.zi = zi
            elif len(zi) < self.L - 1:
                self.zi = np.concatenate((zi, np.zeros(self.L - 1 - len(zi))))
            else:
                self.zi = zi[:self.L - 1]
Пример #2
0
    def setUp(self):
        self.q_in = {
            'WI': 0,
            'WF': 15,
            'W': 16,
            'ovfl': 'wrap',
            'quant': 'round'
        }
        self.q_out = {
            'WI': 0,
            'WF': 15,
            'W': 16,
            'ovfl': 'wrap',
            'quant': 'round'
        }
        if HAS_MIGEN:
            self.dut = DUT(self.q_in, self.q_out)

        self.stim = np.array([0, 1, 15, 64, 32767, -1, -64,
                              0])  # last zero isn't tested due to latency of 1

        # initialize a pyfda fixpoint quantizer
        q_obj = {
            'WI': 0,
            'WF': 3,
            'ovfl': 'sat',
            'quant': 'round',
            'frmt': 'dec',
            'scale': 1
        }
        self.myQ = fx.Fixed(
            q_obj)  # instantiate fixpoint object with settings above
Пример #3
0
    def quant_coeffs(self, q_dict, coeffs):
        """
        Quantize the coefficients, scale and convert them to integer and return them
        as a list of integers
        
        This is called every time one of the coefficient subwidgets is edited or changed.
    
        Parameters:
        -----------
        None
    
        Returns:
        --------
        A list of integer coeffcients, quantized and scaled with the settings
        of the passed quantization dict
               
        """
        # Create coefficient quantizer instances using the quantization parameters dict
        # collected in `input_widgets/input_coeffs.py` (and stored in the central filter dict)
        Q_coeff = fx.Fixed(q_dict)
        Q_coeff.frmt = 'dec' # always use decimal format for coefficients

        if coeffs is None:
            logger.error("Coeffs empty!")
        # quantize floating point coefficients and convert them to the
        # selected numeric format (hex, bin, dec ...) with the selected scale (WI.WF),
        # next convert array float -> array of fixp - > list of int (scaled by 2^WF)
        return list(Q_coeff.float2frmt(coeffs) * (1 << Q_coeff.WF))
Пример #4
0
    def update_hdl_filter(self):
        """
        Update the HDL filter object with new coefficients, quantization settings etc. when
        
        - it is constructed
        
        - filter design and hence coefficients change
        
        - quantization settings are updated in this widget
        """
        # setup input and output quantizers
        self.q_i = fx.Fixed(
            self.hdl_dict['QI'])  # setup quantizer for input quantization
        self.q_i.setQobj({'frmt': 'dec'
                          })  #, 'scale':'int'}) # use integer decimal format
        self.q_o = fx.Fixed(
            self.hdl_dict['QO'])  # setup quantizer for output quantization

        b = [int(x)
             for x in self.hdl_dict['b']]  # convert np.int64 to python int
        a = [int(x)
             for x in self.hdl_dict['a']]  # convert np.int64 to python int

        # call setup method of filter widget - this is not implemented (yet)
        # self.fx_wdg_inst.setup_HDL(self.hdl_dict)

        self.hdlfilter.set_coefficients(
            coeff_b=b, coeff_a=a)  # Coefficients for the filter

        # pass wordlength for coeffs, input, output
        # TODO: directly pass the hdl_dict here:
        self.hdlfilter.set_word_format(
            (self.hdl_dict['QC']['W'], self.hdl_dict['QC']['WI'],
             self.hdl_dict['QC']['WF']),
            (self.hdl_dict['QI']['W'], self.hdl_dict['QI']['WI'],
             self.hdl_dict['QI']['WF']),
            (self.hdl_dict['QO']['W'], self.hdl_dict['QO']['WI'],
             self.hdl_dict['QO']['WF']))
Пример #5
0
    def setUp(self):
        q_obj = {
            'WI': 0,
            'WF': 3,
            'ovfl': 'sat',
            'quant': 'round',
            'frmt': 'dec',
            'scale': 1
        }
        self.myQ = fix_lib.Fixed(
            q_obj)  # instantiate fixpoint object with settings above

        self.y_list = [-1.1, -1.0, -0.5, 0, 0.5, 0.9, 0.99, 1.0, 1.1]
        self.y_list_cmplx = [
            -1.1j + 0.1, -1.0 - 0.3j, -0.5 - 0.5j, 0j, 0.5j, 0.9, 0.99 + 0.3j,
            1j, 1.1
        ]
        # list with various invalid strings
        self.y_list_validate = [
            '1.1.1', 'xxx', '123', '1.23', '', 1.23j + 3.21, '3.21 + 1.23 j'
        ]
Пример #6
0
    def quant_coeffs(self,
                     q_dict: dict,
                     coeffs: iterable,
                     to_int: bool = False) -> list:
        """
        Quantize the coefficients, scale and convert them to integer and return them
        as a list of integers

        This is called every time one of the coefficient subwidgets is edited or changed.

        Parameters:
        -----------
        q_dict: dict
           Dictionary with quantizer settings for coefficients

        coeffs: iterable
           a list or ndarray of coefficients to be quantized

        Returns:
        --------
        A list of integer coeffcients, quantized and scaled with the settings
        of the passed quantization dict

        """
        # Create coefficient quantizer instance using the passed quantization parameters
        # dict from `input_widgets/input_coeffs.py` (and stored in the central
        # filter dict)
        Q_coeff = fx.Fixed(q_dict)
        Q_coeff.frmt = 'dec'  # always use decimal format for coefficients

        if coeffs is None:
            logger.error("Coeffs empty!")
        # quantize floating point coefficients with the selected scale (WI.WF),
        # next convert array float  -> array of fixp
        #                           -> list of int (scaled by 2^WF) when `to_int == True`
        if to_int:
            return list(Q_coeff.float2frmt(coeffs) * (1 << Q_coeff.WF))
        else:
            return list(Q_coeff.fixp(coeffs))
Пример #7
0
    def _construct_UI(self):
        """
        Intitialize the widget, consisting of:
        - top chkbox row
        - coefficient table
        - two bottom rows with action buttons
        """
        # ---------------------------------------------------------------------
        #   Coefficient table widget
        # ---------------------------------------------------------------------
        self.tblCoeff = QTableWidget(self)
        self.tblCoeff.setAlternatingRowColors(True)
        self.tblCoeff.horizontalHeader().setHighlightSections(True) # highlight when selected
        self.tblCoeff.horizontalHeader().setFont(self.ui.bfont)

#        self.tblCoeff.QItemSelectionModel.Clear
        self.tblCoeff.setDragEnabled(True)
#        self.tblCoeff.setDragDropMode(QAbstractItemView.InternalMove) # doesn't work like intended
        self.tblCoeff.setItemDelegate(ItemDelegate(self))

        # ============== Main UI Layout =====================================
        layVMain = QVBoxLayout()
        layVMain.setAlignment(Qt.AlignTop) # this affects only the first widget (intended here)
        layVMain.addWidget(self.ui)
        layVMain.addWidget(self.tblCoeff)

        layVMain.setContentsMargins(*params['wdg_margins'])

        self.setLayout(layVMain)

        self.myQ = fx.Fixed(fb.fil[0]['fxqc']['QCB']) # initialize fixpoint object
        self.load_dict() # initialize + refresh table with default values from filter dict
        # TODO: this needs to be optimized - self._refresh is being called in both routines
        self._set_number_format()

        #----------------------------------------------------------------------
        # GLOBAL SIGNALS & SLOTs
        #----------------------------------------------------------------------
        self.sig_rx.connect(self.process_sig_rx)
        #----------------------------------------------------------------------
        # LOCAL (UI) SIGNALS & SLOTs
        #----------------------------------------------------------------------
        # wdg.textChanged() is emitted when contents of widget changes
        # wdg.textEdited() is only emitted for user changes
        # wdg.editingFinished() is only emitted for user changes
        self.ui.butEnable.clicked.connect(self._refresh_table)
        self.ui.spnDigits.editingFinished.connect(self._refresh_table)

        self.ui.cmbQFrmt.currentIndexChanged.connect(self._set_number_format)
        self.ui.butFromTable.clicked.connect(self._copy_from_table)
        self.ui.butToTable.clicked.connect(self._copy_to_table)

        self.ui.cmbFilterType.currentIndexChanged.connect(self._filter_type)

        self.ui.butDelCells.clicked.connect(self._delete_cells)
        self.ui.butAddCells.clicked.connect(self._add_cells)
        self.ui.butLoad.clicked.connect(self.load_dict)
        self.ui.butSave.clicked.connect(self._save_dict)
        self.ui.butClear.clicked.connect(self._clear_table)
        self.ui.ledEps.editingFinished.connect(self._set_eps)
        self.ui.butSetZero.clicked.connect(self._set_coeffs_zero)

        # store new settings and refresh table
        self.ui.cmbFormat.currentIndexChanged.connect(self.ui2qdict)
        self.ui.cmbQOvfl.currentIndexChanged.connect(self.ui2qdict)
        self.ui.cmbQuant.currentIndexChanged.connect(self.ui2qdict)
        self.ui.ledWF.editingFinished.connect(self.ui2qdict)
        self.ui.ledWI.editingFinished.connect(self.ui2qdict)
        self.ui.ledW.editingFinished.connect(self._W_changed)

        self.ui.ledScale.editingFinished.connect(self._set_scale)

        self.ui.butQuant.clicked.connect(self.quant_coeffs)

        self.ui.sig_tx.connect(self.sig_tx)