
Beim Debuggen regulärer Programme können Haltepunkte fast überall und in relativ großen Mengen festgelegt werden. Leider. Wenn ein Programm auf der Steuerung ausgeführt wird, gilt diese Regel nicht. Wenn es einen Abschnitt gibt, in dem das Zeitdiagramm erstellt wird, ruiniert der Stopp alles. Und der Durchgang bei niedrigen und hohen Frequenzen ist nicht dasselbe. Randbedingungen sind eine Geißel der Entwickler. Oder zum Beispiel einen USB-Bus. In NIOS II habe ich nicht damit gearbeitet, aber auf STM32 ist es schrecklich. Und ich möchte etwas sehen, und wenn Sie aufhören, bekommen Sie eine Auszeit. Im Allgemeinen ist das Verhalten des Programms in zeitkritischen Bereichen trotz fortgeschrittenem JTAG-Debugging sehr oft verdeckt. Es wäre großartig zu sehen, zumindest nach der Ausführung, welche Kette das Programm durchlief, welche Zweige funktionierten und welche nicht!
Noch wichtiger ist es, die Geschichte der Ausnahmen zu kennen. Unter NIOS II habe ich dies nicht getan, sondern auf dem Cyclone V SoC im ARM-Kern - vollständig. Beim Debuggen funktioniert alles und wenn Sie das Programm vom ROM aus starten, erhalten Sie eine Ausnahme. Es ist klar, wie sie es betreten haben und welche Art von Entwicklung der Situation dazu geführt hat, ist es nicht. Die Rückverfolgung bricht auch alle Abdeckungen.
Frühere Artikel in der Reihe:
- Entwicklung der einfachsten „Firmware“ für in Redd installierte FPGAs und Debugging am Beispiel des Speichertests
- Entwicklung der einfachsten „Firmware“ für in Redd installierte FPGAs. Teil 2. Programmcode
- Entwicklung eines eigenen Kerns zur Einbettung in ein auf FPGA basierendes Prozessorsystem
- Entwicklung von Programmen für den Zentralprozessor Redd am Beispiel des Zugriffs auf das FPGA
- Die ersten Experimente am Streaming-Protokoll am Beispiel der CPU- und Prozessorkommunikation im Redd FPGA
Einführung
Es ist üblich, Lehrartikel mit ernstem Gesicht zu schreiben und das Material ruhig und unparteiisch darzulegen. Aber leider funktioniert das nicht immer. Nun sollte es laut Plan einen Artikel über die Optimierung des synthetisierten Prozessors im Redd-Komplex geben, in dem wir über die Funktionen der Arbeit mit dem Cache sprechen müssen. Als nächstes folgt ein Artikel über Verzögerungen beim Zugriff auf den Bus. Im Allgemeinen kann dies alles auf einem Oszilloskop gezeigt werden. Ich habe dies bereits in einem Artikel über DMA ("
DMA: Mythen und Realität ") getan. Aber ich wollte alles mit dem Prozessor selbst demonstrieren, ich habe solche Überprüfungen für den ARM-Kern im FPGA Cyclone V SoC durchgeführt. Sehr praktisch (obwohl die Ergebnisse nicht veröffentlicht wurden). Aus diesem Grund habe ich mich entschlossen, mich mit dem dem JTAG-Block innewohnenden Verfolgungsmechanismus zu befassen. Es ist schade, dass ich bisher nicht mit kostenlos herunterladbaren Mitteln anzeigen konnte, wie viele Beats dieser oder jener Befehl ausgeführt wurde, aber es gab Material, mit dessen Hilfe das Programm immer gefragt werden kann, wie es zu einem solchen Leben gekommen ist. Nun, und außerdem, während die Erinnerungen an stürmische Abende noch frisch in meiner Erinnerung sind, werde ich sie auf ziemlich emotionale Weise wegwerfen. So wird es heute viele Memoiren und eine kleine nützliche Theorie geben.
Hardware
Daher ist es beim Debuggen eines Programms für einen Mikrocontroller sehr häufig wünschenswert, den zurückgelegten Pfad zu kennen und ihn mit voller Geschwindigkeit zu übergeben. Für den Fall von NIOS II ist dieser Mechanismus verfügbar und wird hier auf dieser Registerkarte mit den Eigenschaften des Prozessorkerns aufgeführt:

Trace-Typ legt den Typ der zu speichernden Informationen fest. Sie können nichts speichern (dies spart den Speicher des Chips), Sie können nur den Verlauf von Befehlen speichern (meistens ist dies ausreichend) oder den Verlauf von Befehlen und Daten speichern. Es ist erwähnenswert, dass die Dokumentation besagt, dass das Speichern von Informationen im letzten Modus irgendwie schwierig ist, während Überlagerungen mit dem Befehlsverlauf möglich sind und mehr Speicher verbraucht wird. Verwenden Sie diesen Modus also nur, wenn es wirklich notwendig ist.
Der Parameter Trace Storage legt den Speichertyp fest, in dem der Trace gespeichert wird. Die Dokumentation besagt, dass der externe Speicher von der Standardentwicklungsumgebung nicht unterstützt wird. Daher ist es besser, nur das Innere zu wählen.

Nun, Onchip Trace Frame Size legt die Größe des Puffers fest. Je größer der Puffer, desto mehr Ereignisse können darin platziert werden, desto größer kann der Verlauf berücksichtigt werden. Aber desto weniger wird die Erinnerung an den Kristall für andere Bedürfnisse sein.

Es ist nicht erforderlich, das Kontrollkästchen zu aktivieren, um einen separaten JTAG-Port zu erstellen. Lassen Sie alles regelmäßig Taxis.
Software-Support
Gut. Also richten wir den Prozessorkern ein. Wie geht es weiter? Ohhhh! Dann beginnt die Detektivgeschichte. Wenn die obigen Abbildungen als Handlungsanleitung interpretiert werden sollen, folgen Abbildungen, die ein Durcheinander und Würgen zeigen. In einer Reihe von Dokumenten heißt es, dass Sie für die Arbeit mit der Ablaufverfolgung teure Programme von Drittanbietern und sogar spezielle JTAG-Geräte verwenden sollten. In einigen Dokumenten wird jedoch darauf hingewiesen, dass Sie etwas Vollzeit nehmen können.
Eclipse-Experimente
Großartig. Schauen wir uns Eclipse an. Ich erinnere Sie daran, dass ich die Quartus Prime 17.1-Entwicklungsumgebung verwende. Nun, es ist passiert. Wir starten das Programm zum Debuggen und gehen zum Menüpunkt, mit dem Sie verschiedene Fenster öffnen können:

Dort wählen wir das Fenster Debug-> Trace Control:

Und wir bekommen so einen Dummy:

Die Debugging-Sitzung wird jedoch gestartet. Darüber hinaus wurden die Menüpunkte Start Tracing und Stop Tracing sogar darin angezeigt (vor dem Öffnen dieses Fensters waren sie es nicht). Aber sie sind blockiert. Und ich konnte sie nicht aktivieren.

Vergebens habe ich Google mit verschiedenen Anfragen gefüllt. In alten Dokumenten werden diese Elemente als recht gut funktionierend beschrieben, in modernen werden sie jedoch einfach nicht erwähnt. Niemand erwähnt sie in den Foren. Vielleicht sagt dir jemand in den Kommentaren etwas?
Probleme mit der neuesten Version von Eclipse
Gut. Was ist mit der neuesten Version der Entwicklungsumgebung? Vielleicht funktioniert dort alles? JJJJJ! Dies ist ein Thema für ein separates Kapitel. Die neueste Version für den vierten und fünften Zyklon ist 18.1.1. Das heißt, Sie müssen zuerst Version 18.1 herunterladen und dann das Update 18.1.1 installieren. Wenn jemand entschieden hat, dass ich zu viel Freizeit habe, dass ich die Software für jede Kleinigkeit neu anordne, ist alles in Ordnung. Die Hauptprüfung betraf Cache-Probleme. Sie sind ernster, ich wollte sie in der neuen Version überprüfen, ich schreibe hier nur nicht darüber.
Also habe ich es heruntergeladen. Installiert. Zunächst wird Version 18.1 unter WIN7 gestartet, aber 18.1.1 findet die DLL nicht. Gut. Ich habe herausgefunden, dass ich Redist von Visual Studio 2015 herunterladen muss. Ich habe es installiert. Es fing an zu rennen. Erstellt ein Projekt mit einem Prozessorsystem. Er machte sich sogar fertig. Ich gehe zu Eclipse und erstelle ein Programm mit BSP, das darauf basiert, alles, wie wir es schon oft getan haben ... Und ich verstehe so etwas ...

Das Projekt wird nicht. Wenn Sie verlassen und eintreten, wird es nur teilweise geöffnet.

Sehen Sie den Ordner geschlossen? So. Warum? Ohhhh! Drei Dateien haben:

Dies sind die wunderbaren Eigenschaften des Schutzes:

Sie können also nicht geöffnet oder geändert werden ... Wenn Sie mehr Rechte vergeben, wird das Projekt geöffnet, aber die Dateien werden nicht vollständig erstellt, sodass das Sammeln nicht funktioniert. Es wurde versucht, Rechte zu erteilen, bis Eclipse geschlossen wird, und dann das Projekt gespeichert. Das Ergebnis ist das gleiche.
Könnte das schnell alternde Windows 7 schuld sein? Kein Wunder, dass mir Bibliotheken fehlten! Ich habe WIN10 mit frischem Quartus versehen und erhalte ein völlig identisches Ergebnis bei der Erstellung des Projekts! Ich habe einen Freund Aufgrund seines Arbeitsplatzes trifft er manchmal auf Produkte einheimischer Hersteller. Und er drückt eine Reihe von Gedanken über sich selbst und ihre Verwandten aus. Nun, über die Tatsache, dass "wer baut das?" Wenn ich mir den Spaß an Intel-Software anschaue, denke ich, dass sie weit vom Herkunftsland entfernt ist ... Eigentlich war dies unter Alter nicht der Fall ... Alles ist passiert, aber ich erinnere mich nicht daran.
Ich bin gerade ausgestiegen. Ich habe das Projekt mit dem FAT32-Dateisystem auf ein USB-Flash-Laufwerk kopiert. Es gibt keine Sicherheitsattribute. Ich habe das Projekt daraus geöffnet, bin in Eclipse gegangen und habe den Code erstellt. Keine Sicherheitsattribute - kein Problem. Dann habe ich es zurück auf die Festplatte kopiert und ... Nun, natürlich habe ich Probleme beim Generieren von BSP. Weil die * .bsp-Datei viele relative Pfade und einen absoluten enthält. Es ist gut, dass ich ein Flash-Laufwerk herausgezogen habe. Andernfalls hätte ich nicht bemerkt, dass BSP darauf abfällt (da dies der Geburtsort des Projekts ist) und das Projekt auf der Festplatte gesammelt wird. Hier ist ein Beispiel für einen solchen Pfad (bereits korrigiert):

Gut, gut ... Alles wurde generiert, zusammengesetzt ... Und es funktioniert genauso wie in Version 17.1 ... Und für SoC-Controller in der neuen Umgebung müssen Sie auch die JTAG-Kette jedes Mal im Programmierer neu erstellen. In Version 17.1 war es genug, dies einmal zu tun und zu speichern ... Eeeeeh. Na na ja ...
Altera Monitor und sein Problem
Auf die eine oder andere Weise führte mich die Netzwerksuche nach den Wörtern Start Tracing und Stop Tracing zu interessanten Dokumenten. Sie beschreiben verschiedene Versionen eines lustigen Programms namens
Altera Monitor heute (der Name war in alten Dokumenten anders). Sie zu finden war relativ einfach. Sie müssen das
Universitätsprogrammpaket für Ihre Version der Entwicklungsumgebung herunterladen. Beachten Sie die Lizenzbeschränkungen. Aber da wir jetzt studieren, haben wir keine Angst davor. Aber für die kommerzielle Arbeit - dort ist alles schlecht. Details hier:
www.intel.com/content/www/us/en/programmable/support/training/university/materials-software.htmlHerunterladen, setzen ... Der aktuellen Version ist ein Dokument beigefügt (da die im Internet verstreuten Versionen sehr unterschiedlich sind). Ich habe sogar versucht, ein Beispiel für mein DE0-Nano-SoC-Steckbrett zu erstellen. Es funktioniert. Aber als ich versuchte, mein Projekt zu machen, funktionierte es nicht. Die * .sof-Datei wird in das FPGA geladen. Nach einer Weile wird eine Meldung angezeigt:

Nur gibt es keine Informationen im angegebenen Fenster. Wenn Sie erneut versuchen, den Text herunterzuladen, wird der Text genau in diesem Fenster angezeigt:
JTAG-Instanz-IDs konnten nicht abgefragt werden.
Stellen Sie sicher, dass das FPGA mit der richtigen .sof-Datei konfiguriert wurde.Was ist das für ein Problem? Ich habe bei Google gesucht. Es wurden mehrere Foren mit demselben Problem gefunden. Einmal fragte ein Intel-Mitarbeiter, welche Frequenz der Autor bei JTAG hat, und schlug vor, eine Standardfrequenz festzulegen. Obwohl ich zu diesem Zeitpunkt bereits verstanden hatte, dass es nicht um die Häufigkeit ging: Das Unternehmensbeispiel funktionierte und wie sollte es eingestellt werden? In einem Forum schrieb der Autor, dass es irgendwie vorbei war. Er verstand nicht wie. Und er sagte, wenn Sie alles sorgfältig gemäß den Anweisungen tun, wird alles funktionieren. Der Rest des Bildes war der gleiche. Der Mann fragt. Sie antworten ihm nicht. Nach sechs Monaten oder einem Jahr schreibt jemand, dass er die gleiche Situation hat. Gab es eine Lösung? Und Stille aaaaaaaa ...
Erfahrene Lösungsversuche
Gut. Was könnte der Grund sein? Zuerst habe ich mich in einem Arbeitsbeispiel umgesehen. Was für eine mysteriöse JTAG-ID? Könnte dies an einem funktionierenden System-ID-System liegen?

Zu sich selbst hinzugefügt, hat nicht geholfen. Vielleicht ist die Brücke zwischen JTAG und Avalon, an die zusätzlich alle Peripheriegeräte angeschlossen sind, schuld?

Hinzugefügt - hat nicht geholfen. Ich habe noch ein paar Hypothesen ausprobiert, aber mir wurde klar, dass man für immer raten kann. Mit Trauer fragte ich sogar Yandex, Bing und sogar BaiDu. Sie alle wissen weniger als Google. Es wurde klar, dass wir uns mit der Dekompilierung befassen mussten, um aus dem Programm selbst zu extrahieren, was es brauchte. Überprüft, in welcher Sprache das Programm geschrieben ist. Es stellte sich heraus, dass in Java. Der Bytecode wird in der Datei Altera_Monitor_Program.jar gespeichert. Nun, es ist komisch. Bis auf die Tatsache, dass ich dieses Java überhaupt nicht kenne. In Java Script gab es einen Fall, der sich mit dem Internet der Dinge befasste, aber ich bin nicht auf ein echtes Java gestoßen. Aber wo unsere nicht verschwunden sind!
JAVA-Bytecode-Analyse, um das Problem zu finden
Wie öffne ich Bytecode? Google führte zu einem Artikel über Habré, in dem es heißt, dass Sie dafür die JD-GUI verwenden müssen. Fand es auf Github, lud es herunter. Ich habe den Problembereich ziemlich schnell identifiziert, da die JD-GUI eine wunderbare interaktive Navigation hat. Von der Nachricht auf die Website ging ich in 10 Minuten aus. In diesem Abschnitt wird ein Drittanbieterprogramm aufgerufen, wonach die Antwort analysiert wird. Der Anruf sieht folgendermaßen aus:
systemConsoleCommand[index] = "system-console"; systemConsoleCommand[var24++] = "--script=" + Globals.gHost.getMonitorProgramRootDir("bin/jtag_instance_check.tcl", true); systemConsoleCommand[var24++] = cable; systemConsoleCommand[var24++] = Globals.gProject.system.sofFilename; try { Process sysConsoleProc = NiosIIShell.executeCommand(systemConsoleCommand).start(); BufferedReader gdbIn = new BufferedReader(new InputStreamReader(sysConsoleProc.getInputStream()));
Nun, und weiter - Analyse der Antwort, die wir noch nicht berücksichtigen.
Mit diesem Code habe ich versucht, die NIOS II-Konsole zu öffnen:

Dort ging ich in das Verzeichnis, in dem sich die Sof-Datei befindet, und fuhr die Befehlszeile:
system-console --script = jtag_instance_check.tcl USB-0 test.sofDazu musste ich jedoch die Datei C: \ intelFPGALite \ 17.1 \ University_Program \ Monitor_Program \ bin \ jtag_instance_check.tcl an dieselbe Stelle kopieren, an der sich sof befindet, um nicht unter dem Pfad zu leiden. Am Ende bekam ich eine ziemlich anständige Antwort:
TYPE_NAME altera_avalon_jtag_uart.jtag FULL_HPATH jtag_uart_0 (INSTANCE_ID: 0)
TYPE_NAME altera_nios2_gen2.data_master FULL_HPATH nios2_gen2_0 (INSTANCE_ID: 0)
Alles scheint schön zu sein ...
JAVA Bytecode Tracing
Wenn der Fall heute stattfinden würde, würde dieser Abschnitt nicht existieren. Aber es ist gestern passiert. Ich habe Java immer noch sehr schlecht verstanden. Was dort beim Parsen des Textes geschrieben wurde, war für mich ein dunkler Wald. Zwar besuchte mein Kind zwei Jahre lang Olympiade-Programmierkurse bei 1Soviet-Franchisenehmern (Zertifikate und Handouts waren 1Sovskie). Für diese Kurse wurde verrücktes Geld gegeben. Und sie haben sie dort nur in Java unterrichtet. Also verstand er auch nicht, was weiter im Code geschrieben war (unter Beibehaltung der Intrige werde ich den Code etwas niedriger veröffentlichen, nicht jetzt). Im Allgemeinen gab es ein anhaltendes Gefühl, dass es Zeit war, zu verfolgen. Ich kenne den schlechten Abschnitt, ich sehe, dass die Zeilen dort empfangen wurden und das Programm sie mit etwas nicht mag. Also was?
Das Kind fand mir einen sehr wunderbaren Artikel
www.crowdstrike.com/blog/native-java-bytecode-debugging-without-source-codeEs handelt sich um ein sehr nützliches Plugin für Eclipse, mit dem Sie mit JARs arbeiten und darin Haltepunkte setzen können. Wo ich herunterladen kann, habe ich hier gefunden:
marketark.eclipse.org/content/bytecode-visualizer/helpIch habe Eclipse heruntergeladen, das Plug-In für die Offline-Installation mit halbem Kummer heruntergeladen ... Ich habe mit der Installation begonnen - es gibt nicht genügend Bibliotheken. Ich fing an zu lesen. Es stellt sich heraus, dass es drei Versionen des Plugins gibt. Unter Eslipse 4.5 (Mars), 4.4 (Luna) und 4.3 (ich erinnere mich nicht an den Namen). Nun, alles ist einfach. Wir gehen zur Eclipse-Website und sehen einen Link zum Herunterladen der Version von Mars für Java ... Und ... Es ist tot. Es spielt keine Rolle! Es gibt ungefähr ein Dutzend Spiegel! .. Und alle Links zu ihnen sind tot. Wir versuchen Luna für Java, dort sind Links zu x64 tot, zu x86 gibt es einen Lebenden ... Wie ein Freund von mir sagt: "Hämorrhoiden, es ist umfassend." Im Allgemeinen hatte Google Schwierigkeiten, fand aber eine 64-Bit-Java-Assembly der Mars-Version auf einem inoffiziellen Server. Ich habe es eine halbe Stunde lang heruntergeladen, aber heruntergeladen.
Ein Plugin implementiert, ein Projekt erstellt ... Horror! Dort befindet sich der Trace nicht auf der Ebene des Quellcodes, sondern auf der Ebene eines Assemblers. Kurz gesagt, der decodierte Bytecode wird verfolgt. Aber in der Tat spielt es keine Rolle! Schließlich können Sie immer überprüfen, ob die dekompilierten Quellen in einem anderen Fenster geöffnet sind, und das Plugin zeigt sehr gute Kommentare ... Es stellte sich auch heraus, dass Haltepunkte nicht an jedem Ort, sondern nur am Eingang der Funktion gesetzt werden können. Aber ich kann nicht aufhören! Es ist nicht viel da und Sie müssen vom Eingang zum Problembereich gehen.
Ich möchte Sie daran erinnern, dass die verarbeiteten Zeilen folgendermaßen aussehen:
TYPE_NAME altera_avalon_jtag_uart.jtag FULL_HPATH jtag_uart_0 (INSTANCE_ID: 0)
TYPE_NAME altera_nios2_gen2.data_master FULL_HPATH nios2_gen2_0 (INSTANCE_ID: 0)Und hier ist der Java-Code:
if (str.contains("(INSTANCE_ID:")) { Pattern getInstance = Pattern.compile("\\(INSTANCE_ID:(\\d+)\\)"); Matcher idMatcher = getInstance.matcher(str); if (idMatcher.find()) { String foundstr = idMatcher.group(1); instance = Integer.parseInt(foundstr); }
Isoliert die Instanz-ID perfekt. Und hier ist der Code:
Pattern getHPath = Pattern.compile("FULL_HPATH (.+?)\\|(.+?) \\("); Matcher hpathMatcher = getHPath.matcher(str); if (hpathMatcher.find()) { hpath = hpathMatcher.group(2).replace("|", "."); }
Die Variable hpath wird nicht ausgefüllt. Heute weiß ich schon, dass der reguläre Ausdruck:
"FULL_HPATH (.+?)\\|(.+?) \\("
erfordert zwei Wörter, die durch einen vertikalen Balken getrennt sind. Nun, dann nur was ist, nachdem die Linie genommen wurde. Ich wusste es gestern nicht. Interessanter ist eine andere. Das Kind studierte zwei Jahre lang Arbeit in Java und lernte keine regulären Ausdrücke! Nein, es ist klar, dass ihnen nicht die Sprache beigebracht wurde, sondern die Olympiadenprogrammierung mittels der Sprache, aber so wie ich es verstehe, sind reguläre Ausdrücke in Java in der Reihenfolge der Dinge. Sie nehmen solches Geld, sie schütteln Zertifikate von seriösen Unternehmen, aber sie lehren keine wichtigen Dinge ... Aber ich schweife ab.
Licht am Ende des Tunnels
Was ist die vertikale Linie? Wir nehmen das Projekt, das funktioniert hat, geben ihm das gleiche Team und erhalten diese Antwort:
TYPE_NAME altera_avalon_jtag_uart.jtag FULL_HPATH Computer_System: The_System | JTAG_UART (INSTANCE_ID: 0)
TYPE_NAME altera_avalon_jtag_uart.jtag FULL_HPATH Computer_System: The_System | JTAG_UART_2nd_Core (INSTANCE_ID: 1)
TYPE_NAME altera_avalon_jtag_uart.jtag FULL_HPATH Computer_System: The_System | JTAG_UART_for_ARM_0 (INSTANCE_ID: 2)
TYPE_NAME altera_avalon_jtag_uart.jtag FULL_HPATH Computer_System: The_System | JTAG_UART_for_ARM_1 (INSTANCE_ID: 3)
TYPE_NAME altera_nios2_gen2.data_master FULL_HPATH Computer_System: The_System | Nios2 (INSTANCE_ID: 0)
TYPE_NAME altera_nios2_gen2.data_master FULL_HPATH Computer_System: The_System | Nios2_2nd_Core (INSTANCE_ID: 1)Was ist Computer_System: The_System? Hier ist alles einfach. In dieser Artikelserie fördere ich eine fortgeschrittene Idee, bei der sich das Computersystem auf der obersten Ebene der Hierarchie befindet.
Und dieses Beispiel hat diese Verilog-Ebene: module DE0_Nano_SoC_Computer ( //////////////////////////////////// // FPGA Pins //////////////////////////////////// // Clock pins input CLOCK_50, input CLOCK2_50, input CLOCK3_50, // ADC output ADC_CONVST, output ADC_SCLK, output ADC_SDI, input ADC_SDO, // ARDUINO inout [15:0] ARDUINO_IO, inout ARDUINO_RESET_N, // GPIO inout [35:0] GPIO_0, inout [35:0] GPIO_1, // KEY input [1:0] KEY, // LED output [7:0] LED, // SW input [3:0] SW, //////////////////////////////////// // HPS Pins //////////////////////////////////// // DDR3 SDRAM output [14:0] HPS_DDR3_ADDR, output [2:0] HPS_DDR3_BA, output HPS_DDR3_CAS_N, output HPS_DDR3_CKE, output HPS_DDR3_CK_N, output HPS_DDR3_CK_P, output HPS_DDR3_CS_N, output [3:0] HPS_DDR3_DM, inout [31:0] HPS_DDR3_DQ, inout [3:0] HPS_DDR3_DQS_N, inout [3:0] HPS_DDR3_DQS_P, output HPS_DDR3_ODT, output HPS_DDR3_RAS_N, output HPS_DDR3_RESET_N, input HPS_DDR3_RZQ, output HPS_DDR3_WE_N, // Ethernet output HPS_ENET_GTX_CLK, inout HPS_ENET_INT_N, output HPS_ENET_MDC, inout HPS_ENET_MDIO, input HPS_ENET_RX_CLK, input [3:0] HPS_ENET_RX_DATA, input HPS_ENET_RX_DV, output [3:0] HPS_ENET_TX_DATA, output HPS_ENET_TX_EN, // Accelerometer inout HPS_GSENSOR_INT, // I2C inout HPS_I2C0_SCLK, inout HPS_I2C0_SDAT, inout HPS_I2C1_SCLK, inout HPS_I2C1_SDAT, // Pushbutton inout HPS_KEY, // LED inout HPS_LED, // LTC inout HPS_LTC_GPIO, // SD Card output HPS_SD_CLK, inout HPS_SD_CMD, inout [3:0] HPS_SD_DATA, // SPI output HPS_SPIM_CLK, input HPS_SPIM_MISO, output HPS_SPIM_MOSI, inout HPS_SPIM_SS, // UART input HPS_UART_RX, output HPS_UART_TX, // USB inout HPS_CONV_USB_N, input HPS_USB_CLKOUT, inout [7:0] HPS_USB_DATA, input HPS_USB_DIR, input HPS_USB_NXT, output HPS_USB_STP ); //======================================================= // REG/WIRE declarations //======================================================= wire hps_fpga_reset_n; //======================================================= // Structural coding //======================================================= Computer_System The_System ( //////////////////////////////////// // FPGA Side //////////////////////////////////// // Global signals .system_pll_ref_clk_clk (CLOCK_50), .system_pll_ref_reset_reset (1'b0), // ADC .adc_sclk (ADC_SCLK), .adc_cs_n (ADC_CONVST), .adc_dout (ADC_SDO), .adc_din (ADC_SDI), // Arduino GPIO .arduino_gpio_export (ARDUINO_IO), // Arduino Reset_n .arduino_reset_n_export (ARDUINO_RESET_N), // Slider Switches .slider_switches_export (SW), // Pushbuttons .pushbuttons_export (~KEY), // Expansion JP1 .expansion_jp1_export ({GPIO_0[35:19], GPIO_0[17], GPIO_0[15:3], GPIO_0[1]}), // Expansion JP7 .expansion_jp7_export ({GPIO_1[35:19], GPIO_1[17], GPIO_1[15:3], GPIO_1[1]}), // LEDs .leds_export (LED), //////////////////////////////////// // HPS Side //////////////////////////////////// // DDR3 SDRAM .memory_mem_a (HPS_DDR3_ADDR), .memory_mem_ba (HPS_DDR3_BA), .memory_mem_ck (HPS_DDR3_CK_P), .memory_mem_ck_n (HPS_DDR3_CK_N), .memory_mem_cke (HPS_DDR3_CKE), .memory_mem_cs_n (HPS_DDR3_CS_N), .memory_mem_ras_n (HPS_DDR3_RAS_N), .memory_mem_cas_n (HPS_DDR3_CAS_N), .memory_mem_we_n (HPS_DDR3_WE_N), .memory_mem_reset_n (HPS_DDR3_RESET_N), .memory_mem_dq (HPS_DDR3_DQ), .memory_mem_dqs (HPS_DDR3_DQS_P), .memory_mem_dqs_n (HPS_DDR3_DQS_N), .memory_mem_odt (HPS_DDR3_ODT), .memory_mem_dm (HPS_DDR3_DM), .memory_oct_rzqin (HPS_DDR3_RZQ), // Accelerometer .hps_io_hps_io_gpio_inst_GPIO61 (HPS_GSENSOR_INT), // Ethernet .hps_io_hps_io_gpio_inst_GPIO35 (HPS_ENET_INT_N), .hps_io_hps_io_emac1_inst_TX_CLK (HPS_ENET_GTX_CLK), .hps_io_hps_io_emac1_inst_TXD0 (HPS_ENET_TX_DATA[0]), .hps_io_hps_io_emac1_inst_TXD1 (HPS_ENET_TX_DATA[1]), .hps_io_hps_io_emac1_inst_TXD2 (HPS_ENET_TX_DATA[2]), .hps_io_hps_io_emac1_inst_TXD3 (HPS_ENET_TX_DATA[3]), .hps_io_hps_io_emac1_inst_RXD0 (HPS_ENET_RX_DATA[0]), .hps_io_hps_io_emac1_inst_MDIO (HPS_ENET_MDIO), .hps_io_hps_io_emac1_inst_MDC (HPS_ENET_MDC), .hps_io_hps_io_emac1_inst_RX_CTL (HPS_ENET_RX_DV), .hps_io_hps_io_emac1_inst_TX_CTL (HPS_ENET_TX_EN), .hps_io_hps_io_emac1_inst_RX_CLK (HPS_ENET_RX_CLK), .hps_io_hps_io_emac1_inst_RXD1 (HPS_ENET_RX_DATA[1]), .hps_io_hps_io_emac1_inst_RXD2 (HPS_ENET_RX_DATA[2]), .hps_io_hps_io_emac1_inst_RXD3 (HPS_ENET_RX_DATA[3]), // I2C .hps_io_hps_io_i2c0_inst_SDA (HPS_I2C0_SDAT), .hps_io_hps_io_i2c0_inst_SCL (HPS_I2C0_SCLK), .hps_io_hps_io_i2c1_inst_SDA (HPS_I2C1_SDAT), .hps_io_hps_io_i2c1_inst_SCL (HPS_I2C1_SCLK), // Pushbutton .hps_io_hps_io_gpio_inst_GPIO54 (HPS_KEY), // LED .hps_io_hps_io_gpio_inst_GPIO53 (HPS_LED), // LTC .hps_io_hps_io_gpio_inst_GPIO40 (HPS_LTC_GPIO), // SD Card .hps_io_hps_io_sdio_inst_CMD (HPS_SD_CMD), .hps_io_hps_io_sdio_inst_D0 (HPS_SD_DATA[0]), .hps_io_hps_io_sdio_inst_D1 (HPS_SD_DATA[1]), .hps_io_hps_io_sdio_inst_CLK (HPS_SD_CLK), .hps_io_hps_io_sdio_inst_D2 (HPS_SD_DATA[2]), .hps_io_hps_io_sdio_inst_D3 (HPS_SD_DATA[3]), // SPI .hps_io_hps_io_spim1_inst_CLK (HPS_SPIM_CLK), .hps_io_hps_io_spim1_inst_MOSI (HPS_SPIM_MOSI), .hps_io_hps_io_spim1_inst_MISO (HPS_SPIM_MISO), .hps_io_hps_io_spim1_inst_SS0 (HPS_SPIM_SS), // UART .hps_io_hps_io_uart0_inst_RX (HPS_UART_RX), .hps_io_hps_io_uart0_inst_TX (HPS_UART_TX), // USB .hps_io_hps_io_gpio_inst_GPIO09 (HPS_CONV_USB_N), .hps_io_hps_io_usb1_inst_D0 (HPS_USB_DATA[0]), .hps_io_hps_io_usb1_inst_D1 (HPS_USB_DATA[1]), .hps_io_hps_io_usb1_inst_D2 (HPS_USB_DATA[2]), .hps_io_hps_io_usb1_inst_D3 (HPS_USB_DATA[3]), .hps_io_hps_io_usb1_inst_D4 (HPS_USB_DATA[4]), .hps_io_hps_io_usb1_inst_D5 (HPS_USB_DATA[5]), .hps_io_hps_io_usb1_inst_D6 (HPS_USB_DATA[6]), .hps_io_hps_io_usb1_inst_D7 (HPS_USB_DATA[7]), .hps_io_hps_io_usb1_inst_CLK (HPS_USB_CLKOUT), .hps_io_hps_io_usb1_inst_STP (HPS_USB_STP), .hps_io_hps_io_usb1_inst_DIR (HPS_USB_DIR), .hps_io_hps_io_usb1_inst_NXT (HPS_USB_NXT) ); endmodule
Ich habe es speziell vollständig zur Sprache gebracht, um zu betonen, wie viel völlig unnötigen Code Sie in diesem Fall schreiben müssen. Und wenn die Beine hinzugefügt oder entfernt werden, muss dieser Code ebenfalls bearbeitet werden. Eigentlich die Zeilen

Gleicher Text: ... Computer_System The_System ( //////////////////////////////////// // FPGA Side //////////////////////////////////// // Global signals .system_pll_ref_clk_clk (CLOCK_50), ...
und geben Sie dieses Präfix. Die Autoren glauben, dass die Hierarchie so sein sollte, nur diese und keine andere. Das Prozessorsystem kann nicht tiefer entfernt und nicht hochgetragen werden.
Wir sollten nicht auf die Gnade der Natur warten, sondern sie annehmen - unsere Aufgabe!
Haben wir wirklich so einen Job gemacht, nur um diese Angelegenheit zu ertragen? Wie ein Freund von mir gerne sagt: „Unnötige Arbeit ist schlimmer als Trunkenheit“, und die Schaffung einer solchen Schicht ist ein typischer Fall von unnötiger Arbeit. Daher werden wir versuchen, diese Einschränkung zu umgehen. Denken Sie daran, dass beim Aufrufen eines JAVA-Programms eines Drittanbieters der Code ein tcl-Skript ersetzte und ich es auch in das Verzeichnis neben der sof-Datei kopierte. Es ist unser Heil! Er teilt der Systemkonsole mit, welche Aktionen auszuführen sind, und er formatiert die Antwort. Die Formatierung sieht folgendermaßen aus:

Gleicher Text: # PRINT OUT INSTANCE ID INFO FOR EVERYTHING: set i 0 foreach path [lsort -command compare_node_number [get_service_paths bytestream]] { # If this path corresponds to a JTAG UART, incr i if {[string match *$cable_name* $path ] && [string match *jtag_uart* [marker_get_type $path] ]} { puts "[marker_get_info $path] (INSTANCE_ID:$i)" incr i } } set i 0 foreach path [lsort -command compare_node_number [get_service_paths processor]] { # If this path corresponds to a NiosII, incr i if {[string match *$cable_name* $path ] && [string match *nios2* [marker_get_type $path] ]} { puts "[marker_get_info $path] (INSTANCE_ID:$i)" incr i } }
Der erste Block formatiert Informationen zu JTAG_UART-Blöcken, der zweite zu Prozessorkernen. Wenn wir hier vertikale Linien zum Ausgabestream hinzufügen! Mein Kollege hat diesen Abschnitt wie folgt korrigiert:
# PRINT OUT INSTANCE ID INFO FOR EVERYTHING: set i 0 foreach path [lsort -command compare_node_number [get_service_paths bytestream]] { # If this path corresponds to a JTAG UART, incr i if {[string match *$cable_name* $path ] && [string match *jtag_uart* [marker_get_type $path] ]} { set info [marker_get_info $path] if {[string first "|" $info] == -1} { set info [string map {"FULL_HPATH " "FULL_HPATH a:b|"} $info] } puts "$info (INSTANCE_ID:$i)" incr i } } set i 0 foreach path [lsort -command compare_node_number [get_service_paths processor]] { # If this path corresponds to a NiosII, incr i if {[string match *$cable_name* $path ] && [string match *nios2* [marker_get_type $path] ]} { set info [marker_get_info $path] if {[string first "|" $info] == -1} { set info [string map {"FULL_HPATH " "FULL_HPATH a:b|"} $info] } puts "$info (INSTANCE_ID:$i)" incr i } }
Wenn keine Bindestriche vorhanden sind, werden diese hinzugefügt. Und schließlich funktioniert das Programm nicht nur mit einem schrecklichen, sondern auch mit einem optimal geschriebenen Prozessorsystem!
Einrichten eines Projekts in Altera Monitor
Uffff. Das ist alles. Das Ende des Aushöhlens, des Geländes und der Schlamperei (obwohl im Gelände - das ist nicht korrekt). Die Zeichnungen im Artikel spiegeln nun wieder die Arbeitsanweisungen wider! Wir haben ein Projekt für FPGAs sowie ein Programm, das in Eclipse erstellt und ausgeführt wird. Starten Sie nun Altera Monitor und erstellen Sie ein Projekt.

Wir erstellen einen Katalog mit dem Projekt (ich habe ihn getrennt vom Projekt für FPGA abgelegt) und geben den Namen des Projekts an. Wählen Sie auch eine Prozessorarchitektur

Das System, das ich wähle, ist Benutzerdefiniertes System. Sie müssen meine * .sof- und * .sopcinfo-Dateien angeben. Ich wähle sie in den Arbeitsverzeichnissen aus. Unser System benötigt keinen Preloader.

Wählen Sie den Programmtyp Programm mit Gerätetreiberunterstützung aus, dann wird die BSP-Bibliothek erstellt:

Bisher gibt es nur eine Arbeitsdatei (sie wurde in Eclipse erstellt). Hier füge ich es hinzu:

Im letzten Fenster ändere ich nichts:

Wir stimmen dem Download der Sof-Datei zu:

Wenn wir nur die Software installiert haben, sind wir in den Quellmodus gewechselt. Dann wird es bereits eingeschaltet (ich werde Ihnen zeigen, wie das Menü aussieht, wenn alles bereits eingeschaltet ist, es wird auch ein Element zum Einfügen geben).

Ich habe das einfachste C-Programm:
#include "sys/alt_stdio.h" int main() { alt_putstr("Hello from Nios II!\n"); volatile int i=0; i += 1; i += 2; i += 3; i += 4; i += 5; i += 6; i += 7; i += 8; i += 9; i += 10; i += 11; i += 12; /* Event loop never exits. */ while (1); return 0; }
Ich versuche es zu sammeln:

Ich erhalte eine Fehlermeldung:
c: /intelfpga/17.1/nios2eds/bin/gnu/h-x86_64-mingw32/bin /../ lib / gcc / nios2-elf / 5.3.0 /../../../../ .. /H-x86_64-mingw32/nios2-elf/bin/ld.exe: Regionscode um 15888 Bytes übergelaufenDies liegt daran, dass ich dem System kein SDRAM hinzugefügt habe, sondern es auf den internen FPGA-Speicher beschränkt habe. Aber warum passte alles in Eclipse, aber nicht hier? Weil ich dort BSP mit dem Suffix Small gewählt habe, wurde mir hier aber automatisch ein reguläres Paket gemacht. Öffnen Sie daher die Datei: C: \ Work \ Play2 \ BSP \ settings.bsp
Und wir beginnen mit der manuellen Abstimmung.


BSP neu erstellen:

Und wieder sammeln wir das Projekt. Diesmal erfolgreich. Laden Sie es jetzt:

Endlich die wahre Spur
Sie haben nicht vergessen, warum ich das alles mache? Ich mache das zum Aufspüren. Es muss aktiviert sein. Gehen Sie dazu zur Registerkarte Trace und wählen Sie im Kontextmenü Trace aktivieren:

Ich werde einen Haltepunkt am Ende der Funktion main () auf der Registerkarte Disassembly einfügen (wie schön der RISC-Assembler nach dem schrecklichen Stack-Assembler aussieht, in den der Java-Code verwandelt wird!)
Hier ist der Beginn der Hauptfunktion:

Scrollen Sie ein wenig nach unten und setzen Sie hier einen Haltepunkt:

Wir starten, warten auf einen Stopp und gehen zur Registerkarte Trace.
Im Allgemeinen ist nicht alles sehr gut. Anfangs gab es offensichtlich eine Art von Erwartung (wir hatten dort eine Schlussfolgerung in der JTAG, es ist also eine legitime Sache):

Am Ende - ein anderer Code ... Aber ich sehe den Hauptfunktionscode nicht! Hier ist das Ende:

Ich weiß nicht einmal, was ich sagen soll. Wenn Sie jedoch nicht einen, sondern zwei Haltepunkte (am Anfang und am Ende der Hauptfunktion) setzen, ist das Bild nach dem Übergang vom ersten zum zweiten anständig:

Kurze Schlussfolgerungen
Wir haben also herausgefunden, dass es durchaus möglich ist, herauszufinden, wie eine bestimmte Site funktioniert. So wird das Thema des Artikels ("... wie der Prozessor zu einem solchen Leben gekommen ist") offenbart. Interessanter ist, wie all diejenigen, deren Probleme gelöst werden mussten, um ein Ergebnis zu erzielen, zu einem solchen Leben gekommen sind? Und es ist sehr bedauerlich, dass ich bisher nicht feststellen konnte, wie viele Bars ein bestimmtes Team absolviert hat. Aus Ausschnitten der Dokumentation geht hervor, dass dies technisch möglich zu sein scheint, aber welche Software dies zulässt, ist nicht klar. Es gibt eine Meinung, dass das Dokument
Analysieren und Debuggen von Designs mit der Systemkonsole , das ich bei der Analyse des tcl-Skripts durchlesen musste, uns helfen wird. Es hat ein interessantes Tablet.
Tabelle 10-15: Trace-Systembefehle , aber ich persönlich habe einfach keine Zeit für eine detaillierte Untersuchung dieser Angelegenheit. Aber vielleicht ist es für jemanden so wichtig, dass er alles umsetzt. Diese Befehle sind in tcl-Skripten enthalten.
Nun, in den folgenden Artikeln müssen die Messungen auf die altmodische Weise mit einem Oszilloskop durchgeführt werden.