2025年近期C6000 DSP开发小结

近期C6000 DSP开发小结复数乘法指令 TI 的编译器提供的一些内联函数中可以直接调用复数乘法的汇编指令 CMPYSP 只有 C66x DSP 支持 完成复数乘法运算 src1 和 src2 是连续的两个 32 位寄存器组成的 register pair dst 是由四个连续的 32 位寄存器组成的 register quadruplets

大家好,我是讯享网,很高兴认识大家。

复数乘法指令

  TI的编译器提供的一些内联函数中可以直接调用复数乘法的汇编指令(CMPYSP,只有C66x DSP支持),完成复数乘法运算。
在这里插入图片描述
讯享网

  src1和src2是连续的两个32位寄存器组成的register pair,dst是由四个连续的32位寄存器组成的register quadruplets。这里只是做了乘法运算。
在这里插入图片描述

  然后用DADDSP指令可以对上面的结果中的实数部分和虚数部分分别求和,即可实现复数乘法。

( a + b i ) ( c + d i ) = a c − b d + ( a d + b c ) i \left( {a + b{\rm{i} } } \right)\left( {c + d{\rm{i} } } \right) = ac - bd + \left( {ad + bc} \right){\rm{i} } (a+bi)(c+di)=acbd+(ad+bc)i

  另外编译器也提供了一种快速实现复共轭乘法的方式,即 p × q ∗ p\times q^* p×q。乘数中需要求复共轭的数 q q q放在src1寄存器对中作为 a + b i a+b\rm{i} a+bi,另一个乘数 p p p放在src2寄存器对中,依次完成CMPYSP和DSUBSP即可得到 p × q ∗ p\times q^* p×q的结果。
在这里插入图片描述

( a − b i ) ( c + d i ) = a c + b d + ( a d − b c ) i \left( {a - b{\rm{i} } } \right)\left( {c + d{\rm{i} } } \right) = ac + bd + \left( {ad - bc} \right){\rm{i} } (abi)(c+di)=ac+bd+(adbc)i

Cache映射方式

  Cache的映射方式包括直接映射,全相联映射和组相联映射,后者是前两者相结合的产物。C6678的L1P Cache采用的是直接映射,存储器中的code在L1P Cache中只有唯一确定的位置。
  C6678的L1D Cache采用的是两路组相联映射(two-way set associative cache),一个set里面有两个line frame,存储器中的数据映射到固定的set,但可以是任意的line frame。
在这里插入图片描述

  C6678的cache line frame是64字节,所以地址中的Offset字段固定为6bits。一个set是128字节,如果L1D的Cache大小为4kB,那么L1D Cache可以分为32个set,所以Set字段为5bits,剩下的就是Tag字段21bits。
在这里插入图片描述

  当L1D Cache设置为32kB时,set的数量也就变为了原来的8倍,因此Set字段需要8bits,相应的Tag字段减少为18bits。

TI Data Type

  调试过程中经常需要预先往存储器中加载数据,可以通过Memory Browser窗口里的Load Memory实现。
在这里插入图片描述

  需要加载的数据预先存在在一个“xxx.dat”文件里,按照TI Data的格式进行存放,在加载的时候CCS就会根据文件头的信息把数据加载到指定的位置。
在这里插入图片描述

  帧头的数都是十六进制表示的!可以在CCS的Help->Help Comtents里搜索“data format”找到相关的介绍。
在这里插入图片描述

  数据格式“9”表示一种比较新的数据格式说明方式,具体数据格式由最后一个数决定。数据个数就是数据的行数,因为一行一个数据。具体数据格式如下表:

具体数据格式(十六进制) 含义
0 64bit Hex TI-style
1 64bit Hex C-style (带0x前缀)
2 64bit Floating Point
3 Exponential Float (指数表示的浮点数)
4 32bit Hex TI-style
5 32bit Hex C-style
6 32bit Signed Int
7 32bit Unsigned Int
8 32bit Binary
9 32bit Floating Point
A 32bit Exponential Float
B 16bit Hex TI-style
C 16bit Hex C-style
D 16bit Signed Int
E 16bit Unsigned Int
F 16bit Binary
10 8bit Hex TI-style
11 8bit Hex C-style
12 8bit Signed Int
13 8bit Unsigned Int
14 8bit Binary
15 Character
16 Packed Char

