Automatische Codegenerierung im Model-Based Design soll den Zeit- und Kostenaufwand deutlich reduzierten. Allerdings kann es sein, dass der generierte Code im Vergleich zu handgeschriebener Software langsamer läuft und mehr Speicher braucht. Der Generator muss also die Effizienz optimieren, sprich den Speicherbedarf minimieren und die Ausführungsgeschwindigkeit maximieren. Bei militärischen Systemen und Flugzeugen ist es zudem zwingend nötig, den Code stringent zu verifizieren und konform mit Standards zu halten – das lohnt aber auch bei anderen Projekten.

Auf einen Blick

Drum prüfe: Automatisch generierter Code hat weniger Fehler als sein handgeschriebenes Pendant, dafür läuft er langsamer und braucht mehr Speicher. So weit die Erwartungshaltung. Doch in kritischen Umgebungen gilt es, die Fehlerfreiheit zu verifizieren und die Effizienz zu optimieren. Beides ist mit den passenden Tools von Mathworks möglich.

Um die Effizienz zu messen und den Code zu verifizieren, können Entwickler die Matlab- und Simulink-Produktfamilie von Mathworks verwenden. Dieser Artikel bezieht sich auf Version R2011b, insbesondere den Embedded Coder zur Generierung von Flight-Software. Die vorgestellten Entwicklungs- und Verifikationstätigkeiten sind dabei ausgerichtet auf die Ziele von DO-187B sowie den künftigen DO-178C-Standard. Sie berücksichtigen die in DO-178C geplante Ergänzung „Model-Based Development and Verification“. Für die beschriebenen Verifikations-Tools sind Qualifikations-Kits erhältlich.

Statische Effizienz-Analyse

Die Metriken zur Code-Effizienz lassen sich in zwei Kategorien einteilen: Die erste misst den Speicherbedarf für RAM, ROM und Stackgröße; die zweite Kategorie misst die Zahl der benötigten Ausführungszyklen und damit die Geschwindigkeit.

Bild 1: Der Embedded Coder erzeugt aus dem Modell (rechts oben) ausführbaren Programmcode und begleitet diesen mit einem Bericht über statische Code-Metriken.

Bild 1: Der Embedded Coder erzeugt aus dem Modell (rechts oben) ausführbaren Programmcode und begleitet diesen mit einem Bericht über statische Code-Metriken.Mathworks

Der Embedded Coder erzeugt nach der Codegenerierung einen Bericht (Bild 1), der die Analyse und Optimierung des Speicher-Footprints erleichtert. Dieser Bericht enthält die Zahl der Codezeilen sowie die allgemeine RAM- und Stackgröße, welche mithilfe einer statischen Analyse des Quellcodes sowie verschiedener Charakteristika der Target-Hardware wie etwa Integer-Wortlängen abgeschätzt wurden. Diese Analyse ist statisch, weil sie weder die Cross-Kompilierung noch die Ausführung des Codes berücksichtigt. Die Ingenieure können damit in einem schnellen Durchgang den Speicherbedarf für den Quellcode optimieren, indem sie beispielsweise mit verschiedenen Datentypen experimentieren oder die im Modell vorhandene Logik verändern.

Für den nachfolgenden Analyse- und Optimierungsschritt, bei dem der tatsächliche On-Board-Speicherbedarf und die Ausführungszeit untersucht werden, muss man allerdings auf die gesamte Toolkette für Embedded-Systeme zurückgreifen.

Bild 2: Der Simulink Code Inspector überprüft, ob der erzeugte Code die Anforderungen tatsächlich erfüllt und mit dem Modell übereinstimmt.

Bild 2: Der Simulink Code Inspector überprüft, ob der erzeugte Code die Anforderungen tatsächlich erfüllt und mit dem Modell übereinstimmt.Mathworks

Verifikation

Die statische Verifikation von Quellcode stützt sich vor allem auf Codereviews sowie die Analyse der Rückverfolgbarkeit von Anforderungen. Der neue Simulink Code Inspector (Bild 2) führt automatisch eine strukturelle Analyse des generierten Quellcodes durch und bewertet, wie gut dieser mit dem Low-Level-Anforderungsmodell übereinstimmt. Bei dieser Inspektion überprüft das Werkzeug, ob jede Codezeile einem Element oder Block im Modell entspricht. Ebenso überprüft es alle im Modell vorhandenen Elemente auf ihre strukturelle Äquivalenz zu Operationen, Operatoren und Daten im generierten Code. Im Anschluss daran entsteht ein detaillierter Rückverfolgbarkeitsbericht vom Code zum Modell sowie vom Modell zum Code.

Zur Verifikation gehört außerdem, sicherzustellen, dass der Code einschlägige Industriestandards erfüllt, etwa MISRA AC AGC („Guidelines for the application of MISRA-C:2004 in the context of automatic code generation“). Seit Release R2011a enthält der Embedded Coder eine optionale Vorgabe, die den Generator so einstellt, dass er MISRA-C-konformen Code ausgibt. Dieser Code lässt sich im Anschluss mit MISRA-C-Analysetools überprüfen. So analysieren beispielsweise die Polyspace-Produkte den Code auf Übereinstimmung mit MISRA AC AGC und MISRA-C:2004.

Polyspace kann außerdem ermitteln, ob im Code Laufzeitfehler wie Divisionen durch Null und Zugriffe außerhalb von Array-Grenzen vorhanden sind. Der Simulink Code Inspector kann zusammen mit Polyspace zur Bearbeitung sämtlicher in DO-178B, Tabelle A5 niedergelegten Verifikationsziele für die Analyse von Quellcode dienen.

