Wie hilft die Harvard-Architektur?

12

Ich las über Arduino und die AVR-Architektur und blieb an dem Punkt hängen, an dem die Einführung der Harvard-Architektur in den AVR das Abwürgen oder Sprudeln von Pipelines löst ermöglicht das Laden eines Programms ohne Bediener. Aber wie kann das oben genannte Problem gelöst werden?

Ayush
quelle
2
Dies ist eine kleine Vermutung, daher werde ich keine Antwort veröffentlichen, aber ich vermute, die Harvard-Architektur hilft, da es nicht möglich ist, den Code durch eine vorherige Anweisung in der Pipeline selbst zu ändern.
PeterJ
1
Ich bin mir nicht sicher, ob ich dich bekomme. Willst du damit sagen, dass der Befehl, nachdem er "geholt" wurde, nicht mehr geändert oder zurückgeworfen werden kann?
Ayush
1
Ja, das ist richtig, für Nicht-Harvard-Benutzer, da sich der Code von selbst ändern kann, besteht die Möglichkeit, dass der vorherige Befehl den folgenden Befehl ändert. Aber warte eine Weile, jemand wird wahrscheinlich eine eindeutigere und klarere Antwort haben.
PeterJ

Antworten:

9

Die Harvard-Architektur, die übrigens lange vor der Erfindung von AVRs verwendet wurde, verfügt in der Tat über separate Adressräume für den Programmspeicher und den Datenspeicher. Dies bringt für die Partei die Fähigkeit mit sich, die Schaltung so zu gestalten, dass ein separater Bus und eine Steuerschaltung verwendet werden können, um den Informationsfluss vom Programmspeicher und den Informationsfluss zum Datenspeicher zu handhaben. Durch die Verwendung der getrennten Busse ist es möglich, dass der Programmabruf und die Programmausführung ohne Unterbrechung einer gelegentlichen Datenübertragung in den Datenspeicher fortgesetzt werden. Beispielsweise kann in der einfachsten Version der Architektur die Programmabrufeinheit damit beschäftigt sein, den nächsten Befehl in der Programmsequenz parallel zu einer Datenübertragungsoperation abzurufen, die Teil des vorherigen Programmbefehls gewesen sein kann.

Auf dieser einfachsten Ebene ist die Harvard-Architektur dahingehend eingeschränkt, dass es im Allgemeinen nicht möglich ist, Programmcode in den Datenspeicher zu schreiben und von dort ausführen zu lassen.

Es gibt viele Variationen und Komplexitäten, die zu dieser einfachsten Form der von mir beschriebenen Architektur hinzugefügt werden können. Eine übliche Ergänzung besteht darin, dem Programminformationsbus eine Befehlszwischenspeicherung hinzuzufügen, die es der Befehlsausführungseinheit ermöglicht, schneller auf den nächsten Programmschritt zuzugreifen, ohne jedes Mal in einen langsameren Speicher gehen zu müssen, um den Programmschritt abzurufen, wenn dies erforderlich ist.

Michael Karas
quelle
Vielen Dank ... hat mir wirklich geholfen, es zu bekommen, aber noch eine Sache ... können wir nicht verschiedene Busse haben, aber den gleichen Speicher und die gleiche Arbeit zur gleichen Zeit?
Ayush
@ Ayush - Wenn zwei Busse auf den gleichen Speicherplatz fahren würden, müssten immer noch zwei Speichertransaktionsanforderungen, die gleichzeitig im Speicher eintreffen, um Speicherzugriff kämpfen. Man muss warten, bis der andere fertig ist !! Nun, da dies gesagt wurde, haben einige Entwickler 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 auf den Speicher und (siehe nächster Kommentar)
Michael Karas
(Fortsetzung von vorherigem Kommentar) Wenn der zweite Bus mit den geraden Zugriffsschlitzen des Speichers synchronisiert ist, können beide Busse ohne Speicherzugriffskonflikt mit Geschwindigkeit weiterarbeiten.
Michael Karas
@MichaelKaras: Das könnte man machen. Andererseits ist in den meisten Fällen die Speichergeschwindigkeit der primäre Begrenzungsfaktor für die Gesamtsystemgeschwindigkeit. Wenn man einen Speicher hätte, der doppelt so schnell laufen könnte, wie es nur für Daten oder nur für Code erforderlich wäre, würde das Aufteilen des Speichersystems in jeweils einen für Daten und Code die Dinge doppelt so schnell laufen lassen.
Supercat
4

Einige Anmerkungen zusätzlich zu Michaels Antwort:

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

2) Das Problem, das durch die Harvard-Architektur gelöst wird, ist ein Buskonflikt: Bei einem System, bei dem der Codespeicher die Anweisungen gerade noch schnell genug bereitstellen kann, um die CPU auf Hochtouren zu halten, verlangsamt die zusätzliche Belastung durch Datenabrufe / -speicher 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. Häufig werden Harvarding und Caching in interessanten Kombinationen eingesetzt.

Harvard benutzt zwei Busse. Es gibt keinen inhärenten Grund, sich an zwei zu halten. In ganz besonderen Fällen werden mehr als zwei verwendet, hauptsächlich in DSPs (Digital Signal Processors).

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