QDMA的使用

  有时候需要手动启动DMA并且随时需要对PaRAM进行修改,而不是等待外部事件触发,那么就可以用QDMA来实现。QDMA能够在写完PaRAM时就启动DMA传输。实际应用过程中可以有这几点需要考虑:

  1. 硬件初始化
  2. 中断服务函数
  3. 启动传输

  下面是C6678上用于实现矩阵转置的一个类。三个成员函数分别对应我提到的三点要考虑的地方。

#ifndef CTSPSMANAGER_H #define CTSPSMANAGER_H #include <csl_edma3.h> #define TPSP_PARAM_NUM (10) #define TSPS_QDMA_CHANNEL (0) #define TSPS_TCC_CODE (8) #define TSPS_SYSEVT_EDMA3R0 (38) #define TSPS_REGION CSL_EDMA3_REGION_0 class CTspsManager { 
    private: CSL_Edma3Handle m_hEdma; CSL_Edma3Obj m_Obj; Bool m_bInitDone; int m_nCicId; public: CTspsManager(); ~CTspsManager(); int HwInit(int coreId); void startTranspose( void *restrict pSrc, void *restrict pDst, int nSrcWidth, int nSrcHeight, size_t nUnit); void ClearInterruptFlag(); }; #endif 

讯享网

  硬件初始化过程中,因为要配置中断,所以不同的核需要设置对应的片上中断控制器(CIC)。QDMA通道绑定队列与PaRAM,使能通道。同时也需要使能PaRAM中TCC code对应的DMA通道,和这个DMA通道的中断使能。清中断的时候需要清系统中断和EMDA的中断挂号寄存器。

