Wie hilft die Harvard-Architektur?

Ich habe über Arduino und die AVR-Architektur gelesen und bin an dem Punkt hängengeblieben, wie das Blockieren oder Blubbern von Pipelines durch die Einführung der Harvard-Architektur im AVR gelöst wird. Ich meine, Harvard bietet nur unterschiedliche Speicherorte für Datenspeicher und Programmspeicher an ermöglicht das Laden von Programmen ohne Bediener. Aber wie hilft es, das obige Problem zu lösen?

Dies ist eine kleine Vermutung, daher werde ich nicht als Antwort posten, aber ich denke, die Harvard-Architektur hilft, da es nicht die Möglichkeit gibt, den Code durch eine vorherige Anweisung in der Pipeline selbst zu modifizieren.
Ich bin mir nicht sicher, ob ich dich verstehe ... willst du damit sagen, dass die Anweisung, sobald sie "abgeholt" wurde, nicht mehr geändert oder zurückgeworfen werden kann?
Ja, das ist richtig, für Nicht-Harvard, da sich der Code selbst ändern kann, besteht die Möglichkeit, dass die vorherige Anweisung die folgende Anweisung ändert. Aber warten Sie eine Weile, jemand wird wahrscheinlich eine definitivere und klarere Antwort haben.

Antworten (4)

Die Harvard-Architektur, die übrigens lange vor der Erfindung von AVRs verwendet wurde, hat tatsächlich getrennte Adressräume für den Programmspeicher und für den Datenspeicher. Was dies der Partei bringt, ist die Möglichkeit, die Schaltung so zu gestalten, dass ein separater Bus und eine separate Steuerschaltung verwendet werden können, um den Informationsfluss vom Programmspeicher und den Informationsfluss zum Datenspeicher zu handhaben. Die Verwendung der getrennten Busse bedeutet, dass es möglich ist, das Abrufen und Ausführen des Programms ohne Unterbrechung durch eine gelegentliche Datenübertragung zum Datenspeicher fortzusetzen. Beispielsweise kann in der einfachsten Version der Architektur die Programmabrufeinheit damit beschäftigt sein, die nächste Anweisung in der Programmsequenz parallel zu einer Datenübertragungsoperation abzurufen, die Teil der vorherigen Programmanweisung gewesen sein kann.

Auf dieser einfachsten Ebene hat die Harvard-Architektur insofern eine Einschränkung, als es generell nicht möglich ist, Programmcode in den Datenspeicher zu legen und von dort aus auszuführen.

Es gibt viele Variationen und Komplexitäten, die dieser einfachsten Form der Architektur, die ich beschrieben habe, hinzugefügt werden können. Eine übliche Ergänzung ist das Hinzufügen von Befehls-Caching zum Programminformationsbus, das der Befehlsausführungseinheit einen schnelleren Zugriff auf den nächsten Programmschritt ermöglicht, ohne dass sie zu einem langsameren Speicher gehen muss, um den Programmschritt jedes Mal, wenn er erforderlich ist, abzurufen.

