Design Article

Combining C and assembly in DSP applications

Eran Balaish, CEVA

12/10/2007 3:00 AM EST

As DSP processors become more powerful and compiler optimization techniques improve, the once common trend of writing DSP applications solely in assembly has withered away. Today, almost every DSP application is comprised of a combination of both C code and assembly code. In critical functions, where performance is of the essence, DSP engineers continue to use highly optimized assembly code. Less critical functions, however, are now written in C, allowing easier maintenance and better portability. This combination of C and assembly code requires special tools and methodologies in the tool box of every DSP engineer.

It is well known that assembly coding has the advantage of better performance, while C coding is considered much easier and faster to write. To understand why this is so, let's take a closer look at the advantages and disadvantages of assembly coding compared to C coding:

Assembly Coding Pros:

  • Assembly code can take advantage of a processor's unique instructions as well as various specialized hardware resources. On the other hand, C code is generic, and must support various hardware platforms. Thus, it is difficult for C to support platform-specific code.
  • The assembly programmer is usually very familiar with the application and can make assumptions that are unavailable to the compiler.
  • The assembly programmer can use human creativity; the compiler, advanced as it may be, is merely an automatic program.
Assembly Coding Cons:

  • The assembly programmer has to handle time-consuming machine-level issues such as register allocation and instruction scheduling. With C code, these issues are taken care of by the compiler.
  • Assembly coding requires specialized knowledge of the DSP architecture and its instruction set, whereas C coding only requires knowledge of the C language—which is rather common.
  • With assembly code, it is extremely difficult and time consuming to port applications from one platform to another. Porting is relatively easy for C applications.
Figure 1 demonstrates the utilization of dedicated hardware mechanisms for highly optimized assembly code. The C implementation on the left side creates a cyclic buffer p1 using modulo arithmetic. In the highly optimized assembly code on the right, an equivalent buffer is created using the Modulo Mechanism of the CEVA-TeakLite-III DSP Core. The Modulo Mechanism automatically performs the modulo arithmetic whenever there is an update to the buffer pointer (r0 in this case). This arithmetic occurs in the same cycle as the pointer update, so the assembly code is much more efficient than the C code, which would generate separate instructions for the modulo arithmetic.


(Click to enlarge)

Figure 1. The CEVA-TeakLite-III assembly code on the right implements the C code on the left.

Choosing the right mixture of C code and assembly code in DSP applications
The question is where to draw the line between C code and assembly code. The answer lies in the performance analysis provided by the profiler. (For more information about the profiler refer to Compiler optimization for DSP applications and DSP optimization strategies using simulators and profilers.) However, before using the profiler, the DSP engineer needs to define clear objectives for the application. Typically, the objectives are cycle count, code size and data size. Once these are defined, the application should first be written and built entirely in C. Only then should the profiler be used to analyze its performance.

In some rare cases, mostly in control applications, C level coding is sufficient. In most cases, the initial C level version of the application does not comply with one or more of the objectives. This usually means that assembly coding is required to some extent. There are many measures that can be taken in the C level to improve performance before resorting to assembly coding, but these measures are not in the scope of this article. (For tips on C-level optimization, see the DSP programmer's guide.) Assuming all C level measures have been exhausted and assembly coding has been initiated, it is highly recommended to save the original C code implementation. This eases debugging and also enables the return to the C implementation once the conditions are right (e.g., when moving to a more powerful platform).

The assembly portion of the code should be kept to a minimum. For this purpose, the performance results reported by the profiler should be analyzed and the critical functions of the application should be identified. Critical functions are those that consume the most execution time and therefore ought to be rewritten in assembly to meet performance objectives. Once the two or three most critical functions have been rewritten, it is time to take another performance measurement. If the application still does not meet its objectives, additional critical functions should be defined and rewritten in assembly. This process iterates until the performance objectives are met.





Please sign in to post comment

Navigate to related information

Datasheets.com Parts Search

185 million searchable parts
(please enter a part number or hit search to begin)