 Das ist jetzt der, wir übersetzen den Talk, der nächste Talk ist Ende zu Ende formelle Verifizierung von Reducing Suscription Ships, 5 Prozessoren mit einem etwas, was riskformel heißt, der Clifford Wolf hält den Talk, die Clifford ist sehr bekannt in der open software Community und ist besonders für Eistorm bekannt, bitte helft uns, helft mir den zu begrüßen, Clifford zu begrüßen. Vielen Dank, mein Vortrag ist über Ende zu Ende formelle Verifikation und ich fange am besten an um den Titel zu erklären, was ist Risk5? Risk5 ist eine offene ins Kommandos Architektur, das ist eine Spezifikation für Professoren, das jeder benutzen kann und falls du schon deinen eigenen Prozessor implementiert hast, dann weißt du vielleicht, dass es einfacher ist eine Prozessor zu implementieren als alle Werkzeuge, also Compiler und so weiter, um den Prozessor zu benutzen, zu entwickeln und wenn du Risk5 benutzt, dann kannst du alle Werkzeuge benutzen, die es schon gibt, aber für das Unternehmen brauchen wir Prozessionen, die kompatibel zueinander sind, das heißt, die Risk5 richtig implementieren und wir fangen mit einem Prozessor an und sagen, das ist ein richtiger Prozessor und dann finden wir einen Bug und dann wird die Spezifikation geändert und dass die Spezifikation jetzt der Hardware, das für die Hardware passt, das kann man mit Risk5 nicht machen, weil es sehr viele Hardware-Implikationen gibt, die die gleiche Spezifikation erfüllen, das heißt, wir brauchen etwas, wir brauchen Mittel, um festzustellen, dass die Prozessor tatsächlich mit der Spezifikation übereinstimmen. Was ist Formelle Verifikation? Das ist ein sehr breiter Begriff. In diesem Zusammenhang geht es um die Verreferzierung von Hardware-Modellen, Spezifische Ober-Sicherheits-Eigenschaften, es gibt da so ein Hardware-Entwurf und es gibt einen Anfangszustand und wir würden wüssten gerne, ob dieses Hardware, ob die Hardware einen schlecht, einen illegalen Zustand aus dem Anfangszustand erreichen kann und das versuchen wir, Formelle zu lösen. Es gibt dafür zwei Mittel, das zwei verschiedene Kategorien von Beweisen, es gibt beschränkte und unbeschränkte Beweise. Mit dem Beschränkenbeweis können wir nur feststellen, dass es für eine bestimmte Anzahl von Zyklen nicht zu einem schlechten Zustand führt, mit einem unbegrenzten Beweis stellen wir fest, dass das in beliebigen Zyklen nicht passieren kann. Deswegen ist ein unbegrenzter Beweis besser, aber das ist oft schwer zu erreichen, aber ein begrenzter Beweis ist leichter zu erreichen, deswegen reden wir darüber. Was ist End-to-end Verifikation? Das ist auch in dem Titel, also historisch, wenn man ein Prozessor verifiziert oder so etwas wie ein Prozessor verifiziert, wird der Prozessor in sehr viele kleine Komponenten zusammengebracht und dann wird für jede einzelne Komponente bewiesen, dass sie den Eigenschaften gehören. Dann packt man diese kleinen Module zusammen und prüft, dass es zusammenstellen die Eigenschaften hat, sodass das gesamte System bewiesen ist. Man sieht das als Black Box an und fragt, ob das eine große Dinge die Eigenschaften hat, die man haben möchte. Auf diesem Weg gibt es Vorteile, es ist nämlich viel einfacher, die Spezifikation von einem Prozessor auf einen anderen Prozessor zu übertragen, weil es sich nicht interessiert, wie der Prozessor gebaut wurde. Es ist sehr viel einfacher, die Spezifikation zu nehmen, die wir haben, um sie auf andere Instruktionsarchitekturen anzuwenden, weil wir haben die eine Spezifikation, die wir erwarten von unserem Prozessor. Der große Nachteil ist, dass es viel teurer ist, die End-zu-End-Vergifikation zu machen, insbesondere vom Prozessor gegenüber die ESA-Spezifikation. Das ist sozusagen ein Beispiel, ein Buchbeispiel. Leider sind die Methoden schlechter geworden. Also es ist das RISC5 Format, das ist ein Framework, das Ende formelle Verifikationen von Prozessoren gegen die ESA-Spezifikation ermöglicht. So RISC5 ist nicht ein formell spezifizierter Prozessor, sondern falls du einen RISC5 Formal Prozessor hast, dann kannst du beweisen, dass der Prozessor den ESA-Spezifikation genügt. Hauptsächlich benutzt du das begrenzte Method, das Bounid Method. Man kann auch anbounid Methods, also unbegrenzte Methoden benutzen, das ist nicht der hauptsächliche Verwendungsfall. Das ist gut, um Bugs zu handeln, also Fehler zu finden. Es gibt vielleicht Beispiele, dass der Prozessor in seinem Verhalten divergiert, aber normalerweise, wenn man so etwas wie den Prozessor hat, kann man keinen illegalen Zustand in kurzer Zeit erreichen. Es gibt schon mal einen hohen Konfidenzintervall, dass der Prozessor so funktioniert wie spezifiziert. Also wenn man einen Prozessor hat und um festzustellen, dass der Prozessor den Spezifikation genügt, muss man einen Transport, also einen speziellen Zugang definieren, um den Punkt anzuschauen. Man muss riskv-Formel dann definieren, welche Möglichkeiten zur Verfügung stehen, zum Beispiel 32-Bit-Operationen, 64-Bit-Operationen und muss dem also riskv-Formel sagen, was der Prozessor kann. Es gibt auch noch andere Sachen, die transparent sind für einen Prozessor, der einfach vom User betrieben wird. Okay, Entschuldigung, wenn wir... Das heißt, man muss verifizieren, es gibt die Möglichkeit, dass man unformatierte Lese- und Schreibzugriffe definieren kann und die Frage ist jetzt, kann der Prozessor da einfach, also das ist ein Unformatier, ein Un-, nicht, nicht, nicht allein Zugriff durchführen ist, wird das einfach für das zu einer Fehlerbehandlung oder kann er das? Okay, zurzeit gibt es hier keine Unterstützung für Gleitkommerzahlenbehandlung und das wird aber noch weitergebildet, also das wird größer und größer, aber all die zusätzlichen Möglichkeiten werden optional sein und vielleicht möchte jemand nur einen ganz kleinen Mikrocontroller implementieren, die ja keine Gleitkommerzahlen unterstützen oder die keine privilegierte Spezifikationen unterstützen und dann haben sie keine spezifischen FSIS. Es wird auch dokumentiert, welche Instruktion... Zurückgenommen werden. Okay, hier ist der Programmzähler für die nächste Instruktion und hier ist der Wert, den ich in dem Register gefunden habe, das ist das Register, das ich geschrieben habe, das ist der Wert, den ich in das Fall geschrieben habe. Also kurz, wir dokumentieren über das RISC-5 vom Interface den Teil des Prozessorzustands, der durch den Befehl geändert wird, also was zum Registerfall geändert wird, was beim Programmzähler gewendet wird. Die meisten Prozessoren sind selbstverständlich Super Scalar, auch wenn sie nicht so aussehen, man kann also Speicherzugriffe, Speicherladezugriffe, außer nicht in der richtigen Reihenfolge machen. Selbst mit solchen Prozessoren denken wir nicht unbedingt in Super Scalareprozessoren, sodass sie vielleicht mehr Instruktionen zyklos machen können. Das können wir mit diesem N-Red Parameter machen, der kann fünfmal so weit aufnehmen, wenn Red Type 5 ist. Okay, wir haben einen Prozessor, der diese Schnittstelle implementiert, was ist die Strategie zur Verifikation, die RISC-5 verfolgt, um formal zu beweisen, dass unser Prozessor tatsächlich korrekt ist. Okay, da gibt es nicht einen großen Beweis, den wir laufen. Stattdessen werden wir einfach ganz viele kleine Beweise tätigen. Das ist der wichtigste Trick, wenn man sich darum will. Es gibt verschiedene Kategorien von Beweisen, eine Kategorie nenne ich Instruktion zu Überprüfungen. Jede Instruktion und jeder Kanal im formalen N-Red Parameter Schnittstelle kann man überprüfen. Und da gibt es locker 100 Instruktionen und dann musst du noch ein paar Kanäle, dann musst du locker 200 Beweise tätigen. Was Sie Instruktionstests machen, ist, Sie fangen in einem Zustand an und lassen es quasi für den unbegrenzten Beweis ewig weiterlaufen. Aber wir können nur eine bestimmte Anzahl von Zyklen laufen lassen und dann nehmen wir einfach an, dass diese Instruktion unserer Annahme entspricht. Und wenn das stimmt, dann gehen wir davon aus, dass der letzte Zyklus in unserem begrenzten Beweis das Ende war. Und dann gucken wir uns die ganzen Schnittstellen an auf die Formatestellen von RISC-5 und gucken uns an, ob das ist, was wir erwartet haben nach der korrekt dekorierten Instruktion, ob die richtigen Werte in die richtigen Register geschrieben wurden sind, ob die Summenstimmen, die wir geschrieben haben. Aber wenn man nur diese Instruktionstests hat, dann hat man natürlich noch eine Lücke in der Verifikation. Okay, man kann sagen, okay, ich habe da diesen Werte in das Register geschrieben, aber vielleicht habe ich das gar nicht geschrieben. Also deswegen gibt es einen zweiten Satz von Verifikation, die benutzen nur einen ganz, ganz kleinen Teil der Schnittstelle des RISC-5, aber über mehrere Zyklen. Also wenn man zum Beispiel ein Register schreibt und dann später diest, dann sollte ich doch bitte das lesen, was ich vorher geschrieben habe. Das sind dann, sozusagen, Konsistenzchecks. Die nehmen nur wenige Instruktionen, aber dafür über mehrere Zyklen und beobachten diese. Okay, für jede Instruktion in der RISC-5-Formale Instruktion Modell sieht es ungefähr so aus. Das sind zwei Folien. Das Erste zeigt die Schnittstelle, die erste Folie. Da gibt es ein paar Signale des RISC-5-Formalen, RISC-5-Formalen Schnittstelle und die Instruktion, die wir ausführen, wo der Programm counter steht, wo wir die Sachen gefunden haben. Und dann gibt es da noch ein paar Signale, die generiert werden durch unsere Spezifikation. Also das ist sozusagen die Ausgabe unserer Refligationsmodelle, welche Register sollen wir lesen, welche Register sollen wir schreiben, welche Werte sollen wir da reinschreiben in diese Register. Das ist also die Schnittstelle für alle Instruktionen. Und dann gibt es den Body, der sieht so aus, den Körper, der sieht so aus. Der die Instruktion dekodiert und checkt, ob das Schnittstelle sofort ausgeführt wird. Und dann haben wir so Sachen, wie die Zeile da in der Nähe vom Boden, der sagt, dass der nächste Programmzähler 4 bytes weiterzählen muss, also einfach um 4 erhöht werden muss. So was. Das ist aber die unterste Zeile im vorletzten Abschnitt. Sehr, dass in diesem Verilog keine Assert Statements drin sind. Das ist einfach das Verhalten, wie man es erwarten würde. Und dann gibt es einen Rapper, der das Ganze instanziert. Und da sind dann Assertions, also Überprüfungen, ob diese Bedingungen erfüllt werden. Das hier wird einfach der gewünschte Ausgabe erzeugt. Und dann kann man an diesen, neben dem Kern, also einen Monitor, also einen Überwachungskor implementieren, der dann überwacht, dass dieser Kern hier das Richtige produziert. Das ist gut, wenn man diesen Kern für vielleicht 4 Tage laufen lässt und dann beobachtbares Verhalten hat, dass irgendwie nicht richtig ist. Aber dazwischen tausende oder Millionen von Zyklen hat, an denen nichts Falsches passiert. Und nur dort, wo der Prozessor divergiert. Und da setzt dann der Monitor ein und ist dann leichter, da Bugs zu finden. Der Monitor hat sozusagen tausende von Zyklen oder Millionen von Zyklen zwischen dem Punkt, wo er divergiert und wo wir den Fehler beobachten können. Okay, hier gibt es ein paar Beispiele, die sich von jedem Prozessor aus ein bisschen unterscheiden, je nachdem, welchen Prozessor wir anschauen. Okay, da gibt es ein Test, ob der Programmzähler für eine Instruktion, also wenn jemand eine Instruktion sagt, das ist der Programmcounter für diese Instruktion und für die nächsten, können wir auch schon sehen. Da können wir auf die nächste Instruktion gucken und dann können wir gucken, ob der nächste Programmcounter sozusagen der nächste Wert für den vorhergehenden Programmzähler ist. Und wenn das zusammenpasst, dann ist es gut. Aber vielleicht möchte der Kern die Instruktion in anderer Reihenfolge ausführen und es kann sein, dass er erst den zweiten sieht und dann den ersten sieht. Vielleicht sieht er aber auch erst den ersten und dann den zweiten. Und deshalb gibt es da verschiedene Checks, einmal zum Beispiel in die richtige Reihenfolge und einmal in der umgekehrten Reihenfolge. Es gibt verschiedene Tests, die zum Beispiel die gisterwerte Schreib- und Lesezugriffe auf Konsistenz testen und gucken, ob der Prozess am Leben ist. Also wenn ich dem Prozessor eine bestimmte Fairness Limitationen gebe, dann wird der Speicher immer wieder in bestimmten Zyklen Anzahlen zurückgegeben, der Speicherzugriff. Das ist natürlich sehr, sehr wichtig. Und das ist natürlich auch wichtig, um zu zeigen, dass der Prozessor nicht Instruktion überspringt, weil andere Tests natürlich die anderen betreffen, dass der Prozessor sowas nicht tut. Und es gibt natürlich in Haufen Konsistenzchecks, wo man am besten sich mit einer Gruppe von Leuten hin und guckt auf die Konsistenz-Tests und guckt, welche bedeuten hier in unserem Fall eigentlich gerade was, welche sind interessant, welche sollen wir verwenden. Was für Fehler kann ein Riskformal finden? Das ist eine sehr, sehr schwierige Frage. Es ist eine super schade schwierige Frage, weil es schwierig ist, eine komplette Liste zu geben. Es kann definitiv Einzelstrange Befehlsequenzen fehlen finden. Bypassing und Forwarding und Pipeline Interlocks kann es auch finden, wo Dinge umsortiert werden in eine Wart, die es nicht gehören. Also wo es Dinge einfrieren, das kann gefunden werden. Fehler zu Speicherinterfaces und Speicherlesen kann gefunden werden, aber das hängt davon ab von Dingen wie die Cashgröße, ob das geht oder nicht. Fehler, die man nicht finden kann, sind Dinge, die noch nicht mit dem risk-5-formalen Interface abgedeckt sind. Also zum Beispiel die Floating Point Arithmetic. Das ist alles auf der To-Do-Liste und da arbeiten wir aktiv dran. Und in einem Jahr wird das wahrscheinlich dabei. Und alles, was der gleichzeitig als Konkurrentenausführung mit der zusammenhängt, das ist also noch nicht in der Spezifikation drin. Also ich weiß nicht, was ich da genau testen soll, aber das Modell wird bald fertiggestellt. Also da gehen mir die Entschuldigungen aus. Die Prozessoren, die jetzt unterstützen werden, sind Pico F532, Risk-5 Rocker, das ist die berühmteste Implementation und Wax for Risk-5. Es gibt andere, die nicht in Open Source Release vom Risk-5 dabei sind. Also wenn du Unterstützung für einen Risk-5 Prozessor hinzufügen willst, dann guck im Repositorinach, guck im Chorsdirektorinach, welcher Chor deinem am ähnlichsten ist. Dann kopierst du dir dieses Direktor, dieses Verzeichnis und machst deine kleine Anzahl von Änderungen. Das sind noch ein paar Minuten übrig, um über Dinge wie Product Points, Black Boxes und andere Abstraktionen zu reden. Also diese Folie könnte einfach Abstraktionen betitelt sein. Die Idee bei Abstraktionen ist, du ein Teil von deinem Design austauscht mit einer anderen Schaltung, die weniger beschränkt ist, die das Verhalten der Originalschaltung erhält, aber das auch noch andere Dinge tut. Lehrbuchexample ist ein Design mit einem Zähler, der nur um 1 hochzählen kann und die Abstraktion kann Lummern überspringen. Man kann immer nur hochzählen, einfach monotonensteigend. Das enthält das Behalten des Originaldesigns und wenn man etwas beweisen kann, mit dem monotonen Hochzählen den Zähler beweisen kann, dann kann man die Eigenschaft auch beweisen für einen Zähler, der nur um 1 hochzählen kann. Und diese Idee der Abstraktion funktioniert sehr gut mit dem Risk5-Format und der Grund, warum das machen ist, weil das zu einfacheren Beweisen führt. Zum Beispiel guckt Überlektor einen Befehlsüberprüfer an, der überprüft, ob der Optitionsbefehl richtig ausgeführt wird. Wir gucken uns nicht das Registerfell an, was arbeitet, wir kopieren uns das und immer wenn was von dem Registerfell gelesen wird, dann wird ein zufälliger Fehler zugegeben. Das beinhaltet natürlich immer noch das Verhalten eines Kernes mit so einem Register, aber in dem Fall geht es jetzt gerade gar nicht um die Konsistenz zwischen Lesen und Schreibzugriffen. Wir können aber immer prüfen, dass die Instruktion korrekt implementiert würde. Also es ist ein leichterer Beweis. Natürlich kann man diese Abstraktion nicht für alle Beweise verwenden, weil vielleicht werden andere Beweise das sozusagen brauchen und erwarten. Aber wenn man durch die Liste von Beweisen geht und die alle unabhängig voneinander durchführt, dann kann man viele Probleme abstrahieren, in großem Teil des Prozesses abstrahieren und dann, lauter, viele kleinere, einfache Beweise haben. Abhängig davon, welche Lösungen man verwendet, sind manche ziemlich gut darin, diese Abstraktion selber schon zu machen. Das heißt, man muss sie vielleicht nicht mal von Hand dazufügen, sondern einfach zu realisieren, dass das Potenzial dieser Abstraktion da ist. Es ist sehr, sehr hilfreich, wenn man entscheidet, wie man ein großes Verfrigerationsproblem in kleinere Verfrigerationsprobleme aufteilt, weil man immer in der Lage ist, einfache Abstraktionsniveaus zu finden, die leichtere Beweise mit sich bringen. Mit einem grenzten Beweis haben wir außerdem auch die Frage, welche Grenzen werden wir nehmen. Natürlich sind weite Grenzen besser, aber natürlich haben sie auch mehr Auslöse, also es ist schwer, sie zu berechnen. Und wenn man enge Grenzen hat, na gut, dann hat man schnell Fortschritte im Beweis gemacht, aber vielleicht ist man nicht besonders, vertraut man den Beweis nicht besonders, weil das nicht so relevant ist. Also habe ich zwei Lösungen vorgeschlagen. Die erste ist, man kann dieselben Server benutzen und bestimmte Events zu überprüfen und sagen, ich möchte gerne ein Speicherleszug auf Einspeicher, schreib Instruktionen, alle Operationen ausführen und würde gerne den kürzesten Fahrt sehen, der all diese Sachen behandelt. Wenn das dann irgendwie 25 Zyklen übergeht, dann kann man 25 Zyklen überprüfen und das geht schon. Weiß man, das sind die Sachen, die da vorkommen werden. Noch wichtiger ist, wie ich denke, meistens hast du einen Prozess oder hast du schon Fehler gefunden und das ist eine sehr gute Idee, die nicht nur einfach zu fixen und sie zu vergessen, sondern eine Möglichkeit zu behalten, diesen Fehler zurückzuwerfen. Wieder einzuführen, um das Framework zu überprüfen. Wenn man schon einen Bugs hat, die eine Woche gebraucht haben oder ein Monat gebraucht haben, ist es gut, diese Bugs einfach wieder einzuführen und fest und dann damit das Verifikationsprogramm zu verifizieren, ob das diese Bugs oder ähnliche Bugs finden würde. Resultate, ich habe in praktisch jeder Implementation Bugs gefunden. Ich habe Bugs in allen drei Prozessoren gefunden. Wir haben Bugs in Spike gefunden, was die offizielle Implementation von RISC-5 in C ist und es ist mir gelungen, meine Implementation formal zu verifizieren gegen Spike. Es kam dann raus, dass es ein Programm, ein Bug in der englischen Sprache, in der Spezifikation in englischer Sprache war, das das Problem war. Zukunftliche Arbeit, Floating Point muss immer noch gemacht werden. S60-Forbit ist halb getan. Support für CSR muss gemacht werden. Support für mehr Kerne muss gemacht werden. Aber das würde ich gerne langsam machen, weil das immer... Wir weniger flexibel sind, wenn sich Sachen verändern. Und bis jetzt ist das ja alles Open Source Tools, die ich auch geschrieben habe. Also ich habe die Tools geschrieben, aber manche Leute wollen vielleicht nicht meine Open Source Tools benutzen. Die wollen die über die kommerziellen Tools benutzen. Also sollte ich auf meiner To-do-Liste diese Integration verbessern machen. Aber vielleicht... Ich kriege keine Lizenzen für diese Tools, also müssen wir mal gucken, ob das klappt. Das ist das von mir, haben wir Zeit für Fragen. Okay, wir fangen mit Fragen auf der 1 an. Wir haben Zeit für 2 Fragen. Wir starten mit Mikrofon Nummer 1 bitte. Hallo, vielen Dank für deinen Vortrag und deine Arbeit. Meine 1. Frage. Du sprachst über RISC-5-formale Schnittstellen-Börfiguration. Verkaufen die... Schicken die Hersteller dieses... Das ist eine gute Frage, danke. Dieses Interface hat nur Ausgabe-Ports. Und wenn du dieses Interface implementierst, dann solltest du nichts zu deinem Design dazufügen, was diese Output-Ports nicht... was nicht gebraucht werden, um diese Output-Ports zu erzeugen. Das kannst du, kannst du deinen Core benutzen mit dem, mit dem Interface und ohne Interface. Und dann diese Output-Ports einfach entfernen und dann einen formalen Equivalenztest laufen zu lassen mit der Version mit den Output-Ports und ohne, die du dann auf dem ASIC implementierst. Wenn Leute sagen, formale Verifikation, dann denken die anderen meistens irgendwie, wenn es verifiziert ist, dann ist es sehr exzellent. Ja, das ist natürlich exzellent. Würdest du sagen, dass es... dass es all die Fehler eines Prozesses findet? Es fängt davon ab, welchen Beweis du laufen lässt. Die meiste Arbeit, die ich mache, ist mit Begrenzten, mit Beweisen. Und damit kann man nur ein bestimmtes Vertrauen bekommen, weil man nur Fehler sieht, die nach einer bestimmten Anzahl von Zyklen aufzauchen können. Aber wenn du auch einen Vollständigenbeweis starten willst mit symbolischen Zuständen anstatt mit einem Resetzustand und dann kannst du sicherstellen, dass du tatsächlich den ganzen erreichbaren Zustandsraum erreichst und das ist eine sehr haare, sehr schwierig zu machen. Das ist kein Wochenendprojekt und einfach das formale Interface zu laufen und das dann laufen zu lassen, das kann man dann im Wochenende machen. Wir haben leider keine Zeit mehr für weitere Fragen, aber es wird Zeit sein, nach dem Vortrag dich vielleicht anzusprechen. Ja, das können wir machen und du kannst mich ja vielleicht auch dort finden, ein Assembly der offenen FPGA Hardworking Area. Vielen lieben Dank, um so viel Informationen in so wenig Zeit zu bringen. Das hast du sehr gut gemacht. Bitte helft mir, Ihnen zu entlohen, mit Dank für seinen wundervollen Vortrag.