vielen Dank .... hat mir wirklich geholfen, es zu bekommen, aber nur eine Sache noch ... können wir nicht verschiedene Busse haben, aber denselben Speicher und gleichzeitig arbeiten?
@Ayush - Wenn Sie zwei Busse hätten, die zum selben Speicherplatz führen, müssten zwei Speichertransaktionsanforderungen, die gleichzeitig im Speicher ankommen, immer noch um den Speicherzugriff kämpfen. Einer muss warten, bis der andere fertig ist !! Nachdem dies gesagt wurde, haben einige Designer dieses Problem "gelöst", indem sie den Speicher so entworfen haben, dass er mit der doppelten normalen Geschwindigkeit arbeitet, und dann einen Bus abwechselnd mit Zugriffen vom anderen Bus auf den Speicher zugreifen lassen. Das heißt, die Dinge sind so konzipiert, dass der erste Bus immer mit den ungeraden Zugriffsschlitzen zum Speicher synchronisiert wird und der (Fortsetzung nächster Kommentar)
(Fortsetzung vom vorherigen Kommentar) zweiter Bus mit den geraden Zugriffsschlitzen des Speichers synchronisiert, dann können beide Busse mit Geschwindigkeit ohne Speicherzugriffskonflikte arbeiten.
@MichaelKaras: Das könnte man machen. Andererseits ist in den meisten Fällen der Hauptbegrenzungsfaktor für die Gesamtsystemgeschwindigkeit die Speichergeschwindigkeit. Wenn man einen Speicher hätte, der doppelt so schnell laufen könnte, wie er nur für Daten oder nur für Code benötigt würde, würde die Aufteilung des Speichersystems in jeweils ein Speichersystem für Daten und Code es ermöglichen, dass die Dinge doppelt so schnell gehen.

Einige Anmerkungen zusätzlich zu Michaels Antwort:

1) Die Harvard-Architektur erfordert nicht, dass es zwei getrennte Bereiche für Daten und Code gibt, sondern dass sie (meistens) über zwei verschiedene Busse abgerufen werden .

2) Das Problem, das durch die Harvard-Architektur gelöst wird, ist Buskonkurrenz: Bei einem System, bei dem der Codespeicher die Anweisungen gerade schnell genug bereitstellen kann, um die CPU mit voller Geschwindigkeit laufen zu lassen, verlangsamt die zusätzliche Belastung durch das Abrufen/Speichern von Daten die CPU Nieder. Dieses Problem wird durch eine Hardvard-Architektur gelöst: ein Speicher, der (etwas) zu langsam für die Geschwindigkeit der CPU ist.

Beachten Sie, dass Caching eine weitere Möglichkeit ist, dieses Problem zu lösen. Oft werden Harvarding und Caching in interessanten Kombinationen eingesetzt.

Harvard benutzt zwei Busse. Es gibt keinen grundsätzlichen Grund, bei zwei zu bleiben, in sehr speziellen Fällen werden mehr als zwei verwendet, hauptsächlich in DSPs (Digital Signal Processors).

Memory Banking (im Sinne der Verteilung von Speicherzugriffen auf verschiedene Chipsätze) kann als eine Art Harvarding innerhalb des Speichersystems selbst angesehen werden, das nicht auf der Daten/Code-Unterscheidung basiert, sondern auf bestimmten Bits der Adresse.