讯享网int CTspsManager::HwInit(int coreId) { 
    CSL_Status status; CSL_Edma3HwSetup hwSetup; UInt nChannel; CSL_Edma3HwDmaChannelSetup hwDmaSetup[] = CSL_EDMA3_DMACHANNELSETUP_DEFAULT; CSL_Edma3HwQdmaChannelSetup hwQdmaSetup[] = CSL_EDMA3_QDMACHANNELSETUP_DEFAULT; if(coreId < 0 || coreId > 7) return -1; if(m_bInitDone) return 0; m_hEdma = CSL_edma3Open(&m_Obj, CSL_EDMA3CC_0, NULL, &status); assert(m_hEdma != NULL); //--------------------- Hardware Setup -------------------------- // DMA setup hwDmaSetup[TSPS_TCC_CODE].paramNum = TPSP_PARAM_NUM; hwDmaSetup[TSPS_TCC_CODE].que = CSL_EDMA3_QUE_0; hwSetup.dmaChaSetup = hwDmaSetup; // end of DMA setup // QDMA setup hwQdmaSetup[TSPS_QDMA_CHANNEL].paramNum = TPSP_PARAM_NUM; hwQdmaSetup[TSPS_QDMA_CHANNEL].que = CSL_EDMA3_QUE_0; hwQdmaSetup[TSPS_QDMA_CHANNEL].triggerWord = CSL_EDMA3_TRIGWORD_DEFAULT; hwSetup.qdmaChaSetup = hwQdmaSetup; // end of QDMA setup CSL_edma3HwSetup(m_hEdma, &hwSetup); //--------------------- end of Hardware Setup -------------------------- //--------------------- Queue Priority Setup -------------------------- CSL_edma3SetEventQueuePriority(m_hEdma, CSL_EDMA3_QUE_0, CSL_EDMA3_QUE_PRI_0); CSL_edma3SetEventQueuePriority(m_hEdma, CSL_EDMA3_QUE_1, CSL_EDMA3_QUE_PRI_1); CSL_edma3SetEventQueuePriority(m_hEdma, CSL_EDMA3_QUE_2, CSL_EDMA3_QUE_PRI_2); CSL_edma3SetEventQueuePriority(m_hEdma, CSL_EDMA3_QUE_3, CSL_EDMA3_QUE_PRI_3); //--------------------- end of Queue Priority Setup -------------------------- CSL_edma3QdmaRegionAccessDisable(m_hEdma, TSPS_REGION, 0xF); CSL_edma3QdmaRegionAccessEnable(m_hEdma, TSPS_REGION, 1 << TSPS_QDMA_CHANNEL); CSL_edma3DmaRegionAccessDisable(m_hEdma, TSPS_REGION, 0xFFFFFFFF, 0xFFFFFFFF); CSL_edma3DmaRegionAccessEnable(m_hEdma, TSPS_REGION, 1 << TSPS_TCC_CODE, 0); CSL_edma3InterruptLoEnable(m_hEdma, TSPS_REGION, 1 << TSPS_TCC_CODE); //--------------------- end of Region Access Setup -------------------------- CSL_edma3QDMAChannelEnable(m_hEdma, TSPS_REGION, TSPS_QDMA_CHANNEL); CSL_edma3ClearDMAChannelEvent(m_hEdma, TSPS_REGION, TSPS_TCC_CODE); CSL_edma3DMAChannelEnable(m_hEdma, TSPS_REGION, TSPS_TCC_CODE); // CIC0 is used to connect EMDA finish interrupt to CPU m_nCicId = (coreId < 4) ? 0 : 1; nChannel = coreId % 4 * 11 + 33; // attach to host interrupt ID 22 CpIntc_clearSysInt(m_nCicId, TSPS_SYSEVT_EDMA3R0); CpIntc_enableSysInt(m_nCicId, TSPS_SYSEVT_EDMA3R0); CpIntc_mapSysIntToHostInt(m_nCicId, TSPS_SYSEVT_EDMA3R0, nChannel); CpIntc_enableHostInt(m_nCicId, nChannel); CpIntc_enableAllHostInts(m_nCicId); return 0; } void CTspsManager::startTranspose( void *restrict pSrc, void *restrict pDst, int nSrcWidth, int nSrcHeight, size_t nUnit) { 
    CSL_Status status; CSL_Edma3ParamSetup paramSetup; CSL_Edma3ParamHandle hParam; Cache_wb(pSrc, nSrcWidth * nSrcHeight * nUnit, Cache_Type_ALLD, TRUE); hParam = CSL_edma3GetParamHandle(m_hEdma, TPSP_PARAM_NUM, &status); paramSetup.option = CSL_EDMA3_OPT_MAKE(CSL_EDMA3_ITCCH_EN, \ CSL_EDMA3_TCCH_DIS, \ CSL_EDMA3_ITCINT_DIS, \ CSL_EDMA3_TCINT_EN, \ TSPS_TCC_CODE, \ CSL_EDMA3_TCC_NORMAL,\ CSL_EDMA3_FIFOWIDTH_NONE, \ CSL_EDMA3_STATIC_DIS, \ CSL_EDMA3_SYNC_AB, \ CSL_EDMA3_ADDRMODE_INCR, \ CSL_EDMA3_ADDRMODE_INCR); paramSetup.srcAddr = (uint32_t)pSrc; paramSetup.aCntbCnt = CSL_EDMA3_CNT_MAKE(nUnit, nSrcHeight); // (acnt, bcnt) paramSetup.dstAddr = (uint32_t)pDst; paramSetup.srcDstBidx = CSL_EDMA3_BIDX_MAKE(nSrcWidth * nUnit, nUnit); // (src, dst) paramSetup.linkBcntrld = CSL_EDMA3_LINKBCNTRLD_MAK (CSL_EDMA3_LINK_NULL, 0); paramSetup.srcDstCidx = CSL_EDMA3_CIDX_MAKE(nUnit, nSrcHeight * nUnit); // (src, dst) paramSetup.cCnt = nSrcWidth; CSL_edma3ParamSetup(hParam, &paramSetup); } void CTspsManager::ClearInterruptFlag() { 
    CSL_edma3ClearLoPendingInterrupts(m_hEdma, TSPS_REGION, 1 << TSPS_TCC_CODE); CpIntc_clearSysInt(m_nCicId, TSPS_SYSEVT_EDMA3R0); } 

参考资料

  • SPRU187U-TMS320C6000 Optimizing Compiler v7.4
  • SPRUGH7-TMS320C66x DSP CPU and Instruction Set Reference Guide
小讯
上一篇 2025-03-21 15:22
下一篇 2025-03-05 17:10

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/22627.html