2010-08-23 17 views
9

Estoy implementando un filtro FIR en un procesador ARM9 y estoy tratando de usar la instrucción SMLAL.Uso de la instrucción de acumulación de múltiples en línea Ensamblaje en C++

Inicialmente tuve implementado el siguiente filtro y funcionó perfectamente, excepto que este método usa demasiada potencia de procesamiento para ser utilizado en nuestra aplicación.

uint32_t DDPDataAcq::filterSample_8k(uint32_t sample) 
{ 
    // This routine is based on the fir_double_z routine outline by Grant R Griffin 
    // - www.dspguru.com/sw/opendsp/alglib.htm 
    int i = 0; 
    int64_t accum = 0; 
    const int32_t *p_h = hCoeff_8K; 
    const int32_t *p_z = zOut_8K + filterState_8K; 


    /* Cast the sample to a signed 32 bit int 
    * We need to preserve the signdness of the number, so if the 24 bit 
    * sample is negative we need to move the sign bit up to the MSB and pad the number 
    * with 1's to preserve 2's compliment. 
    */ 
    int32_t s = sample; 
    if (s & 0x800000) 
     s |= ~0xffffff; 

    // store input sample at the beginning of the delay line as well as ntaps more 
    zOut_8K[filterState_8K] = zOut_8K[filterState_8K+NTAPS_8K] = s; 

    for (i =0; i<NTAPS_8K; ++i) 
    { 
     accum += (int64_t)(*p_h++) * (int64_t)(*p_z++); 
    } 

    //convert the 64 bit accumulator back down to 32 bits 
    int32_t a = (int32_t)(accum >> 9); 


    // decrement state, wrapping if below zero 
    if (--filterState_8K < 0) 
     filterState_8K += NTAPS_8K; 

    return a; 
} 

que han estado tratando de reemplazar el acumulan multiplican con el montaje en línea desde GCC no está utilizando una instrucción MAC incluso con la optimización activada. He sustituido el bucle for con lo siguiente:

uint32_t accum_low = 0; 
int32_t accum_high = 0; 

for (i =0; i<NTAPS_4K; ++i) 
{ 
    __asm__ __volatile__("smlal %0,%1,%2,%3;" 
     :"+r"(accum_low),"+r"(accum_high) 
     :"r"(*p_h++),"r"(*p_z++)); 
} 

accum = (int64_t)accum_high << 32 | (accum_low); 

La salida ahora consigo el uso de la instrucción no está SMLAL los datos filtrados que estaba esperando. He estado obteniendo valores aleatorios que parecen no tener ningún patrón o conexión con la señal original o los datos que estoy esperando.

Tengo la sensación de que estoy haciendo algo mal al dividir el acumulador de 64 bits en los registros altos y bajos para la instrucción, o los estoy volviendo a armar mal. De cualquier manera, no estoy seguro de por qué no puedo obtener la salida correcta al intercambiar el código C con el ensamblaje en línea.

+0

¿Por qué no utiliza una biblioteca DSP? –

+4

¿Qué versión de compilador estás usando? Intenté compilar tu código C solo usando GCC 4.4.3 usando las opciones -O3 -march = armv5te y generó las instrucciones smlal. –

+0

He estado usando 4.3.2. No sabía que pudiera especificar el distintivo -march así. Una vez que lo agregué, GCC también estaba produciendo el montaje que estaba esperando. ¡Gracias! –

Respuesta

3

¿Qué versión de compilador estás usando? Intenté compilar tu código C solo usando GCC 4.4.3 usando las opciones -O3 -march = armv5te y generó las instrucciones smlal.

Cuestiones relacionadas