Design Article
Programming DSPs in High-Level Languages
Marco Roodzant
8/14/2000 12:00 AM EDT
With IP re-use now heralded as the only answer to shortening the time-to-market for new software developments, one thing is certain. In the future, nearly all DSP software will have to be written in a high-level language to make it maintainable, re-usable, and portable. Yet the high-level programming languages being adopted by the DSP community are virtually all based on C, a language that in standard form is not able to handle the fixed-point arithmetic, divided memory spaces, and circular buffers that are typical of modern DSP architectures. In addition, the use of any such high-level language tends to decrease the efficiency of the generated code. Yet code efficiency is a critical requirement for many DSP programs, particularly those designed for real-time embedded systems.
So how do programmers utilize DSP features that the C language was never designed to handle, yet still achieve portability and highly efficient compact code? The answer is to use one of a number of variants of the C language, coupled with advanced simulation tools and compilers (See Why Choose C for DSPs?). The relative efficiency of these C-language variants depends on how easily they allow programmers to reach the unique features of DSPs at the C language level.
Because the definitions of new classes, and the way operators operate on them, are themselves written in C++, this approach has the advantage that your entire DSP program remains within the language. Using C++ with DSP classes therefore goes a long way to meeting the requirements of maintainability and re-usability. Programs written in this way can also be simulated and tested using standard software development tools and compiled using standard compilers.
However, the same reason that gives this approach the advantages of maintainability and re-usability is also the reason why it is difficult to get efficient DSP code from it. Operations on the DSP-oriented objects, which on the target processor typically execute in a single instruction cycle, appear in the C++ program as relatively long sections of code. C++ merely emulates these operations according to the newly defined DSP class rules, with the emulation actually being written in C++.
As a result, it is extremely difficult for compilers to recognize those parts of the C++ code that are DSP class operations and to map them onto appropriate target DSP instructions. Most compilers will simply treat the C++ emulation of a DSP class operation as standard C++, and generate much less efficient code from it. This compounds a problem that already exists with C++ compilers, in that because of the added complexity of the C++ language, these compilers already tend to generate less efficient code than standard C compilers.
Efficient mapping to target system instructions can only be done if the C++ code somehow contains hints to the compiler that certain sections of code relate to specific DSP instructions. Unfortunately, the addition of these hints not only moves the program outside the limits of standard C++, it also means that the C++ code needs to contain target-specific information, both of which have serious implications for portability. Another disadvantage of using C++, particularly if you are only familiar with programming your DSPs in assembler, is that C++ is a considerably more difficult language to learn than C.
Ultimately, compiler technology may well develop to the point where C++ compilers have sufficient in-built intelligence to automatically recognize DSP class extensions and map them appropriately, but at present that situation is some way off. Because class-specific operations are themselves coded in C++, for example, such a compiler would have to recognize sections of standard C++ code and map them onto the target in a non-standard way. Nevertheless, when such compilers do arrive, C++ with DSP classes will be one of the cleanest ways to program DSPs.

Figure 1: One way to tune a high-level language to the needs of DSPs is to create a custom compiler using a compiler generator that accommodates DSP constructs. The CoSy Compiler Development Platform from ACE Associated Compiler Experts, with its ability to implement sophisticated and intelligent optimization strategies and its internal support of DSP features, is likely to be one of the main platforms on which these compilers are developed.
Because intrinsics are necessarily target architecture dependent, this C with intrinsics approach is the one most commonly found in compilers that are sold by silicon vendors to support their own proprietary DSP chip families. Each member of a particular DSP family normally has a similar architecture and instruction set, which means that it is relatively easy for the manufacturer to supply a compiler with a comprehensive library of intrinsics that will result in reasonably efficient code generation.
For chip vendors, portability is not an issue. For customers, however, with a great deal of IP bound up in their application programs, portability is a crucial issue if they want to maintain IP re-use throughout a migration path to different and more advanced DSP architectures. The C with intrinsics approach doesn't give them that portability.
Once they have the basic functionality right, they then manually translate their C++ programs into C with intrinsics, often translating critical parts directly into assembler. This allows them to run the programs on a simulator to get closer to target system performance or even to compile the whole program into machine code so that it can be run in real-time on a hardware emulator.
Although their programs have the appearance of being portable at the C++ level, in practice everything below this is non-portable. As a result, if a decision is made to change to a different DSP architecture, a great deal of work still needs to be done to prove the software on the new architectural platform. Even if portability is not a primary concern, having to maintain application programs that exist both in C++ and C with intrinsics, especially when manual translation between the two is required, is not conducive to good quality control.
For example, in much the same way that C includes predefined routes for type conversion from a 'short' to an 'int' to a 'long', DSP-C provides similar type conversion routes from a 'short fixed' to a 'fixed' to a 'long fixed'. In other words, the new type definitions in DSP-C are supported in the same logical way that programmers have come to expect from a language like C. While the C with intrinsics approach tackles DSP issues from the target system viewpoint, resulting in a lack of portability, DSP-C tackles these issues from within the language itself. As a result DSP-C programs remain highly portable.
The compiler issue is just as important, and it is what distinguishes DSP-C from the C++ with classes approach. As mentioned earlier, compiler technology is not sufficiently advanced at the moment to allow C++ compilers to handle the necessary DSP classes and type conversions in a way that results in highly efficient target code. C compilers on the other hand are already very efficient, and with DSP-C extensions built into the language, this same efficiency can be carried over into the DSP domain—a fact that ACE has demonstrated with DSP-C compilers generated using the CoSy-DSP version of its CoSy Compiler Development Platform. With the ability to perform global optimizations that focus specifically on DSP operations, these compilers produce highly stable DSP code that is easier to debug, resulting in short time-to-market development cycles.
With many DSP programmers only now moving over from assembly language to high-level language programming, it is important that all the necessary tools are in place to make the process as easy and effective as possible. In addition to DSP-C and its associated compilers, ACE has also developed a DSP simulator that allows DSP-C programs to be emulated with bit-true accuracy on standard workstations. This means that the effectiveness of different DSP algorithms and application programs can be evaluated early on in the design cycle, even before target system silicon or an instruction set simulator is available to run them.
While DSP-C has yet to become an official standard, it fulfills such an urgent need that it is already in use by a large number of DSP companies worldwide. Together with the availability of compilers for many of the latest DSPs, it is already making a significant impact on IP re-use and shortened time-to-market within the DSP industry. And with DSP-C now providing direct support for DSP-specific operations and architectures, it is logical to predict that the principles behind DSP-C will ultimately be transferable to the C++ domain, in much the same way that the C language itself developed into C++.



