Forum: Mikrocontroller und Digitale Elektronik Synchronisierung von 2 Prozessoren


von FPGAzumSpass (Gast)


Lesenswert?

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

von c-hater (Gast)


Lesenswert?

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?

von Robert P. (fpgazumspass) Benutzerseite


Lesenswert?

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.

von A. S. (Gast)


Lesenswert?

Wenn Du das Signal verzögern kannst, dann verzögern es doch um 0 oder 1 
Takt.

von c-hater (Gast)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Robert P. (fpgazumspass) Benutzerseite


Lesenswert?

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.

von Tom B. (botas)


Lesenswert?

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 ;-)

von Robert P. (fpgazumspass) Benutzerseite


Lesenswert?

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.

von Christoph M. (mchris)


Lesenswert?

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
Noch kein Account? Hier anmelden.