2010-08-23 7 views
9

Tôi đang triển khai bộ lọc FIR trên bộ xử lý ARM9 và đang cố gắng sử dụng lệnh SMLAL.Sử dụng Multiply Accumulate Instruction Assembly Inline Assembly trong C++

Ban đầu tôi đã triển khai bộ lọc sau và bộ lọc hoạt động hoàn hảo, ngoại trừ phương pháp này sử dụng quá nhiều sức mạnh xử lý được sử dụng trong ứng dụng của chúng tôi.

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; 
} 

Tôi đã cố gắng thay thế tích lũy nhân với lắp ráp nội tuyến vì GCC không sử dụng lệnh MAC ngay cả khi bật tối ưu hóa. Tôi đã thay thế vòng lặp for bằng các thông tin sau:

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); 

Kết quả tôi hiện đang sử dụng lệnh SMLAL không phải là dữ liệu được lọc. Tôi đã nhận được các giá trị ngẫu nhiên mà dường như không có mẫu hoặc kết nối với tín hiệu ban đầu hoặc dữ liệu tôi mong đợi.

Tôi có cảm giác mình đang làm điều gì đó sai với việc chia bộ tích lũy 64 bit vào thanh ghi cao và thấp để được hướng dẫn, hoặc tôi đặt chúng lại với nhau sai. Dù bằng cách nào tôi không chắc chắn lý do tại sao tôi không thể có được sản lượng chính xác bằng cách trao đổi mã C với lắp ráp nội tuyến.

+0

Tại sao bạn không chỉ sử dụng thư viện DSP? –

+4

Bạn đang sử dụng phiên bản trình biên dịch nào? Tôi đã thử biên dịch mã C duy nhất của bạn bằng cách sử dụng GCC 4.4.3 bằng cách sử dụng tùy chọn -O3 -march = armv5te và nó tạo ra các hướng dẫn smlal. –

+0

Tôi đã sử dụng 4.3.2. Tôi không biết bạn có thể chỉ định cờ -march như thế. Một khi tôi đã thêm nó, GCC cũng đang sản xuất lắp ráp mà tôi đã hy vọng. Cảm ơn! –

Trả lời

3

Bạn đang sử dụng phiên bản trình biên dịch nào? Tôi đã thử biên dịch mã C duy nhất của bạn bằng cách sử dụng GCC 4.4.3 bằng cách sử dụng tùy chọn -O3 -march = armv5te và nó tạo ra các hướng dẫn smlal.