Hallo, ich versuche die Frage mal so abstrakt wie möglich zu stellen, stelle aber auch das konkrete Problem vor, weil eh danach gefragt würde. Abstrakt: 2 Prozessoren bekommen das gleiche Signal zur gleichen Zeit und müssen es verwerten. Beide führen exakt das gleiche Programm aus, welches unveränderbar ist. Prozessor 1 läuft gepipelined, kann das Signal also nur verzögert auswerten. Die Verzögerung beträgt dabei null oder eine Instruktion. Prozessor 2 läuft immer ohne Pipeline, kann also prinzipiell jederzeit auswerten und hat damit erstmal immer 0 Instruktionen Verzögerung. Beide können nicht kommunizieren, müssen aber zur exakt gleichen Instruktion das Signal auswerten. Beide Bausteine sind aber insoweit veränderbar, das man z.b. beliebige Delays auf das Signal geben kann. Konkret: Es geht um einen Prozessor und seinen Emulator. Um einen Emulator mit exaktem Verhalten zu bekommen nehme ich den Zustand des Systems(Register, Timer, etc) nach jeder Instruktion auf und tue das gleiche vom Prozessor. Über ein Diff sehe ich ab wann es Unterschiede gibt. Das läuft soweit sehr gut, macht aber immer wieder Probleme bei Interrupts z.b. wenn ein Timer abgelaufen ist. Im Emulator liegt die Information sofort vor, im echten Prozessor hängt es davon ab wie lange der Befehl davor dauert. Dementsprechend laufen die Zustände auseinander, wenn der Interrupt nicht bei der gleichen Instruktion auftrat. Manchmal ist nach dem Interrupt Handler wieder alles gleich, aber nicht immer. Ich möchte jetzt gerne sicherstellen das immer beide zur gleichen Zeit in den Interrupt gehen. Im Idealfall trickse ich dabei nur im Emulator, es stört aber auch nicht wenn der Prozessor geändert werden muss(FPGA Softcore). Weil die absolute Zeit für den Interrupt nicht so entscheidend ist nutze ich derzeit die Lösung bei "instructionCount % 100 == 0" tatsächlich in den Interrupt zu gehen. Das löst das Problem in 99% der Fälle, aber der Jitter ist schon sehr groß. Deswegen frage ich mal in die Runde ob jemand eine bessere Lösung hat das Ganze synchron zu bekommen. Nur eins vorneweg: das Pipelineverhalten nachbauen um es immer garantiert genauso zu haben möchte ich ausdrücklich nicht. Vielleicht hat ja noch jemand eine zündende Idee. Danke und viele Grüße
FPGAzumSpass schrieb: > Nur eins vorneweg: das Pipelineverhalten nachbauen um es immer > garantiert genauso zu haben möchte ich ausdrücklich nicht. Wenn das Ziel ist, es garantiert genauso zu haben, kannst du nicht die aus naheliegenden logischen Gründen einzige Möglichkeit ausschliessen, dies zu erreichen... Formales logisches Denken ist nicht deine Stärke, oder?
Nein, das ist nicht das Ziel, habe ich vielleicht schlecht geschrieben. Eigentlich bin ich auf der Suche nach Fehlern, z.b. Instruktionen die sich anders Verhalten. Weil ich das aber auf diese sehr komfortable Weise nur herausfinden kann, wenn beide sich zeitweise(!) nahezu gleich Verhalten brauche ich diese Krücke. Hinterher, wenn alles läuft, fliegt das wieder raus. Eben deshalb ist es den Aufwand erst recht nicht wert beides exakt gleich zu machen. Das erkannt man z.b. auch dran, das es mir egal ist ob der Interrupt etwas später oder früher kommt. Wenn der Nachbau exakt gleich sein müsste wäre das entscheidend, ist es aber (zum Glück) nicht.
Wenn Du das Signal verzögern kannst, dann verzögern es doch um 0 oder 1 Takt.
A. S. schrieb: > Wenn Du das Signal verzögern kannst, dann verzögern es doch um 0 oder 1 > Takt. Falls du es noch nicht bemerkt hast: genau das Nichtwissen, ob es um 0 oder 1 Takt zu verzögern ist, ist sein Problem. Ausserdem will er auch nicht die einzige Lösung, die das sicherstellen könnte. Kurzfassung: wohl ein Troll.
Ich wüsste ja schon gerne, woher die Vorstellung kommt, dass Pipelining eine Reaktion um exakt einen Takt verzögern würde. Grundprinzip von Rechnerarchitekturen aus dem Lehrbuch? Die Realität sieht anders aus. Weshalb sich die Anforderung nicht von der konkreten Implementierung des Prozessors trennen lässt.
A. K. schrieb: > Ich wüsste ja schon gerne, woher die Vorstellung kommt, dass Pipelining > eine Reaktion um exakt einen Takt verzögern würde. Ich habe den Softcore halt genau so implementiert: der Prozessor rechnet an Instruction A und die dauert x Takte. Diese x Takte werden auf den Timer addiert wenn die Instruction fertig ist. Dem Timer fehlen noch y Takte bis zum Interrupt. Wenn x >= y, dann gibt es einen Interrupt request. Dieser wirkt in der Pipeline im Execution Teil, davor gibt es noch Instruction Fetch und Decode. Wenn nun Fetch und Decode schneller sind als der Timer das x aus der letzten Instruktion auf seinen Zählerstand addiert hat und den IRQ request erzeugt hat, dann gibt es eine Instruktion Verzögerung, weil der execution Teil schon weiterrechnen kann. Dies betrifft vor allem den Fall, das die Pipeline schon gefüllt ist. Dauern Fetch und Decode länger (z.b. Fetch von langsamen externem Ram), dann gibt es keinen Takt Verzögerung, weil Execution noch nicht rechnen kann und demzufolge den IRQ request bekommt, bevor die nächste Instruktion ansteht. Spätestens hier sollte klar sein, warum ich das nicht emulieren will: es müsste alles beachten, z.b. auch Ram-Refresh, Cache Hit/Miss usw. Weil das exakte Timing aber in der Anwendung unwichtig ist wäre der Aufwand am Ende nutzlos. Bis jetzt habe ich eben nur 2 Lösungen gefunden: - einen Instruction Counter mitlaufen lassen und einen IRQ request nur z.b. jeden n-ten Takt durchzulassen. Das klappt in den allermeisten Fällen, sorgt aber, je besser es funktionieren soll, für mehr "IRQ-Jitter" - den Prozessor prinzipiell nach jeder Instruktion solange mit der Execution warten lassen, bis der Interrupt auf jeden Fall da wäre. Das macht ihn aber viel langsamer. Ich dachte vielleicht gibt es jemanden der noch mehr Ideen dazu hat. c-hater schrieb: > Ausserdem will er auch > nicht die einzige Lösung, die das sicherstellen könnte Wo habe ich das geschrieben? Ich habe nirgends eine 100%ige Lösung erwartet, sondern lediglich gefragt ob jemandem etwas einfällt das etwas besser ist. Das ich schon 2 Lösungen (genau genommen 3 mit der exakten) selbst vorgelegt habe zeigt wohl deutlich das es mehrere Varianten. Warum soll es also nicht noch andere geben? Weil sie mir nicht einfallen? Weil sie dir nicht einfallen? Also so von mir selbst überzeugt bin ich nun nicht, das ich jeden Fall den es geben könnte wissen kann. Genau deshalb schreibe ich hier. Wenn du das ins Lächerliche ziehen willst, weil du Dinge behauptest die so nicht sind, ist das dein Ding. Wenn dir nicht Besseres einfällt, dann musst du ja nicht schreiben.
Könnte man vielleicht das Pipelineverhalten ändern? Die Sparc(?) CPUs haben glaub ich alle Register doppelt. Einmal für die normale Ausführung und einmal für Interrupts. Dadurch kann man da sehr schnell in Interrupts wechseln. Kein "Push & Pop" nötig... Vielleicht könnte man so ähnlich auch zwei Befehlspipelines haben und mitten in einem Befehl in den Interrupt wechseln und danach mit dem Befehl weiter machen als ob nichts gewesen wäre? Klingt schon fasst so als ob man dann einen zweiten (Co-)Prozessor für Interrupts hätte... Der Aufwand das ans Laufen zu bekommen ist wahrscheinlich so groß das es sich nicht lohnt zu überlegen ob das funktionieren könnte ;-)
Das wäre so ähnlich tatsächlich denkbar: ich könnte alle Register und Zustände vom Ende der vorigen Instruktion speichern und diese wieder herstellen wenn ein Interrupt verspätet reinkommt. Der Aufwand ist halt sehr groß dafür, sowohl Arbeitstechnisch, als auch an Registern/Logik im Prozessor. Gerade eine solch große Änderung im Prozessor selbst (der wichtigere Teil) wollte ich möglichst vermeiden. Trotzdem vielen Dank fürs Überlegen. Genau solche Denkanstöße suche ich noch.
Vielleicht wäre es möglich, eine Wait-Leitung wie beim Z80 einzuführen, um die Abläufe zu synchronisieren.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.