Um bei der Entwicklung elektronischer Steuergeräte Zeit und Kosten zu sparen, setzen Halbleiter- und Automobilbranche zunehmend auf Pre-Silicon-Development und Software-Prototyping. Welche Vor- und Nachteile bringt's für die Softwareentwicklung, das Testen und das Debuggen mit virtuellen Prototypen?
Cross-Debugger also Debugging-Werkzeuge, die typischerweise auf einem PC laufen, aber Software analysieren und steuern, die für eine andere, oftmals eingebettete Zielarchitektur bestimmt ist, sind längst nicht mehr nur dann gefordert, wenn die Software einer elektronischen Steuereinheit (ECU) nicht das tut, was man vermeintlich richtig programmiert hat. Vielmehr handelt es sich dabei heutzutage häufig um sehr vielseitig nutzbare Werkzeuge, die aus den Softwareentwicklungs-Toolchains für elektronische Steuerungen nicht mehr wegzudenken sind (Bild 1). Debugger wie die »UDE Universal Debug Engine« von PLS werden längst nicht mehr nur für das Software-Debugging auf echter Hardware eingesetzt; zunehmend an Bedeutung gewinnen auch die Systemanalyse, der Test und das Debugging auf virtuellen Prototypen, also in der frühen Entwicklungsphase, in der die Zielapplikation noch auf einem Simulator läuft.
Einen Simulator anstatt eines realen Mikrocontrollers zu nutzen, kann verschiedene Gründe haben. Da sind zunächst einmal die Kosten. Die Softwareentwicklung auf echter Hardware erfordert immer ein Entwicklungsboard auf dem Tisch des Softwareingenieurs. Das mag für kleine Projekte mit kleinen Mikrocontrollern kein Problem sein. Bei Automobilelektronik-Steuergeräten mit komplexen, heterogenen Multicore-Mikrocontrollern und -Prozessoren können Entwicklungsboards hingegen schon einmal schnell deutlich vierstellige Summen kosten.
Eine kostengünstige und flexible Alternative zum direkten Debugging auf der realen Zielhardware besonders in frühen Entwicklungsphasen oder bei der Entwicklung von modularen, in sich abgeschlossenen Softwarekomponenten stellen Instruction-Set-Simulatoren (ISS) dar. Nicht selten sind diese auch als Zusatz-Feature für den Debugger verfügbar. PLS‘ UDE beispielsweise umfasst neben dem Debug- und Trace-Support für die Bausteine der Infineon-Aurix-Familie auch den als TSIM bezeichneten ISS (Instruction Set Simulator) für die TriCore-Architektur und ermöglicht sowohl Debugging als auch Tracing dafür.
Generell simuliert ein ISS den Befehlssatz (Instruction Set) der Zielarchitektur exakt gemäß der Spezifikation der jeweiligen Instruction Set Architecture (ISA). Der kompilierte Code wird dabei genauso ausgeführt wie später im realen Prozessor, was eine realitätsnahe funktionale Verifikation ermöglicht – völlig unabhängig von der Verfügbarkeit oder Stabilität der physischen Hardware.
Ein großer Vorteil dieser Methode liegt im uneingeschränkten Zugriff auf alle Register, Speicherbereiche und die Programmlogik. Prinzipbedingt gibt es zudem keinerlei Limitierungen hinsichtlich verfügbarer Debug-Funktionen, wie zum Beispiel der Anzahl nutzbarer Breakpoints. Entwickler können Programme schrittweise analysieren und Fehler gezielt reproduzieren, ohne potenzielle Risiken für reale Systeme einzugehen. Auch automatisierte Unit-Tests und Regressionstests lassen sich im ISS effizient integrieren. Ein weiterer Vorteil ist die einfache einschränkungsfreie Aufzeichnung der Programmausführung während deren Laufzeit. Dieses Program Tracing ist auf echter Hardware nicht nur mit höheren Hardwarekosten verbunden. Darüber hinaus müssen auch immer Limitierungen bezüglich der Aufzeichnungsdauer in Kauf genommen werden, weil für die Trace-Daten nur begrenzter Speicherplatz zur Verfügung steht. Gerade letzteres ist beim Simulator nicht der Fall.
Wo Licht ist, ist bekanntlich auch Schatten. Weil bei der Instruction-Set-Simulation der Fokus auf der funktionalen Ausführung des Codes liegt, wird das zeitliche Verhalten eines realen Systems – etwa durch die Prozessor-Pipeline, Cache-Effekte oder Out-of-Order-Execution – nicht berücksichtigt. Laufzeitmessungen und Performance-Analysen liefern daher keine belastbaren Ergebnisse. Ebenso fehlen in typischen ISS-Umgebungen die Peripherals, weshalb jedwede externe »Physik«, Interrupt-Latenzen oder Race-Conditions nur unzureichend simuliert werden können. Entsprechende Hardware-Interaktionen müssen durch Mockup-Code ersetzt werden, was zusätzlichen Aufwand verursacht. Daher eignet sich die Instruction-Set-Simulation vor allem zur isolierten Entwicklung und funktionalen Prüfung von Softwaremodulen. Für die ganzheitliche Systemintegration und das Aufdecken hardwareabhängiger Fehler bleibt das Debugging auf der realen Zielplattform unerlässlich.
Die immer rasantere Innovationsgeschwindigkeit und der damit einhergehende Wettbewerbsdruck in vielen Branchen führt dazu, dass gerade auch im Automotive-Bereich Projekte inzwischen immer öfter bereits mit der nächsten oder sogar übernächsten MCU-Generation evaluiert werden. In diesem Fall spielen virtuelle Prototypen und deren Simulation natürlich eine zentrale Rolle. Pre-Silicon-Development sowie Software-Prototyping sind heutzutage entscheidend für die signifikante Verkürzung der Time-to-Market. Unabhängig von der Verfügbarkeit von erstem Silizium für die neue Zielhardware können vor allem Schlüsselkunden großer Halbleiterherstellern deshalb mitunter schon viele Monate vorher mit der Softwareentwicklung beginnen.
Die für das Pre-Silicon-Development und Software-Prototyping eingesetzten Simulatoren und die darauf laufenden MCU-Modelle sind natürlich deutlich umfangreicher und damit auch kostenintensiver als reine Instruction-Set-Simulatoren. Neben den Cores werden zusätzlich Peripherals, Bussysteme und teilweise sogar deterministische Modelle des Speicher-Subsystems modelliert. Dadurch lassen sich auch komplexere Systemverhalten und erste Integrationsszenarien wie etwa Timer-Interrupts, DMA-Transfers oder Peripherie-Anbindungen wie SPI oder CAN simulieren.
Ein aktuelles Beispiel ist Infineons Automotive RISC-V Prototype, dem das Synopsys Virtual Development Kit (VDK) zugrunde liegt. Der virtuelle Prototyp kombiniert die Modelle der RISC-V-Multi-Core-Cluster mit Modellen des Interrupt-Controllers, der Interprozessor-Kommunikation und speziellen Automotive-Peripherals. Standardisierte Schnittstellen des VDKs ermöglichen es Debugger-Tools wie der UDE, als Frontend für den Simulator zu fungieren. Dadurch können Entwickler ihre Software in der Simulation genauso debuggen und testen wie später auf dem realen Silizium. Debugger-Oberfläche und -Funktionen sind 100-prozentig identisch. So lassen sich schon frühzeitig Low-Level-Software wie Start-up-Code, Treiber oder Safety-Libraries mit virtuellen Prototypen entwickeln sowie Software-Architekturen und sicherheitsrelevante Funktionen evaluieren und gegen erste Anforderungen verifizieren. Wer hier also frühzeitig auf einen Cross Debugger setzt, partizipiert bei der Verfügbarkeit der realen MCU von einem nahtlosen Übergang von der Pre-Silicon- zur Post-Silicon-Entwicklung und somit von einem minimierten Umstellungsaufwand im Projektverlauf.
Es gibt noch zwei weitere gewichtige Aspekte, warum es sich anbietet, statt auf realem Silizium auf einem Simulator zu debuggen: Komfort und Effizienz.
Cross-Debugger sind für das Debuggen auf einer realen MCU immer auf unterstützende Hardware-Features im Chip angewiesen. Das umfasst zunächst die Hardware-Breakpoints, die durch den Debugger per Debug-Register so konfiguriert werden, dass die CPU vor der Ausführung einer Instruktion an einer bestimmten Adresse die Ausführung unterbricht. Und zwar so, dass die CPU-Pipeline in ihrem Verhalten nicht verändert wird, also die Ausführung nach dem Anhalten auch sicher fortgesetzt werden kann. Ergänzend zu den Hardware-Breakpoints können im Core-Befehlssatz Debug-Instruktionen implementiert sein, die ebenfalls die Ausführung anhalten. Der Debugger tauscht an der gewünschten Position im Code die ursprüngliche Instruktion reversibel gegen die Debug-Instruktion aus, um einen sogenannten Software-Breakpoint zu realisieren. Auch gibt es häufig komplexere Trigger, mit denen sich Daten-Breakpoints, Watchpoints oder Ähnliches realisieren lassen. All dies erfordert zusätzliche Logik auf dem Silizium und verursacht Kosten. On-Chip Debug-Funktionen sind deshalb immer ein Kompromiss. Simulatoren kennen solche Einschränkungen kaum. Einzig auf die Simulationsgeschwindigkeit können sich gesetzte Breakpoints negativ auswirken, weil hier zusätzliche Prüfungen während der Simulationsschritte erforderlich sind.
Als überaus vorteilhaft erweist sich eine Simulation oft auch, wenn Spezialapplikationen für einen Beschleuniger-Core entwickelt werden müssen. Beim Debuggen auf realer Hardware muss sich der Entwickler immer noch um das Gesamtstartverhalten der MCU kümmern, also um das Booten und das anliegende Starten und Initialisieren des Beschleuniger-Cores: Clock konfigurieren und Einschalten, Applikation laden usw. Bei der Verwendung eines Simulators hingegen steht nach dem Start sofort ein vollständig initialisierter virtueller Prototyp des Cores zur Verfügung.
Ein Beispiel dafür ist das in einer ganzen Reihe von Automotive-Mikrocontrollern implementierte Generic Timer Module (GTM) von Bosch. Neben einer Vielzahl unterschiedlicher Funktionsblöcke zur Signalerfassung, -filterung und -erzeugung verfügt der IP-Block auch über mehrere programmierbare RISC-basierte Multi-Channel Sequencer (MCS). Sowohl die Initialisierung des GTM als auch das Debugging ist in realer Hardware nicht trivial: Die GTM-Applikation muss beispielsweise durch die Main-Applikation in den GTM-Speicher kopiert werden, und auch die geringe Anzahl der verfügbaren Breakpoints – zwei Hardware-Breakpoints, keine Software-Breakpoints – erschwert das Debugging.
Eine deutliche komfortablere Möglichkeit für die Software-Entwicklung bietet hier der Virtual Prototype des GTM in der Entwicklungsumgebung COSIDE von COSEDA Technologies. Die UDE dient in diesem Beispiel als Frontend für ein komfortables Debugging der GTM-MCS-Applikationen (Bild 2). Die Simulation erfolgt unabhängig vom konkret eingesetzten Mikrocontroller, und die Anzahl nutzbaren Breakpoints ist prinzipbedingt unbegrenzt. Im Unterschied zum GTM in realer Hardware wird das gesamte GTM-Model bei Erreichen eines Breakpoints angehalten, was einem Einfrieren der Zeit gleichkommt. Somit hat das Debugging keinerlei Einfluss auf das Systemverhalten, ist also nicht-invasiv, und die Simulation ist zu 100 Prozent reproduzierbar.
Die Kommunikation mit der Simulatorsoftware stellt für entsprechend leistungsstarke und flexible Debugger wie der UDE keine große Herausforderung dar. Dafür bieten die Simulatoren entweder ein proprietäres Interface an (Software-API) oder greifen auf das MCD-Interface (Multi-Core Debug API) zurück. MCD ist eine standardisierte leistungsfähige, aber trotzdem einfache C-Schnittstelle, die Debuggern den Zugriff auf reale oder simulierte Multicore-Systeme ermöglicht. In der UDE ist dafür ein sogenanntes Simulator-Target-Interface vorgesehen, das die MCD-Schnittstelle bedient und statt der Target-Interfaces für die reale Hardware durch die Debugger-Komponenten benutzt wird (Bild 3). Dadurch registrieren die Debugger-Komponenten gar nicht, dass sie gerade mit einem Simulator verbunden sind.
Es gibt also eine ganze Reihe guter Gründe, in bestimmten Phasen der Software-Entwicklung zumindest gelegentlich auf einen Simulator statt auf reale Hardware zurückzugreifen: Entscheidend ist dabei allerdings, dass der verwendete Debugger den Entwicklern für beide Optionen die gleichen Funktionen und Sichten auf das Zielsystem zur Verfügung stellt, damit ein reibungsloser Übergang zwischen dem virtuellen Prototypen und dem Silizium ohne Toolwechsel möglich ist.