1 // *************************************************************************
2 // multiply function (c version)
3 // -------------------------------------------------------------------------
10 while(in
> 0) { counter
++; in
= in
>> 1; }
14 void fft(fftval_t workspace_real
[], fftval_t workspace_imag
[],
15 const fftval_t tf_real
[], const fftval_t tf_imag
[]) //size is FFT_SIZE
17 const int num_stage_ops
= FFT_SIZE
>> 1;
18 const int logfftsize
= log2down(FFT_SIZE
);
21 // First, setup hwacha to what we need:
22 #if defined(FFT_FIXED)
23 // num_stage_ops VL, 9 x-reg (1 zero, 2 ctrl, 4 data, 2 scratch), 1 fpu (avert bug)
24 asm volatile ("vsetcfg 9, 1");
25 #elif defined(FFT_FLOATING)
26 asm volatile ("vsetcfg 8, 6");
27 #if defined(FP_SINGLE)
28 // asm volatile ("vsetprec 32");
29 #elif defined(FP_HALF)
30 // asm volatile ("vsetprec 16");
31 #elif defined(FP_DOUBLE)
36 asm volatile ("vsetvl %[gvl], %[nvl]" : [gvl
]"=r"(given_vl
) : [nvl
]"r"(num_stage_ops
));
37 asm volatile ("fence"); // Make sure prefilling of workspace is complete
39 for(int stage
= 0; stage
< logfftsize
; stage
++)
41 const int half_cur_fft_size
= (1 << stage
);
42 const int sel_block_op
= half_cur_fft_size
-1;
43 const int sel_block
= ~sel_block_op
;
44 const int tf_scale
= logfftsize
- stage
- 1;
47 for(int lane_start
= 0; lane_start
< num_stage_ops
; lane_start
+= given_vl
)
49 // Setup new vector length for this stripmining pass
50 const int needed_vl
= num_stage_ops
- lane_start
;
51 asm volatile ("vsetvl %[gvl], %[nvl]" : [gvl
]"=r"(given_vl
) : [nvl
]"r"(needed_vl
));
53 #if defined(FFT_FIXED)
54 // First VF block to have vector unit determine what op it is doing
56 vmsv vx1, %[lane_start]
57 vmsv vx2, %[sel_block]
58 vmsv vx3, %[sel_block_op]
62 )": // no output registers
63 : [lane_start
]"r"(lane_start
),
64 [sel_block
]"r"(sel_block
),
65 [sel_block_op
]"r"(sel_block_op
),
66 [tf_scale
]"r"(tf_scale
),
67 [half_cfs
]"r"(half_cur_fft_size
),
68 [vf_ptr
]"r"(&vf_fft_init
)
72 // Second VF block loads tf and op2 then calculates scale factor
76 vmsv vx6, %[workspace_real]
77 vmsv vx7, %[workspace_imag]
80 )": // no output registers
81 : [tf_real
]"r"(tf_real
),
82 [tf_imag
]"r"(tf_imag
),
83 [workspace_real
]"r"(workspace_real
),
84 [workspace_imag
]"r"(workspace_imag
),
86 [vf_ptr
]"r"(&vf_fft_scale
)
89 #elif defined(FFT_FLOATING)
90 // First VF block to have vector unit determine what op it is doing
92 vmsv vx1, %[lane_start]
93 vmsv vx2, %[sel_block]
94 vmsv vx3, %[sel_block_op]
98 )": // no output registers
99 : [lane_start
]"r"(lane_start
),
100 [sel_block
]"r"(sel_block
),
101 [sel_block_op
]"r"(sel_block_op
),
102 [tf_scale
]"r"(tf_scale
),
103 [half_cfs
]"r"(half_cur_fft_size
),
104 [vf_ptr
]"r"(&vf_fft_init
)
108 // Second VF block loads tf and op2 then calculates scale factor
112 vmsv vx6, %[workspace_real]
113 vmsv vx7, %[workspace_imag]
115 )": // no output registers
116 : [tf_real
]"r"(tf_real
),
117 [tf_imag
]"r"(tf_imag
),
118 [workspace_real
]"r"(workspace_real
),
119 [workspace_imag
]"r"(workspace_imag
),
120 [vf_ptr
]"r"(&vf_fft_scale
)
124 #error no mode selected in vec-fft/vec-fft.c
127 // Third VF block actually calculates the results
129 vmsv vx5, %[workspace_real]
130 vmsv vx6, %[workspace_imag]
132 )": // no output registers
133 : [workspace_real
]"r"(workspace_real
),
134 [workspace_imag
]"r"(workspace_imag
),
135 [vf_ptr
]"r"(&vf_fft_exec
)
139 // Fourth VF block stores first result
141 vmsv vx3, %[workspace_real]
142 vmsv vx4, %[workspace_imag]
144 )": // no output registers
145 : [workspace_real
]"r"(workspace_real
),
146 [workspace_imag
]"r"(workspace_imag
),
147 [vf_ptr
]"r"(&vf_fft_store1
)
151 // Fifth VF block stores second result
153 vmsv vx3, %[workspace_real]
154 vmsv vx4, %[workspace_imag]
156 )": // no output registers
157 : [workspace_real
]"r"(workspace_real
),
158 [workspace_imag
]"r"(workspace_imag
),
159 [vf_ptr
]"r"(&vf_fft_store2
)
166 asm volatile ("fence"); // Make sure all that work from vector unit is visible to CPU