Tatsächlich erfordert eine "reine" Harvard-Architektur getrennte Speicher (Adressräume) für Anweisungen und Daten. Da dies jedoch einen Computer daran hindert, sich selbst zu booten, implementieren viele Maschinen eine "modifizierte" Harvard-Architektur, in der Schreibvorgänge in den Befehlsspeicher erlaubt sind.
Memory Banking hilft nur, wenn zwei (oder mehr) Busse zwischen der CPU und jeder der Speicherbänke vorhanden sind.
@Dave 2: Banking hilft unter bestimmten Umständen, zum Beispiel, wenn das Problem das Speichertiming ist UND der Bus zum Speicher nicht blockiert (mehrere Transaktionen können ausstehend sein).
@Dave1: kannst du eine Referenz geben?
Wikipedia , auch Princeton University (was wirklich nur eine Kopie der Wikipedia-Seite ist). Außerdem sind die meisten Einzelchip-Mikrocontroller Harvard-Architektur, und viele Datenblätter diskutieren tatsächlich, wie die Bereitstellung eines Mechanismus zum Selbstschreiben des Code-Flash-Speichers eine modifizierte Harvard-Architektur schafft.
Memory Banking mit mehreren ausstehenden Transaktionen kann die Bandbreite für einen Speicher mit hoher Latenz verbessern, verbirgt aber nicht die Tatsache, dass Befehls- und Datenzugriffe um denselben Bus konkurrieren müssen. Es „eine Art Harvard“ zu nennen, trübt nur das Wasser, anstatt etwas klarer zu machen. Die Harvard-Architektur nutzt eine bestimmte Art von Parallelität aus, aber Sie können nicht alle Formen der Parallelität "Harvarding" nennen.
@DaveTweed: Wenn eine Maschine einen Vierphasentakt verwendete, bei dem Phase 1 eine Befehlsadresse ausgab, die von einer externen Schaltung zwischengespeichert wurde, Phase 2 eine Datenadresse zwischenspeicherte, Phase 3 einen Befehl las und Phase 4 ein Byte las oder schrieb angegebene Adresse, würde ich die gemeinsame Nutzung derselben Bus-Pins nicht als Ausschluss des Systems als "Harvard-Architektur" betrachten, wenn der Multiplex-Bus auf unterschiedliche Adress-/Datenbusse erweitert würde und es eine starre Unterteilung gäbe, die Phase 1 immer ist Codeadresse, Phase 2 ist immer Datenadresse usw.
@supercat: Ich bin mir wirklich nicht sicher, worauf Sie hinauswollen. Bei der Architektur von Harvard vs. von Neumann geht es nicht um das Bus-Timing, sondern darum, separate Speicherplätze für I und D zu haben. Sogar der niedrige 8051 teilt sich die gleichen Pins für beide Zugriffsarten, aber er hat einen zusätzlichen Pin, der anzeigt, welcher Speicherplatz ist auf die in einem bestimmten Zyklus zugegriffen wird.
@DaveTweed: Der Begriff "Harvard Architecture" hat Hardware- und Softwareaspekte; Für den Hardwareaspekt würde ich sagen, dass ein definierendes Merkmal darin besteht, dass Datenabrufe durchgeführt werden können, ohne Codeabrufe zu verzögern. Auf dem 8x31 bewirkt der MOVX-Befehl, dass der Bus, der normalerweise für Codeabrufe verwendet wird, mit der Verarbeitung des Datenabrufs verbunden wird, sodass ich in Bezug auf MOVX den 8x51 nicht als Harvard-Architektur betrachten würde. Der primäre Datenraum des 8x51 ist jedoch ein internes RAM, auf das unabhängig vom Codebus zugegriffen werden kann.

Eine reine Harvard-Architektur ermöglicht im Allgemeinen, dass ein Computer mit einem bestimmten Komplexitätsgrad schneller läuft als eine Von-Neuman-Architektur, vorausgesetzt, dass keine Ressourcen zwischen dem Code und den Datenspeichern geteilt werden müssen. Wenn Pinbelegungsbeschränkungen oder andere Faktoren die Verwendung eines Busses für den Zugriff auf beide Speicherräume erzwingen, werden solche Vorteile leicht zunichte gemacht.

Eine "reine" Harvard-Architektur ist auf die Ausführung von Code beschränkt, der von einem anderen Mechanismus als dem Prozessor, der den Code ausführt, in den Speicher gestellt wird. Dies schränkt die Nützlichkeit solcher Architekturen für Geräte ein, deren Zweck nicht von der Fabrik (oder jemandem mit spezialisierter Programmierausrüstung) festgelegt wird. Zwei Ansätze können verwendet werden, um dieses Problem zu lindern:

Einige Systeme haben separate Code- und Speicherbereiche, stellen aber spezielle Hardware bereit, die aufgefordert werden kann, kurzzeitig den Codebus zu übernehmen, einige Operationen durchzuführen und die Steuerung an die CPU zurückzugeben, sobald eine solche Operation abgeschlossen ist. Einige dieser Systeme erfordern ein ziemlich ausgefeiltes Protokoll, um solche Operationen auszuführen, einige haben spezielle Anweisungen, um eine solche Aufgabe auszuführen, und einige wenige suchen sogar nach bestimmten "Datenspeicher" -Adressen und lösen die Übernahme/Freigabe aus, wenn versucht wird, auf sie zuzugreifen . Ein Schlüsselaspekt solcher Systeme ist, dass es explizit definierte Speicherbereiche für „Code“ und „Daten“ gibt; selbst wenn es der CPU möglich ist, "Code"-Raum zu lesen und zu schreiben, wird er immer noch als semantisch verschieden vom Datenraum erkannt.'

