コード例 #1
0
ファイル: r2sdf.py プロジェクト: donzelot/pyha
        def fft_model(inp):
            if self.INPUT_ORDERING == 'natural':
                offset = self.LOCAL_FFT_SIZE // 2
                twiddles = [W(i, self.LOCAL_FFT_SIZE) for i in range(offset)]
                packets = np.array(np.reshape(inp, (-1, self.LOCAL_FFT_SIZE)))
                for pack in packets:
                    for i in range(offset):
                        pack[i], pack[i + offset] = pack[i] + pack[i + offset], \
                                                    (pack[i] - pack[i + offset]) * twiddles[i]

                return packets.flatten()

            elif self.INPUT_ORDERING == 'bitreversed':
                input_stride = 2**self.STAGE_NR
                local_fft_size = self.GLOBAL_FFT_SIZE // input_stride
                twiddles = toggle_bit_reverse(
                    [W(i, local_fft_size) for i in range(local_fft_size // 2)])
                packets = np.array(
                    np.reshape(inp, (len(twiddles), -1))
                )  # note: this shape is upside down compared to NORMAL order function

                offset = input_stride
                for packet_i, pack in enumerate(packets):
                    for i in range(offset):
                        pack[i], pack[i + offset] = pack[i] + pack[i + offset], \
                                                    (pack[i] - pack[i + offset]) * twiddles[packet_i]
                return packets.flatten()
コード例 #2
0
def test_rev(fft_size):
    input_signal = np.random.uniform(
        -1, 1, fft_size) + np.random.uniform(-1, 1, fft_size) * 1j
    my = pyfft_rev(input_signal, fft_size)
    input_signal = toggle_bit_reverse(input_signal)
    ref = np.fft.fft(input_signal, fft_size)

    np.testing.assert_allclose(ref, my)
コード例 #3
0
ファイル: r2sdf.py プロジェクト: donzelot/pyha
def numpy_model(inp, fft_size, input_ordering='natural', inverse=False):
    """ This basically sums up what is going on in this file """
    x = np.array(inp).reshape(-1, fft_size)

    if input_ordering == 'bitreversed':
        x = toggle_bit_reverse(x)

    if inverse:
        ffts = np.fft.ifft(x, fft_size)
        ffts *= fft_size
    else:
        ffts = np.fft.fft(x, fft_size)
        ffts /= fft_size

    if input_ordering == 'natural':
        ffts = toggle_bit_reverse(ffts)

    return ffts.flatten()
コード例 #4
0
    def test_rand(self, fft_size):
        input_signal = np.random.uniform(
            -1, 1, fft_size) + np.random.uniform(-1, 1, fft_size) * 1j
        rev_input_signal = toggle_bit_reverse(input_signal)

        stage = 0
        inp = rev_input_signal
        while 2**stage != fft_size:
            inp = bitrevered_fft_stage(inp, fft_size, stage)
            stage += 1

        ref = np.fft.fft(input_signal, fft_size)

        np.testing.assert_allclose(ref, inp)
コード例 #5
0
    def test_rev8(self):
        fft_size = 8
        input_signal = np.array([
            0.01 + 0.01j, 0.02 + 0.02j, 0.03 + 0.03j, 0.04 + 0.04j,
            0.05 + 0.05j, 0.06 + 0.06j, 0.07 + 0.07j, 0.08 + 0.08j
        ])
        bitrev_input_signal = toggle_bit_reverse(input_signal)
        expect = [
            6.00000000e-02 + 6.00000000e-02j,
            -4.00000000e-02 - 4.00000000e-02j,
            1.00000000e-01 + 1.00000000e-01j,
            -4.00000000e-02 + 4.00000000e-02j,
            8.00000000e-02 + 8.00000000e-02j,
            -5.65685425e-02 - 3.46944695e-18j,
            1.20000000e-01 + 1.20000000e-01j, -6.93889390e-18 + 5.65685425e-02j
        ]

        stage0_out = bitrevered_fft_stage(bitrev_input_signal, fft_size, 0)

        np.testing.assert_allclose(stage0_out, expect)

        # stage 1
        expect = [
            1.60000000e-01 + 1.60000000e-01j,
            -8.00000000e-02 + 6.93889390e-18j,
            -4.00000000e-02 - 4.00000000e-02j,
            6.93889390e-18 - 8.00000000e-02j, 2.00000000e-01 + 2.00000000e-01j,
            -5.65685425e-02 + 5.65685425e-02j,
            -4.00000000e-02 + 4.00000000e-02j,
            -5.65685425e-02 + 5.65685425e-02j
        ]

        stage1_out = bitrevered_fft_stage(stage0_out, fft_size, 1)
        np.testing.assert_allclose(stage1_out, expect)

        # stage 2 (last
        expect = [
            3.60000000e-01 + 3.60000000e-01j,
            -1.36568542e-01 + 5.65685425e-02j,
            -8.00000000e-02 - 6.93889390e-18j,
            -5.65685425e-02 - 2.34314575e-02j,
            -4.00000000e-02 - 4.00000000e-02j,
            -2.34314575e-02 - 5.65685425e-02j,
            -6.93889390e-18 - 8.00000000e-02j, 5.65685425e-02 - 1.36568542e-01j
        ]

        stage2_out = bitrevered_fft_stage(stage1_out, fft_size, 2)
        np.testing.assert_allclose(stage2_out, expect)
コード例 #6
0
def bitrevered_fft_stage(inp, fft_size, stage_nr):
    """ Calculates one stage of the FFT. Inputs BITREVERSED and outputs NATURAL """
    input_stride = 2**stage_nr
    local_fft_size = fft_size // input_stride
    twiddles = toggle_bit_reverse(
        [W(i, local_fft_size) for i in range(local_fft_size // 2)])
    packets = np.array(
        np.reshape(inp, (local_fft_size // 2, -1))
    )  # note: this shape is upside down compared to NORMAL order function

    offset = input_stride
    for packet_i, pack in enumerate(packets):
        for i in range(offset):
            pack[i], pack[i + offset] = pack[i] + pack[i + offset], \
                                               (pack[i] - pack[i + offset]) * twiddles[packet_i]

    return packets.flatten()
コード例 #7
0
    def test_rev4(self):
        # stage 0
        fft_size = 4
        input_signal = np.array(
            [0.01 + 0.01j, 0.02 + 0.02j, 0.03 + 0.03j, 0.04 + 0.04j])
        bitrev_input_signal = toggle_bit_reverse(input_signal)
        expect = [0.04 + 0.04j, -0.02 - 0.02j, 0.06 + 0.06j, -0.02 + 0.02j]

        stage0_out = bitrevered_fft_stage(bitrev_input_signal, fft_size, 0)

        np.testing.assert_allclose(stage0_out, expect)

        # stage 1 (last)
        expect = [
            1.00000000e-01 + 1.00000000e-01j,
            -4.00000000e-02 + 3.46944695e-18j,
            -2.00000000e-02 - 2.00000000e-02j, 3.46944695e-18 - 4.00000000e-02j
        ]

        stage1_out = bitrevered_fft_stage(stage0_out, fft_size, 1)
        np.testing.assert_allclose(stage1_out, expect)
コード例 #8
0
ファイル: r2sdf.py プロジェクト: donzelot/pyha
    def __init__(self,
                 global_fft_size,
                 stage_nr,
                 twiddle_bits=18,
                 inverse=False,
                 input_ordering='natural',
                 allow_gain_control=True):
        self._pyha_simulation_input_callback = NumpyToDataValid(
            dtype=default_complex)

        self.ALLOW_GAIN_CONTROL = allow_gain_control
        self.INVERSE = inverse
        self.GLOBAL_FFT_SIZE = global_fft_size
        self.STAGE_NR = stage_nr
        self.INPUT_ORDERING = input_ordering

        if input_ordering == 'bitreversed':
            self.IS_NATURAL_ORDER = False
            self.INPUT_STRIDE = 2**stage_nr  # distance from butterfly input a to b
            self.LOCAL_FFT_SIZE = global_fft_size // self.INPUT_STRIDE
            self.CONTROL_MASK = (self.LOCAL_FFT_SIZE - 1)

            twid = [
                W(i, self.LOCAL_FFT_SIZE)
                for i in range(self.LOCAL_FFT_SIZE // 2)
            ]
            twid = toggle_bit_reverse(twid)
            twid = np.roll(twid, 1, axis=0)
            self.TWIDDLES = [
                Complex(x,
                        0,
                        -(twiddle_bits - 1),
                        overflow_style='saturate',
                        round_style='round') for x in twid
            ]

        elif input_ordering == 'natural':
            self.IS_NATURAL_ORDER = True
            self.LOCAL_FFT_SIZE = global_fft_size // 2**stage_nr
            self.INPUT_STRIDE = self.LOCAL_FFT_SIZE // 2
            self.CONTROL_MASK = (self.INPUT_STRIDE - 1)

            self.TWIDDLES = [
                Complex(W(i, self.LOCAL_FFT_SIZE),
                        0,
                        -(twiddle_bits - 1),
                        overflow_style='saturate',
                        round_style='round') for i in range(self.INPUT_STRIDE)
            ]

        self.IS_TRIVIAL_MULTIPLIER = len(
            self.TWIDDLES) == 1  # mult by 1.0, useless
        self.shr = ShiftRegister([Complex() for _ in range(self.INPUT_STRIDE)])
        self.twiddle = self.TWIDDLES[0]
        self.stage1_out = Complex(0, 0, -17)
        self.stage2_out = Complex(0, 0, -17 - (twiddle_bits - 1))
        self.output_index = 0
        self.mode_delay = False
        self.control = 0  # replacing this with fixed-point counter saves no resources..

        self.out = DataValid(Complex(0, 0, -17, round_style='round'),
                             valid=False)
        self.start_counter = DownCounter(2 + self.INPUT_STRIDE)