ddorling
Joined: 24 Dec 2007 Posts: 13
|
Help using MAC instruction |
Posted: Fri May 29, 2009 5:42 am |
|
|
Hi
Is anyone using the MAC instruction
Code: |
Wd*Wc,acc,da,dc
Acc = Acc + Wa * Wb; {[W13] = Acc}; {prefetch}
|
I'm building a simple 2nd order bandpass bank and need this instruction to work
Using compiler 4.092 and 30f3013 it hasn't worked yet
If anyone who has had success can give me any information about implementing this instruction, my hat off to you.
This instance of the instruction was posted on the forum
MAC w5*w6,A,[w8]+=2,w5,[w10]+=2,w6
and doesn't seem to work
The operands are not members of those specified by microchip and I wonder if this has anything to do with the problem. I have always assumed CCS compiler has it's own way of accomplishing the tasks at hand so maybe this difference is not the problem at all.
microchip implementaion for MAC
Code: |
Syntax: {label:} MAC A, Wm*Wn ,Wxp,[Wx] ,Wyp,[Wy] ,AWB
B, ,Wxp,[Wx]+=kx ,Wyp,[Wy]+=ky none
,Wxp,[Wx]-=kx ,Wyp,[Wy]-=ky
,Wxp,[W5+W8] ,Wyp,[W7+W8]
none none
|
Code: | Operands: Wm*Wn {W0*W1; W0*W2; W0*W3; W1*W2; W1*W3; W2*W3}
Wxp {W0 ... W3}; Wx {W4, W5}; kx {-6, -4, -2, 2, 4, 6};
Wyp {W0 ... W3}; Wy {W6, W7}; ky {-6, -4, -2, 2, 4, 6};
AWB {W9, [W9]++} |
So please let me know if the instruction is working or if I need to be patient and wait for it to be fixed.
A simple snippet using the MAC instruction. I thought the instruction pretches for the next instruction, so loaded the first values myself.
The prefetch operations appear correct and the data registers have the correct values at the post instruction step showing in the watch window.
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 |
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
//CCS Compiler ver 4.092
Code: | #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
} |
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 |
|
|