Ein alternativer Ansatz, der in einigen High-End-Systemen verwendet wird, besteht darin, einen Controller mit zwei Speicherbussen zu haben, einen für Code und einen für Daten, die beide mit einer Speicherzuteilungseinheit verbunden sind. Diese Einheit wiederum ist mit verschiedenen Speichersubsystemen verbunden, wobei für jedes ein separater Speicherbus verwendet wird. Ein Codezugriff auf ein Speichersubsystem kann gleichzeitig mit einem Datenzugriff auf ein anderes verarbeitet werden; Nur wenn Code und Daten versuchen, gleichzeitig auf dasselbe Subsystem zuzugreifen, müssen beide warten.

Auf Systemen, die diesen Ansatz verwenden, können nicht leistungskritische Teile eines Programms einfach die Grenzen zwischen Speichersubsystemen ignorieren. Wenn sich der Code und die Daten zufällig in demselben Speichersubsystem befinden, laufen die Dinge nicht so schnell wie in separaten Subsystemen, aber für viele Teile eines typischen Programms spielt das keine Rolle. In einem typischen System gibt es einen kleinen Teil des Codes, bei dem die Leistung wirklich eine Rolle spielt, und er arbeitet nur mit einem kleinen Teil der vom System gespeicherten Daten. Wenn man ein System mit 16 KB RAM hätte, das in zwei 8-KB-Partitionen unterteilt ist, könnte man Linker-Anweisungen verwenden, um sicherzustellen, dass sich der leistungskritische Code in der Nähe des Anfangs des gesamten Speicherplatzes befindet und die leistungskritischen Daten in der Nähe des Ende. Wenn die Gesamtcodegröße auf z. B. 9K anwächst, Code innerhalb der letzten 1 KB würde langsamer ausgeführt als Code, der an anderer Stelle platziert wird, aber dieser Code wäre nicht leistungskritisch. Wenn der Code beispielsweise nur 6 KB groß wäre, die Daten aber auf 9 KB anwachsen, wäre der Zugriff auf die niedrigsten 1 KB an Daten langsam, aber wenn sich die leistungskritischen Daten an anderer Stelle befinden, wäre das kein Problem.

Beachten Sie, dass die Leistung zwar optimal wäre, wenn der Code unter 8 KB und die Daten unter 8 KB wären, das oben erwähnte Speichersystemdesign jedoch keine strikte Aufteilung zwischen Code- und Datenraum auferlegen würde. Wenn ein Programm nur 1 KB Daten benötigt, kann der Code auf 15 KB anwachsen. Wenn nur 2 KB Code benötigt werden, könnten die Daten auf 14 KB anwachsen. Viel vielseitiger als einen 8K-Bereich nur für Code und einen 8K-Bereich nur für Daten.

Ein Aspekt, der nicht diskutiert wurde, ist, dass für kleine Mikrocontroller, typischerweise mit nur einem 16-Bit-Adressbus, eine Harvard-Architektur den Adressraum effektiv verdoppelt (oder verdreifacht). Sie können 64 KB Code, 64 KB RAM und 64 KB speicherabgebildete E/A haben (wenn das System speicherabgebildete E/A anstelle von Portnummern verwendet, wobei letztere bereits die E/A-Adressierung vom Code & trennen RAM-Speicherplätze).

Andernfalls müssen Sie den Code, den RAM und optional die E/A-Adresse alle in denselben 64-KB-Adressraum packen.