|
|
View previous topic :: View next topic |
Author |
Message |
ddorling
Joined: 24 Dec 2007 Posts: 13
|
MAC instruction Assembly dsp 4.092 mysterious |
Posted: Tue May 19, 2009 5:46 pm |
|
|
Can someone see what's going wrong here.
A simple snippet using the MAC instruction. I thought the instruction pretches for the next instruction, so loaded the first values myself.
The prefetche operations appear correct and the data registers have the correct values at the post instruction step.
This is the disassembly listing for the MAC instruction MAC w5*w6,A,[w8]+=2,w5,[w10]+=2,w6
Code: | mac 0x000a*0x000c,a,[0x0010]+=2,0x000a,[0x0014]+=2,0x000c |
Here's the wacky stuff.
The first accum prefetches for the next instruction but doubles a correct(15) result.
The second accum prefetches for the next instruction accumulates a correct(0) result but then doubles this result. Shouldn't have changed at all.
The third accum prefetches for the next instruction but accumulates a zero result where the accumlation should have been -5. doesn't seem to have done the multiply.
The fourth accum prefetches for the next instruction but accumulates a -10 result where the accumlation should have been -5
The fifth accum prefetches for the next instruction but accumulates a -8 result where the accumlation should have been -6
Code: | //CCS Compiler ver 4.092
#include <30F3013.h>
#device ICD=TRUE
#FUSES NOWDT //No Watch Dog Timer
#FUSES EC_IO //External clock
#FUSES PR //Primary Oscillator
#FUSES NOCKSFSM //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES WPSB16 //Watch Dog Timer PreScalar B 1:16
#FUSES WPSA512 //Watch Dog Timer PreScalar A 1:512
#FUSES PUT64 //Power On Reset Timer value 64ms
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV47 //Brownout reset at 4.7V
#FUSES LPOL_HIGH //Low-Side Transistors Polarity is Active-High (PWM 0,2,4 and 6)
#FUSES HPOL_HIGH //High-Side Transistors Polarity is Active-High (PWM 1,3,5 and 7)
#FUSES NOPWMPIN //PWM outputs drive active state upon Reset
#FUSES MCLR //Master Clear pin enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOWRT //Program memory not write protected
#FUSES DEBUG //Debug mode for use with ICD
#FUSES NOCOE //Device will reset into operational mode
#FUSES ICSP1 //ICD uses PGC1/PGD1 pins
#FUSES RESERVED //Used to set the reserved FUSE bits
#use delay(clock=20000000)
#word ACCA=0x022
#BankX signed int ACoef[5]={5,0,-5,-2,3};
#BankY signed int Xdata[5]={3,0, 1, 2,-2};
int *ptrAcoef,*ptrXdata;
void main()
{
setup_wdt(WDT_OFF);
setup_timer1(TMR_DISABLED);
ptrAcoef= ACoef;
ptrXdata= Xdata;
*ACCA=0;
ptrAcoef= ACoef; //set coef pointers
ptrXdata= Xdata; //set data pointers
#asm
MOV ptrAcoef,W8 //load coef address
MOV ptrXdata,W10 //load data address
MOV Acoef[0],W5 //move first values to registers
MOV Xdata[0],W6
// xx? accA result (xx) correct result +(x*x) operation
//accumulate terms
nop
MAC w5*w6,A,[w8]+=2,w5,[w10]+=2,w6 //30? (15) +(5*3)
nop
nop
MAC w5*w6,A,[w8]+=2,w5,[w10]+=2,w6 //60? (15) +(0*0)
nop
nop
MAC w5*w6,A,[w8]+=2,w5,[w10]+=2,w6 //60? (10) +(-5*1)
nop
nop
MAC w5*w6,A,[w8]+=2,w5,[w10]+=2,w6 //50? (6) +(-2*2)
nop
nop
MAC w5*w6,A,[w8]+=2,w5,[w10]+=2,w6 //42? (0) +(3*-2)
nop
nop
#endasm
} |
|
|
|
ddorling
Joined: 24 Dec 2007 Posts: 13
|
accumulator doubling multiply result |
Posted: Tue May 19, 2009 8:58 pm |
|
|
Here is some more info.
Rather than using the prefetch part of the instruction I move the data directly into the registers. This works except that the accumulator adds a doubling of the multiply result.
Code: |
#asm
MOV ptrAcoef,W8 //load coef address
MOV ptrXdata,W10 //load data address
//accumulate terms
nop
MOV Acoef[0],W5
MOV Xdata[0],W6
MAC w5*w6,A,[w8]+=2,w5,[w10]+=2,w6 //30? (15) +(5*3)
nop
nop
MOV Acoef[1],W5
MOV Xdata[1],W6
MAC w5*w6,A,[w8]+=2,w5,[w10]+=2,w6 //30? (15) +(0*0)
nop
nop
MOV Acoef[2],W5
MOV Xdata[2],W6
MAC w5*w6,A,[w8]+=2,w5,[w10]+=2,w6 //20? (10) +(-5*1)
nop
nop
MOV Acoef[3],W5
MOV Xdata[3],W6
MAC w5*w6,A,[w8]+=2,w5,[w10]+=2,w6 //12? (6) +(-2*2)
nop
nop
MOV Acoef[4],W5
MOV Xdata[4],W6
MAC w5*w6,A,[w8]+=2,w5,[w10]+=2,w6 //0? (0) +(3*-2)
nop
nop
#endasm |
|
|
|
sevak Guest
|
Re: accumulator doubling multiply result |
Posted: Wed Jul 15, 2009 12:28 am |
|
|
Hi,
Have you got the reason why it is happening so?
If you got the reason please let me know. I am facing the same problem but not getting anything. |
|
|
ddorling
Joined: 24 Dec 2007 Posts: 13
|
MAC assembly 30f |
Posted: Thu Jul 16, 2009 1:37 am |
|
|
Hi
I am just an average programmer and came to the conclusion that the MAC assembly instruction isn't implemented in the CCS compiler to accomplish what it is suppose to do according to the microchip specification. This conclusion I arrived at by default, since my request to CCS and this forum had zero response. Since I needed this instruction for a filtering application I had to resort to the C30 compiler.
I hope you didn't have the frustration I did since I usually think it's my programming causing the problem. Unfortunately I wasted too many days banging my head against the wall before reaching the conclusion.
I don't think the CCS compiler has much functionality regarding the 24f and 30f family and heavens to mercy don't even think about the 33f family.
I wish CCS would respond or a programmer knowledgeable in CCS and say my statement is incorrect. This would make me very happy since I liked the compiler for 8 bit chips and wish I could use the compiler for 16 bit chips. But the improvements to the compiler, now 4.093? show that improving and fixing 16 bit functionality is low priority.
CCS has a daunting task, when you think about it, accommodating so many different chips. They do a good job providing a user friendly programming environment for the 8 bits but the 16 bit are in another league of capability. I wish CCS would make a statement about this regarding the functionality of their compiler regarding the 16 bit chips. From the advertising on their website you think the compiler can get the job done to tame these 16 bit animals but this is far from true.
Unfortunately there has been an expense to my $ to find this out, one year maintenance plan and PCD.
You can download the C30 compiler for free and it will provide full optimization for 60 days. For me it is a matter of time before I can afford the expense to buy C30 but until then reboot computer and reload, and endure the inconvenience. And I'll continue to use CCS for 8 bit animals.
Good Luck
ddorling
C30 code for digital filter
Code: | #include "p30f3013.h"
#include "dsp.h" //some or all of the includes not necessary for this snippet
#include "spi.h"
#include "libpic30.h"
#include "math.h"
//BP3 1152 Microchip elliptic 1152
signed int XYdata3[6] _YDATA(32) = {0,0,0,0,0,0}; // input/output samples
signed int ABcoef3[6] _XDATA(32) = {1275,0,-1275,-16392,22620,-13833}; // BCoef negated
int ACCUMAold3[3]_XDATA(16) ={0,0,0};
int BPout3=0;
int *ADCptr0; //ADC Buffer0
int audio_in0=0,
void ADC_Init(void);
int main (void)
{
loop:
ADC_Init();
//********** Get New Audio Samples
IFS0bits.ADIF = 0; // clear ADC interrupt flag
ADCON1bits.ASAM = 1; // auto start sampling
while (!IFS0bits.ADIF);// // conversion done?
ADCON1bits.ASAM = 0; // yes then stop sample/convert
audio_in0= ADCBUF0; // audio sample
//***************************************************
//********** BP3 IIR
//shift the old samples x0 x1 x2 y0 y1 y2
XYdata3[5]=XYdata3[4]; XYdata3[4]=XYdata3[3]; //XYdata[3] is Y0
XYdata3[2]=XYdata3[1]; XYdata3[1]=XYdata3[0]; //XYdata[0] is X0
XYdata3[0] = audio_in0; //place new audio sample
// accum results are restored and saved if more than one filter is calculated, say BP1,BP2,BP3
ACCAL= ACCUMAold3[0]; //restore accum result
ACCAH= ACCUMAold3[1];
ACCAU= ACCUMAold3[2];
WREG8= (int)ABcoef3; //load coef address
WREG10= (int)XYdata3;
asm("MOVSAC A,[w8]+=2,w4,[w10]+=2,w5");
asm("MAC w4*w5,A,[w8]+=2,w4,[w10]+=2,w5");
asm("MAC w4*w5,A,[w8]+=4,w4,[w10]+=4,w5");
asm("MAC w4*w5,A,[w8]+=2,w4,[w10]+=2,w5");
asm("MAC w4*w5,A,[w8]+=2,w4,[w10]+=2,w5");
asm("MAC w4*w5,A");
asm("SFTAC A,#0xF"); //divide by BCoef[0]
//plus a RS to adjust for double accumulation behavior
XYdata3[3]= (int)ACCAL; //save new Y[0]
ACCUMAold3[0]=ACCAL; //save accum result
ACCUMAold3[1]=ACCAH;
ACCUMAold3[2]=ACCAU;
BPout3= abs(XYdata3[3])<<1;
goto loop;
return(0);}
//*****************************************************
//*****************************************************
void ADC_Init(void)
{
/*
Sampling is a sequence an0. The method uses the internal counter
SSRC, to carry out a sampling period, when finished automaticly converts.
Setting ASAM=1 starts sampling the sequence and automatically repeats samplng
after each conversion. Each ANx is connected to CH0 in sequence for sampling.
When the sequence is finished an intterupt flag is set. Method waits until the
flag is set. Then turns off ASAM. Results are placed sequentially in the Buffers.
*/
_TRISB0=1;_TRISB1=1; //RB0 RB1 as inputs
//---------------------------------------------------------
//(ADCON1 Register)
ADCON1=0b0000000011100000;
ADCON1bits.SSRC=7; //<7-5> internal counter ends sampling and starts covert
ADCON1bits.FORM=0; //<9-8> integer out
ADCON1bits.ADON=0; //<15> adc OFF
//-------------------------------------------------------------
//(ADCON2 Register)
ADCON2=0b0000000000000000;
ADCON2bits.SMPI = 1; //<5:2> interupt sequence 0f 2***
ADCON2bits.BUFM = 0; //<1> single 16 word result buffer***
ADCON2bits.ALTS = 0; //<0> use MUX A input select***
ADCON2bits.CSCNA = 1; //<10> scan CH0+ Input MUX A***
ADCON2bits.VCFG = 0; //<15:13> voltage reference vdd-vss
//------------------------------------------------------------
//(ADCON3 Register)
ADCON3=0b0000111100000000;
ADCON3bits.SAMC = 7; //<12:8> auto sample time is is 15 TAD
ADCON3bits.ADRC = 0; //<7> conversion clock is System Clock
ADCON3bits.ADCS = 3; //<5:0>conversion clock speed
//-----------------------------------------------------------
//(Input select Register)
ADCHS = 0b0000000000000000;
//ADCHSBITS.CHOSA=0; //CSNA overides this
//ADCHSBITS.CHONA=0; //select Vref- as negative for Mux A***
//-------------------------------------------------------------------
//(Port configuration Register)
ADPCFG = 0b1111111111111100; //Set channel AN0 AN1 as analog***
//-----------------------------------------------------------
//Input select scan Register
ADCSSL = 0b0000000000000011; //Scan AN0 AN1***
//--------------------------------------------------------------------
ADCON1bits.ADON = 1; //Turn on the A/D converter
return;
} | |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|