OpenCores
URL https://opencores.org/ocsvn/dblclockfft/dblclockfft/trunk

Subversion Repositories dblclockfft

[/] [dblclockfft/] [trunk/] [sw/] [fftlib.cpp] - Blame information for rev 37

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 36 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    fftlib.cpp
4
//
5
// Project:     A General Purpose Pipelined FFT Implementation
6
//
7
// Purpose:     
8
//
9
// Creator:     Dan Gisselquist, Ph.D.
10
//              Gisselquist Technology, LLC
11
//
12
////////////////////////////////////////////////////////////////////////////////
13
//
14
// Copyright (C) 2015-2018, Gisselquist Technology, LLC
15
//
16
// This program is free software (firmware): you can redistribute it and/or
17
// modify it under the terms of  the GNU General Public License as published
18
// by the Free Software Foundation, either version 3 of the License, or (at
19
// your option) any later version.
20
//
21
// This program is distributed in the hope that it will be useful, but WITHOUT
22
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
23
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24
// for more details.
25
//
26
// You should have received a copy of the GNU General Public License along
27 37 dgisselq
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
28 36 dgisselq
// target there if the PDF file isn't present.)  If not, see
29
// <http://www.gnu.org/licenses/> for a copy.
30
//
31
// License:     GPL, v3, as defined and found on www.gnu.org,
32
//              http://www.gnu.org/licenses/gpl.html
33
//
34
//
35
////////////////////////////////////////////////////////////////////////////////
36
//
37
//
38
#define _CRT_SECURE_NO_WARNINGS   //  ms vs 2012 doesn't like fopen
39
#include <stdio.h>
40
#include <stdlib.h>
41
 
42
#ifdef _MSC_VER //  added for ms vs compatibility
43
 
44
#include <io.h>
45
#include <direct.h>
46
#define _USE_MATH_DEFINES
47
 
48
#if _MSC_VER <= 1700
49
 
50
long long llround(double d) {
51
        if (d<0) return -(long long)(-d+0.5);
52
        else    return (long long)(d+0.5); }
53
 
54
#endif
55
 
56
#else
57
// And for G++/Linux environment
58
 
59
#include <unistd.h>     // Defines the R_OK/W_OK/etc. macros
60
#endif
61
 
62
#include <string.h>
63
#include <string>
64
#include <math.h>
65
// #include <ctype.h>
66
#include <assert.h>
67
 
68
#include "fftlib.h"
69
 
70
 
71
int     lgval(int vl) {
72
        int     lg;
73
 
74
        for(lg=1; (1<<lg) < vl; lg++)
75
                ;
76
        return lg;
77
}
78
 
79
int     nextlg(int vl) {
80
        int     r;
81
 
82
        for(r=1; r<vl; r<<=1)
83
                ;
84
        return r;
85
}
86
 
87
int     bflydelay(int nbits, int xtra) {
88
        int     cbits = nbits + xtra;
89
        int     delay;
90
 
91
        if (USE_OLD_MULTIPLY) {
92
                if (nbits+1<cbits)
93
                        delay = nbits+4;
94
                else
95
                        delay = cbits+3;
96
        } else {
97
                int     na=nbits+2, nb=cbits+1;
98
                if (nb<na) {
99
                        int tmp = nb;
100
                        nb = na; na = tmp;
101
                } delay = ((na)/2+(na&1)+2);
102
        }
103
        return delay;
104
}
105
 
106
int     lgdelay(int nbits, int xtra) {
107
        // The butterfly code needs to compare a valid address, of this
108
        // many bits, with an address two greater.  This guarantees we
109
        // have enough bits for that comparison.  We'll also end up with
110
        // more storage space to look for these values, but without a
111
        // redesign that's just what we'll deal with.
112
        return lgval(bflydelay(nbits, xtra)+3);
113
}
114
 
115
void    gen_coeffs(FILE *cmem, int stage, int cbits,
116
                        int nwide, int offset, bool inv) {
117
        //
118
        // For an FFT stage of 2^n elements, we need 2^(n-1) butterfly
119
        // coefficients, sometimes called twiddle factors.  Stage captures the
120
        // width of the FFT at this point.  If thiss is a 2x at a time FFT,
121
        // nwide will be equal to 2, and offset will be one or two.
122
        //
123 37 dgisselq
        // assert(nwide > 0);
124
        // assert(offset < nwide);
125
        // assert(stage / nwide >  1);
126
        // assert(stage % nwide == 0);
127
        // printf("GEN-COEFFS(): stage =%4d, bits =%2d, nwide = %d, offset = %d, nverse = %d\n", stage, cbits, nwide, offset, inv);
128 36 dgisselq
        int     ncoeffs = stage/nwide/2;
129
        for(int i=0; i<ncoeffs; i++) {
130
                int k = nwide*i+offset;
131
                double  W = ((inv)?1:-1)*2.0*M_PI*k/(double)(stage);
132
                double  c, s;
133
                long long ic, is, vl;
134
 
135
                c = cos(W); s = sin(W);
136
                ic = (long long)llround((1ll<<(cbits-2)) * c);
137
                is = (long long)llround((1ll<<(cbits-2)) * s);
138
                vl = (ic & (~(-1ll << (cbits))));
139
                vl <<= (cbits);
140
                vl |= (is & (~(-1ll << (cbits))));
141
                fprintf(cmem, "%0*llx\n", ((cbits*2+3)/4), vl);
142
                //
143
        } fclose(cmem);
144
}
145
 
146
std::string     gen_coeff_fname(const char *coredir,
147
                        int stage, int nwide, int offset, bool inv) {
148
        std::string     result;
149
        char    *memfile;
150
 
151
        assert((nwide == 1)||(nwide == 2));
152
 
153
        memfile = new char[strlen(coredir)+3+10+strlen(".hex")+64];
154
        if (nwide == 2) {
155
                if (coredir[0] == '\0') {
156
                        sprintf(memfile, "%scmem_%c%d.hex",
157
                                (inv)?"i":"", (offset==1)?'o':'e', stage*nwide);
158
                } else {
159
                        sprintf(memfile, "%s/%scmem_%c%d.hex",
160
                                coredir, (inv)?"i":"",
161
                                (offset==1)?'o':'e', stage*nwide);
162
                }
163
        } else if (coredir[0] == '\0') // if (nwide == 1)
164
                sprintf(memfile, "%scmem_%d.hex",
165
                        (inv)?"i":"", stage);
166
        else
167
                sprintf(memfile, "%s/%scmem_%d.hex",
168
                        coredir, (inv)?"i":"", stage);
169
 
170
        result = std::string(memfile);
171
        delete[] memfile;
172
        return  result;
173
}
174
 
175
FILE    *gen_coeff_open(const char *fname) {
176
        FILE    *cmem;
177
 
178
        cmem = fopen(fname, "w");
179
        if (NULL == cmem) {
180
                fprintf(stderr, "Could not open FFT coefficient file "
181
                                "\'%s\' for writing\n", fname);
182
                perror("Err from O/S:");
183
                exit(EXIT_FAILURE);
184
        }
185
 
186
        return cmem;
187
}
188
 
189
void    gen_coeff_file(const char *coredir, const char *fname,
190
                        int stage, int cbits, int nwide, int offset, bool inv) {
191
        std::string     fstr;
192
        FILE    *cmem;
193
 
194
        fstr= gen_coeff_fname(coredir, stage, nwide, offset, inv);
195
        cmem = gen_coeff_open(fstr.c_str());
196
        gen_coeffs(cmem, stage,  cbits, nwide, offset, inv);
197
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.