DSP code optimization instructions in CCS[Copy link]
The purpose of restrict is to restrict a pointer's access to a block of memory. To put it more concretely, if a memory area is accessed through a restricted pointer, it cannot be accessed through another restricted pointer. The purpose of introducing restrict is to ensure that there are no other references to the same block of memory, so that the compiler can better optimize instructions and generate more efficient assembly code. Put #pragma MUST_ITERATE( , , ) before the loop body to tell the development board the number of loops and improve software pipeline. MUST_ITERATE tells the compiler the properties of the loop, but these properties must be true, otherwise the program may run incorrectly. This directive is mainly used to optimize C function loops. Generally, as long as there is a loop, it is best to bring this directive #pragma MUST_ITERATE(min, max, multiple); the multiple parameter must be present, and the number of loop executions must be an integer multiple of multiple. This information is very important for the compiler to use software pipelining technology Then min and max are the maximum and minimum number of loops const short *restrict x; //Assumption: Vectors x and h are double-word aligned _nassert((int)x % 8 == 0); This is an assertion statement. Judge the condition. If it is 1, it passes. If it is 0, an exception is thrown. By comparing the running time of printf() and LOG_printf(), it is found that when C6211 runs at 150MHz, printf() takes 4000 cycles, about 26.7μs, while LOG_printf() only takes 36 cycles, about 0.24μs. printf() takes more than 100 times more time than LOG_printf(), so LOG_printf() is very helpful for displaying some running status in real time. And for developers familiar with C language, the calling format of LOG_printf() is almost exactly the same as printf(). Like the more familiar const, volatile is a type specifier. It is designed to modify variables that are accessed and modified by different threads. Without volatile, the following results will basically occur: either you cannot write multi-threaded programs, or the compiler loses a lot of optimization opportunities. The role of volatile: As an instruction keyword, it ensures that this instruction will not be omitted due to compiler optimization, and requires direct value reading each time. Simply put, it prevents the compiler from optimizing the code. For example, the following program: XBYTE[2]=0x55; [size= 4] XBYTE[2]=0x56; XBYTE[2]=0x57; [backcolor=white ] XBYTE[2]=0x58; If the above four statements represent different operations on the external hardware, four different actions will be generated. Then the compiler cannot optimize the above four statements as it would a pure program. It only considers XBYTE[2]=0x58 and ignores the previous Three statements (that is, only one machine code is generated), the compiler will compile them one by one and generate the corresponding machine code (four). #000000] Generally speaking, volatile is used in the following places: [ /backcolor] 1. The variables modified in the interrupt service program for detection by other programs need to be added with volatile; [ /color] 2. In a multitasking environment, flags shared between tasks should be added with volatile; 3. Memory-mapped hardware Registers are usually also marked volatile, because each read or write to them may have a different meaning; In addition, the above situations often require the consideration of data integrity (several related flags are interrupted and rewritten halfway through reading), which can be achieved by turning off interrupts in 1. Now, in 2, you can disable task scheduling, and in 3, you can only rely on good hardware design.