Diving into graphical models

Proponents of text based languages often point to the ease of developing / debugging their code; “I put a breakpoint on a line(1) and…” while at first blush it may seem easier to debug textual models today I am going to walk you through(2) how to debug graphical models.

What is debugging?

First let us come to an agreement on what it means to “debug” a model / code. A model has a “bug” when the model either

  • Fails to run:
    or
  • Runs producing incorrect results:
    it is not
  • Excessive memory use, slow execution(3)

Failure to run is easy to detect, incorrect results may be more difficult to detect if unit tests for regression do not exist.

Sometimes…

You get lucky and a simple differencing of your model against recent versions can determine where the error crept in.(4) To do this, you need to…

  • Review the blocks added to the model
  • Review block parameter changes
  • Review the changes to connections
  • Review changes to data

Breakpoints and probes

In textual debugging there is often enough “printf” statements to make you think you are in Project Gutenberg;(5) graphical models use probes and scopes to accomplish the same objective.

Breakpoints can be inserted into the model in any location; for advanced debugging techniques, conditional breakpoints can be used e.g., break when signal > MyVal

Sometimes when you debug you want to go in reverse(6)

Break it down

Finally, a powerful method available in Simulink is the ability to create test harnesses for subsystems, e.g. once you have isolated the issue to a given subsystem you can create a test harness that will run that section of the model independently, enabling a faster debugging experience

Final thoughts

Once you have gone through your debugging exercise…

  • Check any models that you have created to prevent regression to this bug
  • Note any incorrect block usage for future best practices

Footnotes

  1. Why yes, that is MATLAB code with simple breakpoints; it is the “text” portion of the Simulink / Stateflow / MATLAB triumvirate.
  2. After a month of video posts walking you through Model-Based Design this will be a short walk in the park.
  3. Many of the techniques for debugging a model can be used for these situations; however those are optimization problems, not function problems. The general best practice is to ensure full system compliance with requirements before starting to optimize your system.
  4. As a side bar, the phrase “low hanging fruit” is an interesting phrase. It covers the “things that are easy to get”. However, if you talk to people who climb into trees to pick fruit they will tell you that you grab the low hanging fruit last so you do not climb up the tree with extra weight. Like many things in life if your long term objectives should shape your short term actions.
  5. The Project Gutenberg brings public domain books to electronic format.
  6. Point-Break ==> reverse Break-Point

When every pico-second counts…

Often with embedded software speed(1) matters; however function always(2) matters. One common approach to improve execution speed is to take the training wheels off; that is, to remove boundary checking code.(3) Again, we have an often versus always situation; frequently that is okay but not always. So how do we make it always?

The baseline

Before we start trying to make things faster we need to perform a code profiling step (e.g. execute the code in both the standard and worst case scenarios).(4) Next, determine if you are trying to improve the standard or worst case operation. As you gather the data make sure to log both the performance (execution time) as well as the accuracy.

Training wheels off; Are we stable?

Note: this post is focusing on making sure the code is safe as you make it faster. Speed will be covered in other posts…

The first thing to check is if under normal operating conditions the system is stable (e.g., no overflows, no out of bounds errors, no integrator wind ups). For most systems this will be the case.(5) Next, it is time to check the corners.

There are three types of corner case tests that should be performed:

  1. Held: The system is driven to the corner case and the inputs are held there.
  2. In/Out: The system cycles in and out of a corner case.
  3. Sweep: Assuming there are multiple corners, the system sweeps between the different corners.

Wobbling?

When the system has instabilities the question becomes “Where do I insert controls while minimally impacting the system performance?” The key here is to perform a trace back to the first offending block.

Often(6) the block that causes the issue is not where the issue occurs (e.g., it is upstream of the issue). However, by modifying the upstream block you can have a lower impact on the system behavior.

Final notes

As I pointed out near the start of this blog, the first step is to collect timing data on the system “as-is.” Once the changes have been made and the new data is collected the system as a whole should be evaluated.

  • Is there a significant performance improvement?
  • Have the changes impacted the accuracy of the system?
  • Have the changes made the system harder to test?
  • Have the changes reduced the clarity of the system?

Once you have asked yourself these four questions you can then decide if the modifications should become the new version of the code.

Footnotes

  1. Just like in the movie, you don’t want your “Speed” to end up in a crash.
  2. The difference between often and always is how you prioritize your design. Take care of always first, then often will follow.
  3. Boundary checking code (e.g., looking for data type overflows, out of range pointers, or out of range input data).
  4. Optimization for worst case scenarios may not be the same as the standard operating conditions.
  5. In the subset of cases where the standard operating conditions cause errors, this is generally an indication of a poor design. I would strongly recommend stopping here and refactoring the base design first.
  6. I didn’t realize how often I write the word “often” until I called it out in this blog. But that is often the case, we don’t see things until we look at them.