Bild 3: Simulink verifiziert den ausführbaren Objektcode im Rahmen eines PIL-Tests (Processor-in-the-Loop) direkt auf dem Zielsystem oder auf einem Befehlssatzsimulator.

Bild 3: Simulink verifiziert den ausführbaren Objektcode im Rahmen eines PIL-Tests (Processor-in-the-Loop) direkt auf dem Zielsystem oder auf einem Befehlssatzsimulator.Mathworks

Der ausführbare Objektcode

Simulink unterstützt die Verifikation von ausführbarem Objektcode durch Profilanalysen per Software-in-the-Loop-Tests (SIL) und Processor-in-the-Loop-Tests (PIL). Für SIL-Tests kompiliert man den generierten Code und führt ihn auf dem Hostrechner aus, was eine rasche Bewertung erlaubt. Beim PIL-Testen wird der generierte Code in ausführbaren Objektcode (Executable Object Code, EOC) cross-kompiliert und auf dem tatsächlichen Flight-Prozessor oder Befehlssatzsimulator ausgeführt, wobei Simulink wiederum als Test-Harness-in-the-Loop fungiert (Bild 3).

Der Embedded Coder unterstützt durch konfigurierbare APIs und Referenz-Implementierungen PIL-Tests für die Bareboard- oder RTOS-Ausführung auf beliebigen eingebetteten Prozessoren. Eine Beispiel-Implementierungen auf der Website von Mathworks demonstriert dies mit der Multi-IDE und dem Integrity-RTOS von Green Hills auf einem Freescale MPC8620-Prozessor.

Bild 4: Matlab kann ein Profiling der Ausführungszyklen erstellen und damit Engpässe im realen Code aufspüren.

Bild 4: Matlab kann ein Profiling der Ausführungszyklen erstellen und damit Engpässe im realen Code aufspüren.Mathworks

Während des PIL-Tests erzeugt Simulink einen Bericht zum Ausführungsprofil des Codes, mit dem sich Engpässe analysieren lassen (Bild 4). Für einen optimierten Entwurf kann der Entwickler beispielsweise Codeersetzungsmethoden nutzen, etwa SIMD-Ersetzung (Single Instruction, Multiple Data) und IPP-Optimierungen (Intel Integrated Performance Primitives) für generierten ANSI/ISO Standard-C-Code. Matlab kann die Daten des Ausführungsprofils grafisch darstellen und ermöglicht so eine weitergehende Analyse. DO-178 und die zugehörigen Standards verlangen ausdrücklich, dass die komplexe Flight-Software auf der komplexen Flight-Hardware verifiziert wird, wodurch PIL-Tests einen kritischen Verifikationsschritt für High-Integrity-Systeme darstellen.

Dynamische Code-Verifikation

Beim Model-Based Design können dieselben Testfälle, die bereits bei der anforderungsbasierten Simulation eingesetzt wurden, bei den SIL- und PIL-Tests wiederverwendet werden. Die Ingenieure können also die schon in den Modellsimulationen benutzten Eingabedaten erneut einsetzen, dann die Ergebnisse der SIL- und PIL-Tests mit denen der Modellsimulationen vergleichen und mit dem Simulink Simulation Data Inspector feststellen, ob sie numerisch äquivalent sind (Bild 5).

Bild 5: Mit dem Simulation Data Inspector kann der Anwender die Ergebnisse von Simulations- und PIL-Tests vergleichen.

Bild 5: Mit dem Simulation Data Inspector kann der Anwender die Ergebnisse von Simulations- und PIL-Tests vergleichen.Mathworks

Do-178 verlangt außerdem eine Analyse der strukturellen Abdeckung der Software. Dazu gehört die Modified Condition/Decision Coverage (MC/DC), die überprüft, ob während der Tests sämtliche Pfade im Code durchgespielt werden. Simulink Verification and Validation stellt das entsprechende Konzept auf der Modellebene bereit: Die Modellabdeckung überprüft, ob das Modell vollständig ausgeführt wurde. Gemeinsam eingesetzt spüren die Modell- und Codeabdeckung potenzielle Fehler im Entwurf, der Implementierung sowie den Testabläufen auf. Die Modellabdeckungsanalyse wird von Simulink Verification and Validation bereitgestellt. Ab R2011b verfügt der Embedded Coder über eine Integration mit LDRA Testbed und unterstützt damit die Codeabdeckung und weitere Teile des DO-178B-Workflows.

Wie im Fluge

Zusammenfassend lässt sich feststellen, dass Model-Based Design eine automatische Generierung von Flight-Software ermöglicht. Von der Modell- über die Quellcodeebene bis hin zum ausführbaren Objektcode sind die Programme leicht verifizierbar, außerdem lässt sich die Effizienz des erzeugten Codes optimieren. Entwicklung und Verifikation können sich daher auf Simulink-Modelle und -Testfälle konzentrieren. Diese Modelle und Testfälle lassen sich dann wieder einsetzen, wenn es um die Erfüllung der Softwareziele von DO-187B und DO-178C geht.

Simulink bietet weitere Vorteile, die diese Verbesserungen für den Prozess der Softwareentwicklung ergänzen. Dazu gehören beispielsweise seine Unterstützung für den Systementwurf und dessen angeschlossene Standards (etwa ARP 4754) sowie für die Hardwareentwicklung und deren gültige Standards (wie DO-254), wenn die Ingenieure Simulink zusammen mit Mathworks-Produkten für die physikalische Systemmodellierung, Hardware-in-the-Loop-Tests (HIL) und die Generierung von HDL-Code für FPGAs nutzen.