I am going to write some image processing programs for Texas Instruments DaVinci platform. There are tools appropriate for programming in the C language, but I wonder if it is really possible to take full advantage of the DSP processor without resorting to an assembly language. Do you know about any comparisons of speed between programs written in C and in assembler on this DSP platform?
The C-Compiler (as far as I tested) does not take full advantage of the architecture.
But you can get away with it, because the DSP might be fast enough for the operations you need to do.
So it comes down to testing and profiling your code to see the parts which must be speed up to get the system to work.
I've used some other TI DSPs and C was usually fine. The usual approach is to start by writing everything in C and then profile the code to see if anything needs to be hand-optimised.
You can often do the optimisation in C too, by adjusting the C code until you get the assembly output you want. It's important to know how the DSP works and what ways of working are faster or slower.
Depends on the C compiler and your definition of "fast enough". Standard C compilers often struggle to make efficient use of special DSP hardware, such as:
- Multiple memory banks that can be accessed in parallel
- Fixed point data types
- Circular buffers
Usually C is a good place to start. You can get the overall framework and algorithms shaken out quickly, and write most of the plumbing that moves the data around between the real math. Once that's in place and you're happy that your data structures are correct, you can look at in a profiler and figure out which routines need to be squeezed by hand.
I would stick to C until I know there is a hotspot that could benefit from assembly coding. This is the "profiling" method I use. You could be surprised that there are ways to speed up the code that are not hotspots, but rather intermediate function calls that could be removed.
The TI compiler for the C64x/C64x+ DSP on the OMAP3 includes support for what TI calls "intrinsic" function calls. They're not really function calls, they are just a way to tell the compiler what assembly opcode to use for an operation that might not be directly expressable in C. It is especially useful for leveraging the SIMD opcodes in the C64x/C64x+ DSP from C.
An example might be:
A = _add2(B, C);
This SIMD instruction adds the low/high 16 bits of B and C together and store the results in the low/high 16 bits of A. You can't express this in regular C, but you can do it with the intrinsic C opcodes.
I have used intrinsic C to get very close to what you could do with full-blown assembly language (within 5-10%). It is especially useful for video functions like filtering and motion compensation (_dotpsu4!).
I usually compile with the -al switch and look at the pipeline to try and identify what functional units are overloaded and then look at my intrinsics to see if I can rebalance the loop (if I'm using too many S units, I might see if I could change the opcode to use an M unit).
Also, it's helpful to remember that the C64x DSP has 64 registers, so load up the local variables and never assign the output of an instruction back into the same variable -- it'll negatively affect the compiler's ability to pipeline properly.