Technical discussions about the TI C6000 DSPs (including the c62x, c64x and c67x DSPs).
|
Hi C6x champs, Now I'm having a problem with some float calculations on a C6701... Essentially, I need to calculate the energy density ED=real^2 + imag^2 of a complex FFT output bin (X=real + j*imag) to get the amplitude=sqrtf(ED). The function below normally works fine but occasionally it calculates ED as INF (infinity) and following the ampltidue as NAN (not a number). First, we thought that the complex inputs are to big exceeding the float boundaries but even after scaling them down the errors were still present occasionally. Secondly, we checked out the input data and forced the CPU to step through the calculations. Surprisingly, no INF / NAN problems occured anymore. Hence, I believe it has something to do with dynamic pipeline or bus-loading effects (the traffic on the CPU, the EMIF, the peripheral bus and on the DMAs is quite high in this project). Has anybody come accross a similiar problem and know how to solve it? I managed to suppress the problem "a bit" by using 2*16 MByte SDRAM banks (CE2 and CE3) instead of just 1 bank (CE3) but I don't see a clear connection with my problem. How can the CPU miscalculate the result only occasionally? I thought that the pipeline will be stalled automatically until the (correct) data are available from the EMIF and the internal hardware architecture will take care of data movements. However, now I have now doubts about that and don't know how to tackle the problem. Thank you for your help, Regards Phil BTW: I use -o3, speed most critical, alias=default and interrupt treshold=1 on this function /************************************************************************ * Function Name : energy_amp_average() * * Purpose : This function calculates * an averaged energy density vector plus * an averaged amplitude vector * * Inputs : - input : buffer with complex fft spectrum * - samples : number of samples to process * * Outputs : - energy_avg : buffer with averaged energy density vector * - amp_avg : buffer with averaged amplitude vector * * Returned Value : none ************************************************************************/ void energy_amp_average(struct complex *input, float *energy_avg, float *amp_avg, int samples) { int i; float ED; /* if X is given as real + j*imag -> ED=real^2 + imag^2 */ for(i = 0; i < samples; i++) { ED= (input[i].real * input[i].real) + (input[i].imag * input[i].imag); energy_avg[i] += ED; /* add AL to averaged energy-density */ amp_avg[i] += sqrtf(ED); /* calculate amplitude = sqrtf(ED) */ } } -- --------------------------------------------------------------- Dipl.- Inf. Phil Alder Field Application Engineer DSPecialists GmbH Rotherstraße 22 10245 Berlin Email: Germany www.DSPecialists.de --------------------------------------------------------------- DSPecialists Making the Impossible Work ! |
|
Hi Phil, I'd still suggest you to check the input for intermediate overflow, e.g. result of SQRT(X**2 + Y**2) can fits to floating point range just Okay, but the interim result, the sum of squares may overflow. C67xx would produce Inf in this case, and further, the Inf input to the sqrtf() function would result in NaN, as specified in the IEEE floating point math standard. Sometimes, if the input range is unknown apriory and time constraints are not overly tight, one can use the following algorithm: X,Y -- input A = MAX(ABS(X),ABS(Y)) B = MIN(ABS(X),ABS(Y)) RES = A * SQRT(1.0 + (B/A)**2) This algorithm involves 1 division, but greatly increases safe range for sum of squares. As it is clearly seen, the input to SQRT is in the range [1.0, 2.0], so no NaN can be the result of SQRT(). But still A * SQRT() may overflow... I really doubt it that the data memory controller misses memory access and read in incorrect data; it used to be in Rev. 0 C6701 that LDDW instruction reads incorrect upper 32 bits from external memory; I think pipeline is stalles correctly while DMEMC waits for the memory access in EMIF. Your code (as far as I can see it) unlikely uses LDDW to read in real anad imaginary parts of a complex sample. Could you try to store the indices of entries in your input whose results are Infs and subsequently NaNs without stepping through the code in debugger? Just add a few lines of code that checks result and and place the index of a sample under question into an integer array? You can inspect later these entries in the input for intermediate overflows. Hope this helps, Andrew -- Andrew V. Nesterov () Optimized TMS320C6000 DSP Software Generic Digital Design, Inc. > Date: Thu, 14 Mar 2002 16:01:01 +0100 > From: Phil Alder <> > Subject: NAN / INF errors on C6701 > > Hi C6x champs, > > Now I'm having a problem with some float calculations on a C6701... > Essentially, I need to calculate the energy density ED=real^2 + imag^2 > of a complex FFT output bin (X=real + j*imag) to get the amplitude=sqrtf(ED). > The function below normally works fine but occasionally it calculates ED as INF > (infinity) and following the ampltidue as NAN (not a number). > > First, we thought that the complex inputs are to big exceeding the float boundaries > but even after scaling them down the errors were still present occasionally. > > Secondly, we checked out the input data and forced the CPU to step through the > calculations. Surprisingly, no INF / NAN problems occured anymore. Hence, I > believe it has something to do with dynamic pipeline or bus-loading effects (the traffic > on the CPU, the EMIF, the peripheral bus and on the DMAs is quite high in this project). > > Has anybody come accross a similiar problem and know how to solve it? > > I managed to suppress the problem "a bit" by using 2*16 MByte SDRAM banks > (CE2 and CE3) instead of just 1 bank (CE3) but I don't see a clear connection with > my problem. How can the CPU miscalculate the result only occasionally? > I thought that the pipeline will be stalled automatically until the (correct) data are > available from the EMIF and the internal hardware architecture will take care > of data movements. However, now I have now doubts about that and don't > know how to tackle the problem. > > Thank you for your help, > Regards Phil > > BTW: I use -o3, speed most critical, alias=default and interrupt > treshold=1 on this function > /************************************************************************ > * Function Name : energy_amp_average() > * > * Purpose : This function calculates > * an averaged energy density vector plus > * an averaged amplitude vector > * > * Inputs : - input : buffer with complex fft spectrum > * - samples : number of samples to process > * > * Outputs : - energy_avg : buffer with averaged energy density vector > * - amp_avg : buffer with averaged amplitude vector > * > * Returned Value : none > ************************************************************************/ > void energy_amp_average(struct complex *input, float *energy_avg, float *amp_avg, int samples) > { > int i; > float ED; /* if X is given as real + j*imag -> ED=real^2 + imag^2 */ > > for(i = 0; i < samples; i++) > { > ED= (input[i].real * input[i].real) + (input[i].imag * input[i].imag); > > energy_avg[i] += ED; /* add AL to averaged energy-density */ > amp_avg[i] += sqrtf(ED); /* calculate amplitude = sqrtf(ED) */ > } > } > -- > --------------------------------------------------------------- > Dipl.- Inf. > Phil Alder > Field Application Engineer > DSPecialists GmbH > Rotherstraße 22 > 10245 Berlin Email: > Germany www.DSPecialists.de > --------------------------------------------------------------- > DSPecialists Making the Impossible Work ! |
|
|