In a typical Impulse C application, two or more parallel processes are described using C, and these processes communicate with each other through buffered data channels called "streams." This buffering of data makes it possible to write parallel applications at a higher level of abstraction, without the clock-cycle by clock-cycle synchronization that would otherwise be required. Impulse C processes (whether running in hardware or as software processes on an embedded microprocessor) may be independently synchronized such that the arrival of a data packet on an input stream triggers a computation, which then in turn generates an output, either on another stream or by writing to shared memory. Within such a process, compiler pragmas can be used to specify that specific inner code loops are to be unrolled and/or pipelined, further increasing parallelism and resulting in extremely high data rates for many types of algorithms.
The FIR filter in Listing 1 summarizes how one such process operates on a stream of 32-bit values. This process may be connected to other upstream/downstream processes to create a larger, parallel system of communicating pipelined processes, as in Listing 2.
The Impulse C library consists of minimal extensions to C (including the co_stream_open, co_stream_read, co_stream_write, and other functions) that let multiple, parallel processes be described, interconnected, and synchronized. The Impulse C compiler translates and optimizes these processes into appropriate lower level representations, including Register-Transfer-Logic (RTL) descriptions that can be synthesized directly to hardware such as FPGAs, and Standard C that can be compiled onto supported microprocessors through the use of widely available C cross compilers. The compiler also automates the creation of the necessary hardware/software interfaces.
D.P.