Ich baue eine einfache 16-Bit-CPU in Logisim und habe die ALU bereit und die Opcodes, die ich haben möchte. Nun fällt es mir wirklich schwer, die richtige Codierung für die Befehle zu finden, damit die verschiedenen Teilschaltungen (z. B. Logik, Arithmetik) nicht alle Steuerleitungen (die die Codierung aufbauen) als Eingang benötigen, sondern so wenige wie möglich. Gibt es Strategien oder Methoden, die bei einem effizienten Opcode-Design helfen?
thx im vorraus
Ich denke, es ist ein guter Ansatz, einige andere Befehlssätze zu studieren.
Ein kleiner wäre der MSP430 von TI, es ist ein 16-Bit-Prozessor mit etwa 22 Befehlen.
http://www.physics.mcmaster.ca/phys3b06/MSP430/MSP430_Instruction_Set_Summary.pdf
Sie können sich auch die Atmel-AVRs ansehen, die auch einen recht kleinen Befehlssatz haben.
In einem kleinen Projekt von mir habe ich versucht, einen einfachen 32-Bit-Prozessor in VHDL mit einem kleinen Befehlssatz (14 Befehle) zu entwickeln:
Aufgrund meiner derzeitigen Freizeit ist es noch nicht ganz fertig. Die Anweisungen sind implementiert, aber zwei sind nicht getestet und möglicherweise fehlen einige Status-Flags.
Studieren (aber nicht replizieren) Sie den ARM-Ansatz für die Anweisungscodierung. Es ist stark präfixorientiert (wie der von Dzarda empfohlene Huffman-Baum-Ansatz) und sehr einheitlich in Bezug darauf, wo sich der Registerauswahlteil der Anweisung befindet.
Der einfallslose, aber zuverlässige Ansatz besteht darin, alle vorhandenen Steuersignale aufzuzählen , die wahrscheinlich mehr als 16 Bit umfassen, und dann zu versuchen, eine Logikminimierung im Karnaugh-Map-Stil durchzuführen.
Einmal habe ich versucht, in Logisim eine 4-Bit-CPU mit einem Kern mit 8-Bit-Befehlslänge zu erstellen. Es endete mit einer einfachen Zustandsmaschine, wirklich mehr als einer CPU.
Zufällige Dinge zu suchen
Ausgezeichnetes Video auf Computerphile über Huffman-Bäume:
Die ISA, die ich für den Unterricht geschrieben habe, hatte einmal einen 4-Bit-Operationscode wie folgt: 1XXX ALU instructions 01XX jump, jump register, call etc 001X branch not equal, branch equal zero 000X 0 - load, 1 - store
Anstatt der optimalste zu sein, ist dies einer der einfacheren Stile zum Konstruieren / Entwerfen von Gattern, da das Eingangssignal eines einzelnen Bits vollständig steuern kann, welcher logische Pfad genommen wird. Alternativ können Sie Ihre am häufigsten verwendeten Symbole Huffman- codieren und mit Nullen auffüllen, um einen Operationscode mit fester Länge zu erhalten.
Eine Sache, die Sie berücksichtigen müssen, ist, ob Sie irgendeine Form von Mehrwort-Anweisungen zulassen oder alles, was wie eine Mehrwort-Anweisung "fungieren" kann; Wenn Sie dies tun, sollten Sie dann überlegen, ob Sie zusätzliche Anweisungswörter nach der Hauptanweisung verwenden oder Wörter voranstellen möchten. Das Zulassen von Präfixen und Folgewörtern kann die Komplexität der Unterbrechungsbehandlung erhöhen, aber es kann die Notwendigkeit vermeiden, selten verwendete Anweisungen in denselben Opcode-Bereich wie häufig verwendete einzufügen.
Wenn Befehle im Zyklus abgerufen werden, bevor sie ausgeführt werden, könnte man einen "bedingten Verzweigungs"-Befehl haben, der entweder bewirkt, dass das nächste Befehlswort übersprungen wird, oder dessen Inhalt direkt in den Programmzähler übertragen wird; Ein solches Design könnte die Interrupt-Sequenzierung etwas komplexer machen, aber es könnte die Notwendigkeit verringern, einen großen Teil des Opcode-Speicherplatzes für "Verzweigungs-", "Sprung"- und "Aufruf"-Befehle zu verwenden, während es einen viel größeren Bereich von Verzweigungsbedingungen zulässt als sonst möglich wäre. Da eine ausgeführte Verzweigung im Allgemeinen einen toten Zyklus nach der Ausführung des Befehls selbst erfordert, unabhängig davon, woher die Adresse stammt, kostet es keine zusätzlichen Kosten, wenn die Adresse aus dem folgenden Wort stammt, das abgerufen wurde, aber nicht ausgeführt wird Zeit.
Auch wenn das Verschieben der Zieladresse aus den Verzweigungsbefehlen den Opcode-Platz, den sie verschlingen, verringert, ist ein 16-Bit-Opcode-Format immer noch ziemlich eng. Die Verwendung von Präfixanweisungen kann dabei helfen. Wenn man beispielsweise 32 Register haben möchte, würde die unabhängige Angabe jedes Registers als Quelle1, Quelle2 und Ziel 15 Bits im Opcode erfordern, was eine satte Gesamtzahl von zwei Anweisungen ermöglicht. Nicht sehr nützlich. Andererseits wäre es schön, jedes der 32 Register für jeden der drei Operanden verwenden zu können. Man könnte die beiden Ziele ausgleichen, indem jede ALU-Operation, der kein Präfix vorausgeht, acht Bits verwendet, um zwei Eins-aus-sechzehn-Registerauswahlen zu treffen, aber eine ALU-Operation, die unmittelbar auf ein Präfix folgt, einige Bits im Präfix verwendet mit acht aus der folgenden Anweisung, um eine unabhängige Auswahl beider Quellen und des Ziels aus dem vollständigen Satz von 32 zu ermöglichen. Befehle, die die oberen Register verwenden, würden zwei Wörter/Zyklen anstelle von einem benötigen, aber in einigen Fällen könnte sich ein solcher Kompromiss durchaus lohnen. Die größte Schwierigkeit bei der Verwendung von Präfixen besteht darin, dass man entweder verhindern muss, dass zwischen einem Präfix und der nächsten Anweisung ein Interrupt auftritt, oder aber sicherstellen muss, dass, wenn dort ein Interrupt auftritt, die Anweisung nach dem Präfix immer noch die richtigen Register verwendet [z -Zählersicherungslogik speichert die Adresse des letzten ausgeführten Nicht-Präfix-Befehls]. aber in einigen Fällen könnte sich ein solcher Kompromiss durchaus lohnen. Die größte Schwierigkeit bei der Verwendung von Präfixen besteht darin, dass man entweder verhindern muss, dass zwischen einem Präfix und der nächsten Anweisung ein Interrupt auftritt, oder aber sicherstellen muss, dass, wenn dort ein Interrupt auftritt, die Anweisung nach dem Präfix immer noch die richtigen Register verwendet [z -Zählersicherungslogik speichert die Adresse des letzten ausgeführten Nicht-Präfix-Befehls]. aber in einigen Fällen könnte sich ein solcher Kompromiss durchaus lohnen. Die größte Schwierigkeit bei der Verwendung von Präfixen besteht darin, dass man entweder verhindern muss, dass zwischen einem Präfix und der nächsten Anweisung ein Interrupt auftritt, oder aber sicherstellen muss, dass, wenn dort ein Interrupt auftritt, die Anweisung nach dem Präfix immer noch die richtigen Register verwendet [z -Zählersicherungslogik speichert die Adresse des letzten ausgeführten Nicht-Präfix-Befehls].
Die Verwendung von Anweisungen mit mehreren Wörtern erschwert einige Aspekte des Entwurfs, verringert jedoch möglicherweise die Notwendigkeit, andere schwierige Entscheidungen zu treffen.
Dieser Typ hat die besten Details zum Verständnis der Festverdrahtung des fest codierten Teils eines Decoders, der die Steuerleitungen für eine fest codierte CPU erklärt: http://minnie.tuhs.org/CompArch/Tutes/week03.html Wie Sie sehen können, Ihre Die Wahl der Opcodes wirkt sich wirklich darauf aus, wie komplex die Dekodierungslogik ist.
Benutzer253751
Paebbels