Wouter van Ooijen
quelle
4
Eigentlich eine „reine“ Harvard - Architektur nicht benötigt separate Speicher (Adressräume) für Befehle und Daten. Da dies jedoch verhindert, dass ein Computer von selbst startet, implementieren viele Computer eine "modifizierte" Harvard-Architektur, in der das Schreiben in den Befehlsspeicher zulässig ist.
Dave Tweed
Memory Banking hilft nur, wenn zwei (oder mehr) Busse zwischen der CPU und jeder der Speicherbänke vorhanden sind.
Dave Tweed
@ Dave 2: Banking hilft unter bestimmten Umständen, zum Beispiel, wenn das Speicher-Timing das Problem ist UND der Bus zum Speicher nicht blockiert (mehrere Transaktionen können ausstehen).
Wouter van Ooijen
@ Dave1: kannst du eine referenz geben?
Wouter van Ooijen
Wikipedia , auch die Princeton University (die eigentlich nur eine Kopie der Wikipedia-Seite ist). Die meisten Ein-Chip-Mikrocontroller sind Harvard-Architekturen, und in vielen Datenblättern wird diskutiert, wie durch die Bereitstellung eines Mechanismus zum Selbstschreiben des Code-Flash-Speichers eine modifizierte Harvard-Architektur entsteht.
Dave Tweed
2

Mit einer reinen Harvard-Architektur kann ein Computer mit einer bestimmten Komplexität im Allgemeinen schneller ausgeführt werden als mit einer 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 zwingen, um auf beide Speicherbereiche zuzugreifen, können solche Vorteile weitgehend zunichte gemacht werden.

Eine "reine" Harvard-Architektur beschränkt sich darauf, Code auszuführen, der durch einen anderen Mechanismus als den Prozessor, der den Code ausführt, in den Speicher gestellt wird. Dies schränkt den Nutzen solcher Architekturen für Geräte ein, deren Zweck nicht vom Werk festgelegt wurde (oder für Geräte mit speziellen Programmiergeräten). Zwei Ansätze können verwendet werden, um dieses Problem zu beheben:

Einige Systeme verfügen über separate Code- und Speicherbereiche, bieten jedoch spezielle Hardware, die aufgefordert werden kann, kurz den Codebus zu übernehmen, eine Operation auszuführen und die Steuerung an die CPU zurückzugeben, sobald eine solche Operation abgeschlossen ist. Einige solcher Systeme erfordern ein ziemlich ausgefeiltes Protokoll, um solche Operationen auszuführen, andere haben spezielle Anweisungen, um eine solche Aufgabe auszuführen, und einige überwachen sogar bestimmte "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 sie immer noch als semantisch anders als der Datenraum erkannt. '

Ein alternativer Ansatz, der in einigen High-End-Systemen verwendet wird, besteht darin, eine Steuerung mit zwei Speicherbussen zu haben, einen für Code und einen für Daten, die beide mit einer Speicherarbitrierungseinheit verbunden sind. Diese Einheit wiederum ist über jeweils einen separaten Speicherbus mit verschiedenen Speichersubsystemen verbunden. 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, muss einer der beiden warten.

Auf Systemen, die diesen Ansatz verwenden, können nicht leistungskritische Teile eines Programms die Grenzen zwischen Speichersubsystemen einfach ignorieren. Wenn sich der Code und die Daten zufällig im selben 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, auf den es wirklich ankommt, und er wird nur auf einen kleinen Teil der vom System gespeicherten Daten angewendet. Wenn ein System mit 16 KB RAM in zwei 8-KB-Partitionen unterteilt ist, kann mithilfe von Linkeranweisungen sichergestellt werden, dass sich der leistungskritische Code am Anfang des gesamten Speicherbereichs befindet und die leistungskritischen Daten sich in der Nähe des befinden Ende. Wenn die Gesamtcodegröße auf z. B. 9 KB ansteigt, Code innerhalb der letzten 1 KB wird langsamer ausgeführt als an anderer Stelle platzierter Code, dieser Code ist jedoch nicht leistungskritisch. Wenn der Code beispielsweise nur 6 KB groß wäre, die Daten jedoch auf 9 KB anwachsen würden, wäre der Zugriff auf die niedrigsten 1 KB langsam. Wenn sich die leistungskritischen Daten jedoch an einer anderen Stelle befinden würden, wäre dies kein Problem.

Es ist zu beachten, dass, während die Leistung optimal wäre, wenn der Code unter 8 K und die Daten unter 8 K wären, der oben erwähnte Entwurf des Speichersystems 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önnen die Daten auf 14 KB anwachsen. Viel vielseitiger als ein 8K-Bereich nur für Code und ein 8K-Bereich nur für Daten.

Superkatze
quelle
1

Ein Aspekt, der nicht diskutiert wurde, ist, dass für kleine Mikrocontroller, die typischerweise nur einen 16-Bit-Adressbus haben, eine Harvard-Architektur den Adressraum effektiv verdoppelt (oder verdreifacht). Sie können 64 KByte Code, 64 KByte RAM und 64 KByte speicherzugeordnete E / A haben (wenn das System speicherzugeordnete E / A anstelle von Portnummern verwendet, trennt letzteres die E / A-Adressierung bereits vom Code & RAM-Speicher).

Andernfalls müssen Sie den Code, den Arbeitsspeicher und die optionale E / A-Adresse innerhalb desselben 64-KB-Adressraums komprimieren.

Tcrosley
quelle