* Make the FFT size a bit larger.
[matthijs/projects/montium-fft.git] / FFT_support.cpp
1 #include "FFT.h"\r
2 #include <cstdio>\r
3 #include <cmath>\r
4 \r
5 /* Use Q15 fixed point format (1 sign bit plus 15 fractional bits) */\r
6 #define FIXED_POINT 15\r
7 #define WORD_SIZE   16\r
8 \r
9 #define WORDS_PER_LINE 4\r
10 #define WORDS_PER_GROUP 1\r
11 \r
12 mem input_a_re, input_a_im, input_b_re, input_b_im, output_a_re, output_a_im, output_b_re, output_b_im, twiddle_re, twiddle_im; \r
13 \r
14 int to_fixed(float n)\r
15 {\r
16         int res = (int)(n * (1 << FIXED_POINT));\r
17         /* Crop results */\r
18         if (res > (1 << WORD_SIZE - 1) - 1)\r
19                 return (1 << WORD_SIZE - 1) - 1;\r
20         if (res < -(1 << WORD_SIZE - 1))\r
21                 return -(1 << WORD_SIZE - 1);\r
22         return res;\r
23 }\r
24 \r
25 float from_fixed(int n)\r
26 {\r
27         return n / (float)(1<<FIXED_POINT);\r
28 }\r
29 \r
30 void print_mem(mem m, int offset, int size, bool fixed, bool newline)\r
31 {\r
32         int i;\r
33         for(i = offset;i<offset+size;i++)\r
34         {\r
35                 if (fixed)\r
36                         printf("%0.4f", from_fixed(get_mem(m->id, i)));\r
37                 else\r
38                         printf("%04hx", (short)get_mem(m->id, i));\r
39                 if (newline && (i + 1) % WORDS_PER_LINE == 0)\r
40                         printf("\n");\r
41                 else if ((i + 1) % WORDS_PER_GROUP == 0)\r
42                         printf(" ");\r
43         }\r
44         if (newline && i % WORDS_PER_LINE != 0)\r
45                 printf("\n");\r
46 }\r
47 \r
48 \r
49 void pre_run()\r
50 {\r
51         int i;\r
52         /* Assign memories, at least for the first stage */\r
53         input_a_re   = alloc_mem(P0M0);\r
54         input_a_im   = alloc_mem(P1M0);\r
55         input_b_re   = alloc_mem(P2M0);\r
56         input_b_im   = alloc_mem(P3M0);\r
57         \r
58         twiddle_re   = alloc_mem(P4M0);\r
59         twiddle_im   = alloc_mem(P4M1);\r
60         \r
61         /* TODO: Init memory and twiddles */\r
62         for (i=0;i<PARAM_N_t/2;i++)\r
63         {\r
64                 set_mem(twiddle_re->id, i, to_fixed(cos(i*2*M_PI/PARAM_N_t)));\r
65                 set_mem(twiddle_im->id, i, to_fixed(sin(i*2*M_PI/PARAM_N_t)));\r
66         }\r
67         \r
68         for (i=0;i<PARAM_N_t;i++)\r
69         {\r
70                 /* We take the sine from 0 to 20*2*Pi, ie twenty periods. We divide \r
71                  * the value by PARAM_N_t to prevent overflow. */\r
72                 int value = to_fixed(sin((float)i*20*2*M_PI/PARAM_N_t)/PARAM_N_t);\r
73 \r
74                 if (i<PARAM_N_t/2)\r
75                 {\r
76                         if (i % 2 == 0) {\r
77                                 set_mem(input_a_re->id, i, value);\r
78                                 set_mem(input_a_im->id, i, 0);\r
79                         } else {\r
80                                 set_mem(input_b_re->id, i, value);\r
81                                 set_mem(input_b_im->id, i, 0);\r
82                         }\r
83                 }\r
84                 else\r
85                 {\r
86                         if (i % 2 == 0) {\r
87                                 set_mem(input_b_re->id, i - PARAM_N_t/2, value);\r
88                                 set_mem(input_b_im->id, i - PARAM_N_t/2, 0);\r
89                         } else {\r
90                                 set_mem(input_a_re->id, i - PARAM_N_t/2, value);\r
91                                 set_mem(input_a_im->id, i - PARAM_N_t/2, 0);\r
92                         }\r
93                 }\r
94         }\r
95         \r
96         printf("re(W)\n");\r
97         print_mem(twiddle_re, 0, PARAM_N_t/2, true, true);\r
98         printf("im(W)\n");\r
99         print_mem(twiddle_im, 0, PARAM_N_t/2, true, true);\r
100         printf("re(in_a)\n");\r
101         print_mem(input_a_re, 0, PARAM_N_t/2, true, true);\r
102         printf("re(in_b)\n");\r
103         print_mem(input_b_re, 0, PARAM_N_t/2, true, true);\r
104 \r
105         printf("re_in = [");\r
106         print_mem(input_a_re, 0, PARAM_N_t/2, true, false);\r
107         print_mem(input_b_re, 0, PARAM_N_t/2, true, false);\r
108         printf("];\n");\r
109 \r
110 /* Write out memory contents for use by the python simulator */\r
111         save_mem_range_to_file(input_a_re->id, 0, PARAM_N_t/2, "Memory/sin_a_re.mm");\r
112         save_mem_range_to_file(input_a_im->id, 0, PARAM_N_t/2, "Memory/sin_a_im.mm");\r
113         save_mem_range_to_file(input_b_re->id, 0, PARAM_N_t/2, "Memory/sin_b_re.mm");\r
114         save_mem_range_to_file(input_b_im->id, 0, PARAM_N_t/2, "Memory/sin_b_im.mm");\r
115         save_mem_range_to_file(twiddle_re->id, 0, PARAM_N_t/2, "Memory/twiddle_re.mm");\r
116         save_mem_range_to_file(twiddle_im->id, 0, PARAM_N_t/2, "Memory/twiddle_im.mm");\r
117 }\r
118 \r
119 void post_run()\r
120 {\r
121         if (PARAM_n_t % 2 == 0) {\r
122                 /* When the number of stages is even, the \r
123                  * outputs end up at the left memories again */\r
124                 output_a_re  = alloc_mem(P0M0);\r
125                 output_a_im  = alloc_mem(P1M0);\r
126                 output_b_re  = alloc_mem(P2M0);\r
127                 output_b_im  = alloc_mem(P3M0);\r
128         } else {\r
129                 output_a_re  = alloc_mem(P0M1);\r
130                 output_a_im  = alloc_mem(P1M1);\r
131                 output_b_re  = alloc_mem(P2M1);\r
132                 output_b_im  = alloc_mem(P3M1);\r
133         }\r
134         printf("re_out = [");\r
135         print_mem(output_a_re, 0, PARAM_N_t/2, true, false);\r
136         print_mem(output_b_re, 0, PARAM_N_t/2, true, false);\r
137         printf("];\n");\r
138         printf("im_out = [");\r
139         print_mem(output_a_im, 0, PARAM_N_t/2, true, false);\r
140         print_mem(output_b_im, 0, PARAM_N_t/2, true, false);\r
141         printf("];\n");\r
142         /*\r
143         printf("re(out)\n");\r
144         print_mem(output_a_re, 0, PARAM_N_t/2, false, true);\r
145         print_mem(output_b_re, 0, PARAM_N_t/2, false, true);\r
146         printf("im(out)\n");\r
147         print_mem(output_a_im, 0, PARAM_N_t/2, false, true);\r
148         print_mem(output_b_im, 0, PARAM_N_t/2, false, true);\r
149         */\r
150 \r
151 }\r