By Bill Chou, MathWorks
Engineers have translated low-level languages like C into machine code for decades using compilers. But is it possible to translate a high-level language like MATLAB® to C using coders? Most engineers would agree that it’s possible in theory—but does it work in practice? Is the generated code readable or spaghetti? Efficient or bloated? Fast or slow? And does it support industrial workflows, or just R&D?
This article addresses these concerns head-on. It provides tips and best practices for working with MATLAB Coder™, as well as industry examples of successful applications of generated code by companies such as Delphi, Baker Hughes, iSonea, and dorsaVi.
The code samples in this article are available for download.
The simple MATLAB function below multiplies two inputs.
Given scalar inputs, MATLAB Coder generates the following C code:
As you can see, the generated code maps clearly back to the MATLAB code.
The same piece of MATLAB code, when given two matrix inputs, generates three nested
for-loops in C:
The simple function shown above can be implemented in a single step. But for more substantial projects, we recommend a structured approach using a three-step iterative workflow (Figure 1):
The MATLAB Coder app guides you through this iterative process while enabling you to stay within the MATLAB environment. It analyzes your MATLAB code to propose data types and sizes for your inputs. It tests whether your MATLAB code is ready for code generation by generating a MEX function, then executes the MEX function to check for run-time errors (Figure 2). Equivalent command-line functions provide the same functionality so you can generate code as part of a script or function.
The video below illustrates these steps with an example of generating a Kalman filter to predict the trajectory of a bouncing ball. You’ll see that the three-step iterative process enables us to generate code that closely matches the original MATLAB results and satisfies its tracking requirements.
As you prepare your MATLAB algorithm for code generation, you need to take account of implementation constraints resulting from the differences between MATLAB and C code. These include:
static), dynamically (using
malloc), or on the stack (using local variables).
for-loops to express the same algorithms.
Let’s take a closer look at polymorphism. Polymorphism can give a single line of MATLAB code different meanings depending on your inputs. For example, the function shown in Figure 3 could mean scalar multiplication, dot product, or matrix multiplication. In addition, your inputs could be of different data types (logical, integer, floating-point, fixed-point), and they could be real or complex numbers.
MATLAB is a powerful algorithm development environment precisely because you don’t need to worry about implementation details as you create algorithms. However, for the equivalent C code, you have to specify what operations mean. For example, the line of MATLAB code shown above could be translated into this single line of C code that returns B*C:
Or, it could be translated into 11 lines of C code with 3
for-loops that multiply two matrices:
The video below uses a Newton-Raphson algorithm to illustrate the concept of taking implementation constraints into account. You’ll see that code generated using the three-step iterative workflow exactly matches the original MATLAB results.
Once you have generated readable and portable C/C++ code from MATLAB algorithms using MATLAB Coder, you have several options for using it. For example, you can:
dorsaVi generated C++ code from motion analysis algorithms and compiled it into a DLL, which was then integrated into their C# application running on a PC that analyzes the athlete’s movements to diagnose injury.
for-loops whose iterations are independent of each other can be run in parallel simply by replacing
parfor. MATLAB Coder uses the Open Multiprocessing (OpenMP) application interface to support shared-memory, multicore code generation from
parfor loops. OpenMP is supported by many C compilers (for example, Microsoft® Visual Studio® Professional).
You can use MATLAB Coder with Embedded Coder® to further optimize code efficiency and customize the generated code. Embedded Coder provides optimizations for fine-grained control of the generated code’s functions, files, and data. For example, you can use storage classes to control the declaration and definition of a global variable in the generated code, and use code generation templates to customize banners and comments in the generated code. Embedded Coder also improves code efficiency by using code replacement libraries, which replace certain operators and functions with implementations optimized for popular processors like ARM Cortex®-A and ARM Cortex-M.
As you develop your MATLAB algorithm, you can create unit tests to verify that the algorithm produces the results you expect. Tests written using the MATLAB unit testing framework can be reused to verify that the generated code behaves the same way as your MATLAB algorithm. The videos below show how you can reuse the unit tests in Embedded Coder in combination with software-in-the-loop (SIL) and processor-in-the-loop (PIL) tests on the generated standalone code or library (Figure 4).
MATLAB Coder enables an automated workflow for translating MATLAB algorithms into C code. With this workflow you spend less time writing and debugging low-level C code and more time developing, testing, and tuning designs. By maintaining one golden reference in MATLAB, including the algorithm and test benches, you can propagate algorithmic changes to your C code more quickly. Automated tools like the MATLAB unit testing framework and the Embedded Coder SIL and PIL testing framework let you test both the MATLAB code and the C code thoroughly and systematically. Whether you are implementing designs running on traditional PCs, web servers, mobile devices, or embedded processors, MATLAB Coder will help you get from MATLAB to C code faster and with fewer manual translation errors.
Article featured in MathWorks News & Notes
Published 2016 - 92987v00