Opcodes ISA --- D'où viennent-ils?

13

Lorsque les ingénieurs conçoivent une architecture de jeu d'instructions, par quelle procédure ou protocole, le cas échéant, suivent-ils lorsqu'ils désignent certains codes binaires comme instructions. Par exemple, si j'ai un ISA qui dit que 10110 est une instruction de chargement, d'où vient ce nombre binaire? A-t-il été modélisé à partir d'une table d'états pour une machine à états finis représentant une opération de chargement?

Edit: Après avoir fait plus de recherches, je crois que ce que j'essaie de demander concerne la façon dont les opcodes pour les différentes instructions CPU sont attribués. ADD peut être désigné par un opcode de 10011; une instruction de chargement pourrait être désignée comme 10110. Quel processus de réflexion va dans l'attribution de ces opcodes binaires pour l'ensemble d'instructions?

Steven
la source
8
Monte Dalrymple, «Microprocessor Design Using Verilog HDL», fournit une approche de conception très détaillée pour le CPU Z80 et je pense que vous en apprendrez beaucoup sur votre question. Mais il y a beaucoup de considérations qui entrent dans un choix spécifique, y compris l'analyse statistique d'autres jeux d'instructions, les sorties du compilateur, etc. Je recommanderais cependant de commencer par ce livre. Bien que cela commence par un design connu, il entre dans les détails intimes à ce sujet et je pense que vous ramasseriez quelques choses. Bon bouquin.
jonk
Ou, peut-être, vous vous interrogez sur la conception du moteur d'exécution et vous vous demandez comment les bits de l'instruction pourraient y jouer? Pas sûr de votre formulation.
jonk
2
Quelqu'un d'autre pose cette question. Doit être mardi.
Ignacio Vazquez-Abrams du
5
@Steven Pensez-y. Si vous deviez concevoir un ISA, à quoi penseriez- vous ? Si vos instructions n'étaient pas toutes de la même longueur, comment choisiriez- vous des mots d'instructions plus ou moins longs, pour quelles instructions? Si vous deviez concevoir une étape de décodage , à quoi voudriez-vous que votre ISA ressemble? Je pense que la question est inutilement large (et donc, presque impossible de répondre complètement), mais vous pouvez l'améliorer beaucoup en y réfléchissant davantage et en posant une question précise qui ne nous obligerait pas à écrire un livre pour répondre il.
Marcus Müller
4
Les spécifications RISC-V parlent des décisions de conception qu'ils ont prises à tous les niveaux, y compris un peu sur le codage des instructions machine. (Ceci est inhabituel pour un manuel de processeur; RISC-V est d'abord un exercice académique et une architecture CPU en second lieu, contrairement à la plupart.)
zwol

Réponses:

6

Dans de nombreux cas, le choix est assez arbitraire ou basé sur «où cela convient le mieux» à mesure que les ISA se développent avec le temps. Cependant, le MOS 6502 est un merveilleux exemple de puce dont la conception ISA a été fortement influencée par la tentative de faire sortir autant que possible des transistors limités.

Regardez cette vidéo expliquant comment le 6502 a été rétroconçu , en particulier à partir de 34:20.

Le 6502 est un microprocesseur 8 bits introduit en 1975. Bien qu'il ait 60% moins de portes que le Z80, il était deux fois plus rapide, et bien qu'il soit plus contraint (en termes de registres, etc.), il compense cela avec un ensemble d'instructions élégant.

Il ne contient que 3510 transistors, qui ont été dessinés à la main par une petite équipe de personnes rampant sur de grandes feuilles de plastique qui ont ensuite été rétractées optiquement, formant les différentes couches du 6502.

Comme vous pouvez le voir ci-dessous, le 6502 transmet l'opcode d'instructions et les données de synchronisation dans la ROM de décodage, puis les transmet à un composant de "logique de contrôle aléatoire" dont le but est probablement de passer outre la sortie de la ROM dans certaines situations complexes.

6502 schéma de principe

À 37:00 dans la vidéo, vous pouvez voir un tableau de la ROM de décodage qui montre quelles conditions les entrées doivent remplir pour obtenir un "1" pour une sortie de contrôle donnée. Vous pouvez également le retrouver sur cette page .

Vous pouvez voir que la plupart des éléments de ce tableau ont des X dans différentes positions. Prenons par exemple

