我最近在调试MSP-DSPLib 的矩阵API,并使用LEA功能,目前矩阵的加法和减法都在自己的工程里调试成功,但是矩阵的乘法调用后计算的结果似乎不对,一直找不到原因,请高手指点一下。我用的芯片是msp430fr5992,开发环境是IAR7.10,
下面是代码截图,调用完msp_matrix_mpy_q15函数后,statu显示是MSP_SUCCESS。参数和结果见下图右侧watch 1.
Susan Yang:
您是自己的程序?我记得是有相关例程的,您有没有参考一下或者试一下?
user4461879:
回复 Susan Yang:
您好,我参考过例程matrix_ex3_mpy_q15.c文件,在移植过程中为了好验证结果,我把源例程中的对inputA[8][10]和inputB[10][12]的大小和初始化赋值(按照正弦曲线赋值)改了,改动后inputAA[2][3]和inputBB[3][2],我赋的值也比较小,容易计算一些。其他什么都没有改。但是计算的结果不对。返回状态显示是成功的。
另外我把matrix_ex3_mpy_q15.c原封不动的带入测试结果如下:
inputA:00000000000376751112514981870224126112979334517541505225329973736446951955913662111130225533724477556666367683870496950150530014479593073458716100351129412486118823745557373499057106811220613618149041225744836649872610687125061415915624168821263152137701100501221814166158581726418359
inputB:000000000000078815552281294735364033442547024857488647880155629514042471749064590380126201169-403-19340228340434877459432581175-1178-3262-4599-4883-404912953472145962628-394-3259-4818-4446-229278035390354349093259-394-3805-4879-29567824039481426310404445951178-3257-4880-2289227848773264-1168-4592044393807-1174-4815-2957227849111934-3252-4724-801047202629-3256-444378148781936-3800-405315424911048781179-4593-229040393266-3250-405222704600-1158
result:000000000000020171697-96-847-5756699-429-123343133040133383-176-1677-1171119199-846-243677265059315021-221-2456-1851634298-1235-359988389077396592-215-3163-2632097394-1584-4681267504094048074-142-3774-3532491488-1879-5671502605010897944910-4271-4572804578-2111-655168669001219010697249-4637-5763024663-2273-7291813757通过手算上面两个矩阵相乘这个结果不对。
matrix_ex3_mpy_q15.c的路径是:DSPLib_1_30_00_02\examples\Matrix\matrix_ex3_mpy_q15,
我用的芯片是msp430fr5992.
user4461879:
回复 user4461879:
Susan Yang:
关于矩阵的乘法今天下午我又测试了一下,再补充说明一下,希望能尽快找到问题。
矩阵相乘时调用的函数是:msp_matrix_mpy_q15,这个函数实际上在文件中有两个定义,程序是通过宏定义还选择执行哪一个。
如果定义了MSP_USE_LEA则执行代码1(暂且叫代码1吧)。如果没有定义MSP_USE_LEA,还要判断是否定义__MSP430_HAS_MPY32__,如果定义了__MSP430_HAS_MPY32__就执行代码2,否则执行代码3.
我的测试如下,
inputA[2][3]=1132 2132 132 1132 132 132
inputB[3][2]=199 299 33 44 55 66
手动计算的结果是:302884 440988 236884 352988
测试1:使用#undef MSP_USE_LEA 让程序执行代码2,执行的结果是9 13 7 10.(将手动计算的结果>>15后分别是9.24 13.45 7.22 10.77,取整后就是9 13 7 10),代码1里面没有看见将结果>>15的操作。
测试2:使用#undef MSP_USE_LEA 和#__MSP430_HAS_MPY32__让程序执行代码3,执行的结果也是9 13 7 10,但是代码3里面有将结果>>15的代码。
测试3:不用#undef命令,让程序执行代码1(具有LEA功能),执行结果是213 242 25 29。
不理解相同的入口参数,为什么代码1和代码2、3计算的结果不一致。虽然代码1里面我没有看见>>15的操作。
下面是msp_matrix_mpy_q15函数的定义,关键部分我用黑体标出来了。
#if defined(MSP_USE_LEA)
msp_status msp_matrix_mpy_q15(const msp_matrix_mpy_q15_params *params, const _q15 *srcA, const _q15 *srcB, _q15 *dst)
{
uint16_t srcARows;
uint16_t srcACols;
uint16_t srcBRows;
uint16_t srcBCols;
msp_status status;
MSP_LEA_MPYMATRIXROW_PARAMS *leaParams;
/* Initialize the row and column sizes. */
srcARows = params->srcARows;
srcACols = params->srcACols;
srcBRows = params->srcBRows;
srcBCols = params->srcBCols;
#ifndef MSP_DISABLE_DIAGNOSTICS
/* Check that column of A equals rows of B */
if (srcACols != srcBRows) {
return MSP_SIZE_ERROR;
}
/* Check that the data arrays are aligned and in a valid memory segment. */
if (!(MSP_LEA_VALID_ADDRESS(srcA, 4) &
MSP_LEA_VALID_ADDRESS(srcB, 4) &
MSP_LEA_VALID_ADDRESS(dst, 4))) {
return MSP_LEA_INVALID_ADDRESS;
}
/* Acquire lock for LEA module. */
if (!msp_lea_acquireLock()) {
return MSP_LEA_BUSY;
}
#endif //MSP_DISABLE_DIAGNOSTICS
/* Initialize LEA if it is not enabled. */
if (!(LEAPMCTL & LEACMDEN)) {
msp_lea_init();
}
/* Allocate MSP_LEA_MPYMATRIXROW_PARAMS structure. */
leaParams = (MSP_LEA_MPYMATRIXROW_PARAMS *)msp_lea_allocMemory(sizeof(MSP_LEA_MPYMATRIXROW_PARAMS)/sizeof(uint32_t));
/* Set status flag. */
status = MSP_SUCCESS;
/* Iterate through each row of srcA */
while (srcARows–) {
/* Set MSP_LEA_MPYMATRIXROW_PARAMS structure. */
leaParams->rowSize = srcBRows;
leaParams->colSize = srcBCols;
leaParams->colVector = MSP_LEA_CONVERT_ADDRESS(srcB);
leaParams->output = MSP_LEA_CONVERT_ADDRESS(dst);
/* Load source arguments to LEA. */
LEAPMS0 = MSP_LEA_CONVERT_ADDRESS(srcA);
LEAPMS1 = MSP_LEA_CONVERT_ADDRESS(leaParams);
/* Invoke the LEACMD__MPYMATRIXROW command. */
msp_lea_invokeCommand(LEACMD__MPYMATRIXROW);
#ifndef MSP_DISABLE_DIAGNOSTICS
/* Check LEA interrupt flags for any errors. */
if (msp_lea_ifg & LEACOVLIFG) {
status = MSP_LEA_COMMAND_OVERFLOW;
break;
}
else if (msp_lea_ifg & LEAOORIFG) {
status = MSP_LEA_OUT_OF_RANGE;
break;
}
else if (msp_lea_ifg & LEASDIIFG) {
status = MSP_LEA_SCALAR_INCONSISTENCY;
break;
}
#endif //MSP_DISABLE_DIAGNOSTICS
/* Increment srcA and dst pointers. */
srcA += srcACols;
dst += srcBCols;
}
/* Free MSP_LEA_MPYMATRIXROW_PARAMS structure. */
msp_lea_freeMemory(sizeof(MSP_LEA_MPYMATRIXROW_PARAMS)/sizeof(uint32_t));
/* Free lock for LEA module and return status. */
msp_lea_freeLock();
return status;
}
#else //MSP_USE_LEA
msp_status msp_matrix_mpy_q15(const msp_matrix_mpy_q15_params *params, const _q15 *srcA, const _q15 *srcB, _q15 *dst)
{
uint16_t cntr;
uint16_t srcARows;
uint16_t srcACols;
uint16_t srcBRows;
uint16_t srcBCols;
uint16_t dst_row;
uint16_t dst_col;
uint16_t row_offset;
uint16_t col_offset;
uint16_t dst_row_offset;
/* Initialize the row and column sizes. */
srcARows = params->srcARows;
srcACols = params->srcACols;
srcBRows = params->srcBRows;
srcBCols = params->srcBCols;
#ifndef MSP_DISABLE_DIAGNOSTICS
/* Check that column of A equals rows of B */
if (srcACols != srcBRows) {
return MSP_SIZE_ERROR;
}
#endif //MSP_DISABLE_DIAGNOSTICS
/* In initialize loop counters. */
cntr = 0;
dst_row = 0;
dst_col = 0;
row_offset = 0;
col_offset = 0;
dst_row_offset = 0;
#if defined(__MSP430_HAS_MPY32__)
/* If MPY32 is available save control context, set to fractional mode, set saturation mode. */
uint16_t ui16MPYState = MPY32CTL0;
MPY32CTL0 = MPYFRAC | MPYDLYWRTEN | MPYSAT;
/* Loop through all srcA rows. */
while(srcARows–) {
/* Loop through all srcB columns. */
while (dst_col < srcBCols) {
/* Reset result accumulator. */
MPY32CTL0 &= ~MPYC;
RESLO = 0; RESHI = 0;
/* Loop through all elements in srcA column and srcB row. */
while(cntr < srcACols) {
MACS = srcA[row_offset + cntr];
OP2 = srcB[col_offset + dst_col];
col_offset += srcBCols;
cntr++;
}
/* Store the result */
dst[dst_row_offset + dst_col] = RESHI;
/* Update pointers. */
dst_col++;
cntr = 0;
col_offset = 0;
}
/* Update pointers. */
dst_row++;
dst_col = 0;
row_offset += srcACols;
dst_row_offset += srcBCols;
}
/* Restore MPY32 control context, previous saturation state. */
MPY32CTL0 = ui16MPYState;
#else //__MSP430_HAS_MPY32__
_iq31 result;
/* Loop through all srcA rows. */
while(srcARows–) {
/* Loop through all srcB columns. */
while (dst_col < srcBCols) {
/* Initialize accumulator. */
result = 0;
/* Loop through all elements in srcA column and srcB row. */
while(cntr < srcACols) {
result += (_iq31)srcA[row_offset + cntr] * (_iq31)srcB[col_offset + dst_col];
col_offset += srcBCols;
cntr++;
}
/* Saturate and store the result */
dst[dst_row_offset + dst_col] = (_q15)__saturate(result >> 15, INT16_MIN, INT16_MAX);
/* Update pointers. */
dst_col++;
cntr = 0;
col_offset = 0;
}
/* Update pointers. */
dst_row++;
dst_col = 0;
row_offset += srcACols;
dst_row_offset += srcBCols;
}
#endif //__MSP430_HAS_MPY32__
return MSP_SUCCESS;
}
#endif //MSP_USE_LEA
user4461879:
回复 user4461879:
没人给解答一下吗,困扰2天了,自己顶一下。
user4461879:
回复 Susan Yang:
谢谢您的转发!!
今天实在没有办法了,再结合上面两条补充测试的结果,我刚刚又把matrix_ex3_mpy_q15.c测试了一下,同时手动计算了一下结果,有了一个新的发现,就是手动计算的结果>>15,然后再下取整得到的结果和例程里面计算的结果就一致了。不是特别明白为什么?是不是这个API就是这样的,返回的结果并不是直接乘加的结果,而是>>15(缩小了32768倍)。如果真实这样,那就可以肯定这个API是没有问题了。后面我再移植到自己的工程中就有信心了。
matrix_ex3_mpy_q15.c原封不动的带入测试结果如下:
inputA:0 0 0 0 0 0 0 0 0 0
0 376 751 1125 1498 1870 2241 2611 2979 3345
1 754 1505 2253 2997 3736 4469 5195 5913 6621
1 1130 2255 3372 4477 5566 6636 7683 8704 9695
0 1505 3001 4479 5930 7345 8716 10035 11294 12486
1 1882 3745 5573 7349 9057 10681 12206 13618 14904
1 2257 4483 6649 8726 10687 12506 14159 15624 16882
1 2631 5213 7701 10050 12218 14166 15858 17264 18359
inputB:0 0 0 0 0 0 0 0 0 0 0 0
0 788 1555 2281 2947 3536 4033 4425 4702 4857 4886 4788
0 1556 2951 4042 4717 4906 4590 3801 2620 1169 -403 -1934
0 2283 4043 4877 4594 3258 1175 -1178 -3262 -4599 -4883 -4049
1 2953 4721 4596 2628 -394 -3259 -4818 -4446 -2292 780 3539
0 3543 4909 3259 -394 -3805 -4879 -2956 782 4039 4814 2631
0 4044 4595 1178 -3257 -4880 -2289 2278 4877 3264 -1168 -4592
0 4439 3807 -1174 -4815 -2957 2278 4911 1934 -3252 -4724 -801
0 4720 2629 -3256 -4443 781 4878 1936 -3800 -4053 1542 4911
0 4878 1179 -4593 -2290 4039 3266 -3250 -4052 2270 4600 -1158
result: 0 0 0 0 0 0 0 0 0 0 0 0
0 2017 1697 -96 -847 -57 566 99 -429 -123 343 133
0 4013 3383 -176 -1677 -117 1119 199 -846 -243 677 265
0 5931 5021 -221 -2456 -185 1634 298 -1235 -359 988 389
0 7739 6592 -215 -3163 -263 2097 394 -1584 -468 1267 504
0 9404 8074 -142 -3774 -353 2491 488 -1879 -567 1502 605
0 10897 9449 10 -4271 -457 2804 578 -2111 -655 1686 690
0 12190 10697 249 -4637 -576 3024 663 -2273 -729 1813 757
下面是手算结果(我只计算了前面三行):
0 0 0 0 0 0 0 0 0 0 0 0
1498 66112846 55614162 -3129664 -27747896 -1846123 18554202 3271730 -14027055 -4007295 11240494 4388397
2997 131506159 110875321 -5756628 -54927470 -3816413 36673409 6542104 -27719237 -7962487 22212368 8701666
在手算结果基础上>>15(缩小32768倍):
0 0 0 0 0 0 0 0 0 0 0 0
0.045715332 2017.603943 1697.209534 -95.50976563 -846.798584 -56.33920288 566.2293091 99.84527588 -428.0717468 -122.2929382 343.0326538 133.9232483
0.091461182 4013.249481 3383.646271 -175.6783447 -1676.253357 -116.4676819 1119.183624 199.6491699 -845.9239807 -242.9958191 677.8676758 265.553772
>>15后的结果认为下取整的结果与例程中的结果一致。
user4461879:
回复 Susan Yang:
Susan Yang 您好:首先谢谢您对本帖的持续关注。下面是我测试的新情况:如果认为矩阵相乘的结果会>>15是正确的话,我在自己的程序中测试矩阵相乘时会发现如果定义的矩阵行或者列不是2的倍数时,计算的结果会不对,例如我之前一直测试不对(调用LEA功能时不对,使用__MSP430_HAS_MPY32__和直接计算时正确)的inputA[2][3]、inputB[3][2]。而当我重新定义为nputA[2][4],inputB[4][2]时计算的结果会和手动计算的一致(虽然需要>>15并且下取整),不知道这个是为什么?如果这个也是一个规则的话,在实际应用中如果碰到奇数行或者列如何处理?