011XXXXX 2 X RORRORA

Cela signifie que les 3 premiers bits de l'opcode doivent être 011 et G doit être 2; rien d'autre ne compte. Si c'est le cas, la sortie nommée RORRORA deviendra vraie. Tous les opcodes ROR commencent par 011; mais il existe également d'autres instructions qui commencent par 011. Ceux-ci doivent probablement être filtrés par l'unité "logique de contrôle aléatoire".

Donc, fondamentalement, les opcodes ont été choisis de sorte que les instructions qui devaient faire la même chose les unes que les autres aient quelque chose en commun dans leur modèle de bits. Vous pouvez le voir en regardant une table d'opcode ; toutes les instructions OR commencent par 000, toutes les instructions Store commencent par 010, toutes les instructions qui utilisent l'adressage page zéro sont de la forme xxxx01xx. Bien sûr, certaines instructions ne semblent pas "correspondre", car le but n'est pas d'avoir un format d'opcode complètement régulier mais plutôt de fournir un ensemble d'instructions puissant. Et c'est pourquoi la "logique de contrôle aléatoire" était nécessaire.

La page que j'ai mentionnée ci-dessus dit que certaines des lignes de sortie dans la ROM apparaissent deux fois, "Nous supposons que cela a été fait parce qu'ils n'avaient aucun moyen d'acheminer la sortie d'une ligne où ils voulaient, alors ils ont mis la même ligne à un autre emplacement à nouveau. " Je peux simplement imaginer les ingénieurs dessiner à la main ces portes une par une et réaliser soudainement une faille dans la conception et essayer de trouver un moyen d'éviter de redémarrer tout le processus.

Artelius
la source
22

Cela dépend de l'âge de l'ISA.

Au début de la conception manuelle, et plus encore lorsque les CPU étaient assemblés à partir d'une logique discrète, la conception logique serait venue en premier et aurait été considérablement minimisée, puis les modèles de bits ISA auraient été toutes les valeurs requises pour rendre ce minimum travail logique.

Il peut donc y avoir un modèle particulier de signaux de contrôle qui permet à certains multiplexeurs de connecter la sortie ALU à l'entrée du fichier de registre GP, quelques signaux de contrôle supplémentaires qui demandent à l'ALU d'ajouter, de soustraire, ET, OU etc., et quelques-uns adresse les bits dans le fichier de registre. Ces trois groupes de signaux formeront des champs dans l'instruction. Chaque groupe sera maintenu ensemble, et leur signification détaillée découle de la conception de cette unité (ALU, etc.), mais les groupes peuvent être dans n'importe quel ordre, jusqu'à ce que vous conceviez le décodeur d'instructions. (le x86 est assez vieux pour que vous puissiez en détecter une partie si vous regardez au bon endroit - ce n'était pas un design totalement nouveau, mais il s'inspirait de l'ancien 8080)

Les ISA ultérieurs peuvent être «nettoyés» et rendus plus réguliers et plus simples à utiliser, avec du matériel à traduire entre eux et les signaux de contrôle de niveau matériel réels, parfois via un «microcode». Ils sont appelés "CISC" ou "Complex Instruction Set Coding". Le préfixe d'instruction x86 "Rep" en est un exemple simple - il provoque la répétition de l'instruction suivante un certain nombre de fois, pour éviter d'avoir à écrire une boucle FOR.

Plus tard encore (dans les années 1980) est revenu un mouvement vers un style plus simple d'encodage direct (RISC - Reduced Instruction Set Coding) que vous pouvez voir dans les processeurs ARM. Cela était dû à la petite taille des ASIC à l'époque, et au désir de leur mettre des processeurs 32 bits, donc il n'y avait pas de capacité disponible pour les décodeurs de jeux d'instructions complexes, pour réduire le processeur complet à environ 20000 portes. (Il y a également eu une augmentation temporaire des performances, car les gens n'avaient pas encore développé de techniques pour rendre les décodeurs CISC rapides - cela est arrivé vers 1995 avec le Pentium Pro)

Et de nos jours, cela n'a plus d'importance - les processeurs lisent plusieurs instructions à la fois et consacrent des millions de transistors à les décoder, à les réorganiser et à en exécuter autant que possible à la fois, pour accélérer les programmes qui peuvent avoir été écrits pour les plus anciens. style d'ISA.

Brian Drummond
la source
2
Je ne suis pas sûr d'appeler vraiment le CISC "plus facile à utiliser". C'était peut-être l'intention initiale, mais 30 ans plus tard, ils sont en quelque sorte l'antithèse du "facile à utiliser" (par rapport aux ISC RISC, au moins).
tonysdg
2
Il y a des égards dans lesquels ils étaient plus faciles à utiliser ... soit la régularité (l'orthogonalité était un gros sujet) à l'époque où les compilateurs étaient des programmes relativement triviaux, soit en prenant directement en charge des opérations de niveau supérieur, nécessitant moins de traduction du compilateur. Mais c'était il y a longtemps et tout CISC survivant a autant de couches de révisions en plus de son jeu d'instructions d'origine. Les compilateurs ont également changé de toute reconnaissance - le millier de passes d'optimisation effectuées par gcc aurait été impensable à l'époque. Donc, ce qui était "facile" à l'époque et maintenant n'a que très peu de rapport.
Brian Drummond
4
La distinction a été à la fois érodée (les ensembles "RISC" ajoutant plus d'instructions) et remplacée par de nouvelles architectures encore plus complexes telles que VLIW; vraiment le seul consensus est que x86 (16 et 32 ​​bits) est difficile à utiliser
pjc50
1
@tonysdg: Il est difficile d'utiliser RISC et difficile à utiliser CISC. Une bonne comparaison de la "convivialité du programmeur" consiste à comparer 68k vs ARM. L'ARM a été conçu pour un compilateur, vous avez donc dû faire beaucoup de travail manuel pour obtenir des données de la RAM et les réécrire sur la RAM. Le 68k a été conçu pour les programmeurs d'assemblage et vous permet d'opérer directement sur les données en RAM. Si vous regardez l'ISA 68k, vous constaterez qu'il ressemble beaucoup à l'ISA RISC moderne à une exception près - vous pouvez opérer directement sur la RAM alors que RISC vous permet uniquement d'opérer sur des registres.
slebetman
1
Le microcode est principalement un attribut CISC. Cependant vous pourriez implémenter CISC sans microcode: le décodeur d'instructions serait plus compliqué. Vous verrez également certains CISC à partir du Pentium-Pro décrits comme RISC en interne; traduire chaque instruction CISC en une ou plusieurs opérations RISC internes: un autre nom pour le microcode (bien que les distinctions deviennent floues dans les unités d'exécution superscalaires)
Brian Drummond
9

Si vous regroupez des instructions similaires, des modèles apparaîtront. Ceci est très évident dans ARM, où le manuel ISA vous montre en fait quel bit d'un mot d'instruction correspond à la fonction, au choix de registre, etc. Mais il peut également être déduit pour X86 .

En fin de compte, la partie "fonction" des opcodes va dans un décodeur binaire à un instantané qui active réellement une fonction ou une séquence particulière d'opérations en pipeline. Ils ne sont généralement pas liés au contenu d'une machine d'état, sauf si nous considérons des instructions de longueur variable qui nécessitent une machine d'état pour décoder.

pjc50
la source
Vous dites essentiellement qu'ils visent le nombre de transistors le plus bas possible sur la puce. Je suis totalement d'accord dans le contexte de la question d'OP, où ils ne peuvent pas se permettre des centaines de transistors supplémentaires pour un jeu d'instructions plus net. Les processeurs à millions de transistors n'ont pas autant de raisons de s'en soucier, mais bien sûr, beaucoup les conservent pour une compatibilité descendante.
Harper - Rétablir Monica le
@Harper Il y a toujours une raison, car bien que les transistors soient devenus plus petits, ils ont toujours une taille - et les fréquences d'horloge ont beaucoup augmenté entre-temps. Un décodeur d'instructions trop gros peut donc être un goulot d'étranglement pour les performances (l'une des raisons pour lesquelles de nombreux processeurs ont opté pour le pré- décodage des instructions à l'avance). Il ne s'agit pas (seulement) du nombre de transistors, mais plutôt de la fréquence d'horloge en combinaison avec la zone de la puce. La propagation des informations prend encore du temps, et bien que les processeurs modernes ne fonctionnent pas à la vitesse de la lumière, ils ne sont pas assez loin de la limite de vitesse pour s'attendre à des améliorations significatives.
Luaan
@Luaan: En fait, "que faisons-nous avec tous ces transistors" est une vraie question de nos jours. Regardez tous les caches L2 / L3 lancés de nos jours. C'est un aveu silencieux que nous n'avons pas une meilleure utilisation de tous ces millions de transistors. Les derniers Xeon consacrent plus de 2 milliards de transistors au cache!
MSalters
6

Quelqu'un à un moment donné s'est assis et les a définis.

Un bon ISA rendra le décodeur aussi simple que possible.

Par exemple, avec une instruction ALU, vous pouvez laisser certains bits de l'opcode être envoyés directement dans les lignes de contrôle de l'ALU.

monstre à cliquet
la source
Merci à tous pour les excellentes réponses. Vous m'avez tous aidé à mieux comprendre cela.
Steven
4
Il y a en fait plusieurs facteurs autres que la simplicité du décodeur à prendre en compte. Selon les circonstances et l'utilisation prévue, d'autres (par exemple, la densité du code) peuvent être plus importants que la simplicité du décodeur. Dans un processeur moderne, la densité du code l'emporte probablement sur la simplicité du décodeur dans la plupart des cas.
Jerry Coffin
5

En règle générale, vous divisez votre ISA en groupes fonctionnels. Il est logique (que ce soit pour l'optimisation logique ou simplement pour être bien rangé) que les paires complémentaires soient différenciées par un changement de bit unique (charge vs magasin), et que vous avez une hiérarchie de bits qui affecte l'arbre de décision de décodage.

À la fin de la journée, une allocation arbitraire de bits pour le bloc fonction (au lieu de placer les champs «données» dans l'instruction n'aura qu'un faible impact sur l'efficacité globale de votre conception - mais vous avez beaucoup de choix sur la façon de «optimisez» votre encodage ISA en fonction de ce que vous jugez être un paramètre important.

Sean Houlihane
la source
1

L'encodage d'instructions est un compromis laid entre.

Pour simplifier le décodage, vous voulez pour cela un ensemble simple de champs dont chacun peut être décodé séparément et routé vers une partie distincte du moteur d'exécution.

Emballage autant de fonctionnalités que possible dans une taille limitée de mot d'instruction. Cela conduit à des choses comme des formats constants spéciaux qui peuvent coder une variété de nombres communs.

Compatibilité ascendante et descendante. Si vous attribuez des fonctionnalités à chaque opcode possible, vous ne vous donnez pas de place pour étendre l'architecture ultérieurement. Si vous ajoutez à une architecture existante, vous devez insérer vos nouvelles instructions dans les opcodes de rechange.

Peter Green
la source
1

L'excellent (quoique quelque peu daté) de Randy Hyde Art of Assembly va dans le jeu d'instructions x86 en détail dans le chapitre 3.3.4 L'unité de contrôle et les jeux d'instructions et suivants.

Les programmes des premiers systèmes informatiques (avant Von Neumann) étaient souvent «câblés» dans les circuits. C'est-à-dire que le câblage de l'ordinateur a déterminé le problème que l'ordinateur pourrait résoudre. Il fallait recâbler les circuits afin de changer le programme. Une tâche très difficile. L'avancée suivante dans la conception informatique a été le système informatique programmable, qui a permis à un programmeur informatique de «recâbler» facilement le système informatique à l'aide d'une séquence de prises et de fils de connexion. Un programme informatique consistait en un ensemble de rangées de trous (douilles), chaque rangée représentant une opération lors de l'exécution du programme. Le programmeur peut sélectionner l'une des instructions en branchant un fil dans la prise particulière pour l'instruction souhaitée.

Il montre ensuite de façon assez accrocheuse et détaillée comment les deux premiers plugs représentent l'instruction, les plugs suivants encodent la source et la destination. Bien sûr, aujourd'hui, plus personne ne "branche", mais pour les très anciens ISA, les bits de l'opcode font essentiellement le même travail que les fiches précédentes.

Vous vous retrouvez avec quelque chose comme ça:

entrez la description de l'image ici

DevSolar
la source
Merci pour le lien de Hyde! C'est très instructif et il semble avoir un excellent style d'enseignement.
Steven