Les unités de calcul

Difficulté Facile
Note
Thématiques
Mis à jour le mercredi 19 mars 2014

Le rôle du chemin de donnée est d’exécuter une instruction et pour ce faire, notre processeur contient des circuits spécialement étudiés pour. Dans notre processeur, ces circuits sont presque toujours regroupés ensembles, avec quelques petits circuits supplémentaires pour gérer le tout, dans ce qu'on appelle une unité de calcul.

Pour simplifier, notre unité de calcul est donc une sorte de gros circuit qui contient de quoi faire des calculs arithmétiques ou des opérations logiques (comme des ET, OU, XOR, etc). Je ne vous cache pas que ces unités de calculs sont utilisés pour effectuer des instructions arithmétiques et logiques, pour les comparaisons et instructions de test. Mais on peut aussi l'utiliser lors des étapes de calcul d'adresse, de certains modes d'adressage. Après tout, calculer une adresse se fait avec des opérations arithmétiques et logiques simples, comme des décalages, des additions et des multiplications.

Cette unité de calcul est souvent appelée l'unité arithmétique et logique ou UAL. Certains (dont moi) préfèrent l’appellation anglaise Arithmetic and logical unit, ou ALU.

Une unité de calcul est capable d'effectuer des opérations arithmétiques, des opérations logiques, et des instructions de test (les comparaisons).
Les instructions effectuées par ces unités de calcul sont donc le plus souvent :

  • des additions ;

  • des soustractions ;

  • des multiplications ;

  • des divisions ;

  • des changements de signe ;

  • des décalages logiques ;

  • des décalages arithmétiques ;

  • des rotations ;

  • des NON logiques ;

  • des ET logiques ;

  • des OU logiques ;

  • des XOR logiques ;

  • des comparaisons ;

  • des test d'égalité ;

  • etc.

Certaines unités de calculs sont assez rudimentaires, et ne peuvent pas effectuer beaucoup d'instructions : on peut parfaitement créer des unités de calcul ne sachant faire que des opérations simples comme des ET, OU, et NON logiques. Par contre, d'autres unités de calcul sont plus évoluées et peuvent faire énormément d'instructions différentes : certaines unités de calcul sont capables d'effectuer toutes les instructions citées au-dessus, et quelques autres comme calculer des racines carrées, des tangentes, arc-tangentes, cosinus, etc.

Vu de l’extérieur

Nos instructions de comparaisons sont prises en charge par l'unité de calcul et elles doivent mettre à jour le registre d'état. Et c'est sans compter sur certaines opérations de calcul qui doivent mettre à jour le registre d'état : prenez l'exemple du bit NULL, cité il y a quelques chapitres. On peut donc en déduire que le registre d'état est obligatoirement relié à certaines sorties de l’unité de calcul.

De plus, il faudra bien spécifier l'instruction à effectuer à notre unité de calcul parmi toutes celles qu'elle est capable de faire. Après tout, il faut bien prévenir notre unité de calcul qu'on veut faire une addition et pas une multiplication : elle ne peut pas le deviner toute seule ! Il faut donc configurer notre unité de calcul pour que celle-ci exécute l'instruction voulue et pas une autre. Pour cela, notre unité de calcul possède une entrée permettant de la configurer convenablement. Cette entrée supplémentaire s'appelle l'entrée de sélection de l'instruction.

Sur cette entrée, on va mettre un nombre codé en binaire qui précise l'instruction à effectuer. Suivant le nombre qu'on va placer sur cette entrée de sélection de l'instruction, notre unité de calcul effectuera une addition, une multiplication un décalage, etc. Pour chaque unité de calcul, il existe donc une sorte de correspondance entre le nombre qu'on va placer sur l'entrée de sélection de l'instruction, et l'instruction à exécuter :

Entrée de sélection de l'instruction

Instruction effectuée par l'unité de calcul

0000

NOP

0111

Addition

1111

Multiplication

0100

ET logique

1100

Décalage à droite

...

...

Pour votre culture générale, voici comment sont généralement schématisées ces fameuses unités de calcul :

Image utilisateur

Ce schéma montre une unité de calcul effectuant des instructions sur une ou deux données à la fois : elle possède trois entrées et deux sorties.

A l'intérieur d'une unité de calcul

Ces unités de calcul contiennent des circuits, fabriqués à base de portes logiques et de transistors. Suivant l'unité de calcul utilisée, son fonctionnement interne peut être plus ou moins compliqué.

Dans une ALU, il y a des circuits !

Certaines unités de calcul contiennent un circuit différent par instruction qu'elles sont capables d’exécuter. L’entrée de sélection sert donc uniquement à sélectionner le bon circuit et à connecter celui-ci aux entrées ainsi qu'aux sorties.

Pour sélectionner un de ces circuits, on utilise des circuits élèctroniques, qui vont se charger d'aiguiller les données placées en entrée sur le bon circuit. Ces circuits, qui vont relier le bon circuit aux entrées et aux sorties de notre unité de calcul, sont appelés des multiplexeurs. On peut voir ces multiplexeurs comme des espèces d'interrupteurs qui vont venir connecter ou déconnecter les entrées et sorties de notre unité de calcul au bon circuit.

Image utilisateur

Bien sûr, ces multiplexeurs doivent être commandés pour se mettre dans la bonne position : l'entrée de sélection sert à cela.

Unité à configurer

Utiliser un circuit pour chaque instruction semble être une solution assez sympathique. Mais si on regarde bien, elle possède un défaut assez important : certains morceaux de circuits sont présents en double dans notre unité de calcul. Cela ne se voit pas dans les schémas du haut, mais vous allez rapidement comprendre par un bref exemple.

Supposons que j'aie une ALU qui soit capable d'effectuer des additions et des soustractions. En utilisant la technique vue au-dessus, j'aurais donc besoin de deux circuits : un pour les additions et un pour les soustractions. Visiblement, il n'y a pas de duplications, à première vue. Mais si on regarde bien le circuit qui effectue la soustraction, on remarque que certains circuits sont présents en double. Notre soustracteur est composé de deux circuits, reliés en série. Il est composé d'un circuit qui inverse tous les bits de notre opérande, et d'un additionneur. On verra pourquoi au prochain chapitre.

Image utilisateur

L'additionneur est donc présent en double : une fois dans le circuit chargé des soustractions et une autre fois dans celui capable d'effectuer les additions. Bien évidemment, il est plus économe en terme de circuits de ne pas avoir à placer deux additionneurs dans notre processeur. Pour éviter ce problème, on regroupe l'additionneur et l'inverseur dans un seul circuit et on sélectionne l'inverseur quand on veut effectuer une soustraction. Et ce qui peut être fait pour un additionneur peut aussi être fait pour d'autres circuits. Pour cela, certaines unités de calcul sont composées de circuits élémentaires qui sont sélectionnés ou dé-sélectionnés au besoin, suivant l'instruction à exécuter. Le choix des circuits à activer ou désactiver peut se faire de deux façons différentes.

Avec la première façon, ce choix est fait grâce à des "interrupteurs électroniques" (des transistors ou des multiplexeurs) qui connecteront entre eux les circuits à utiliser et déconnecteront les circuits qui sont inutiles pour effectuer l'instruction choisie. Suivant la valeur de l'entrée de sélection de l'instruction, quelques petits circuits internes à l'unité de calcul se chargeront de fermer ou d'ouvrir ces "interrupteurs" convenablement. Dans notre exemple, ce la reviendrait à faire ceci :

Image utilisateur

Pour spécifier qu'on veut faire une addition ou une soustraction, il faut alors placer une entrée chargée de spécifier s'il faut connecter ou déconnecter le circuit inverseur : cette entrée permettra de configurer le circuit. Ce qu'il faut mettre sur cette entrée sera déduit à partir de l'entrée de sélection d'instruction de l'ALU.

Une autre solution peut être de placer en série des circuits, qu'on va activer ou désactiver au besoin. Ces circuits possèdent une entrée qui leur demandera de fonctionner. Suivant la valeur de cette entrée, ces circuits vont agir différemment : soit ils vont faire ce qu'on leur demandent, soit ils recopieront leur entrée sur leur sortie (il ne feront rien, quoi).

Image utilisateur

Ce qu'il faut mettre sur cette entrée sera déduit à partir de l'entrée de sélection d'instruction de l'ALU.

Dans la réalité

les unités de calcul de nos processeurs actuels sont un mélange de tout ce qui a été vu au-dessus. Les unités de calcul les plus complètes sont en effet découpées en pleins de circuits, certains devant être configurés, d'autres reliés, etc. Tout ce passe comme si ces circuits se comportaient comme des sous-unités de calculs inclues dans une unité de calcul plus grosse. Par exemple, on peut avoir une sous-unité de calcul qui se charge des décalages et des rotations (un barrel shifter), une autre qui se charge des opérations logiques (ET, OU, NON, XOR), une autre pour les additions, soustractions et comparaisons, une autre pour la multiplication, etc.

Image utilisateur

Autant dire que l'intérieur d'une unité de calcul est assez sympathique. Dans ce genre de cas, une partie seulement de l'entrée de sélection sert à sélectionner un circuit, le reste servant à configurer le circuit sélectionné.

Bit Slicing

Sur certains processeurs assez anciens, l'ALU est elle-même découpée en plusieurs ALU plus petites, chacune capable d'effectuer toutes les instructions de l'ALU, reliées entre elles, qui traitent chacune un petit nombre de bits. Par exemple, l'ALU des processeurs AMD's Am2900 est une ALU de 16 bits composée de plusieurs sous-ALU de 4 bits. Cette technique qui consiste à créer des unités de calcul plus grosses à partir d’unités de calcul plus élémentaires s'appelle en jargon technique du Bit Slicing.

Unités annexes

Il y a au moins une unité de calcul dans un processeur. Ceci dit, il n'est pas rare qu'un processeur possède plusieurs unités de calcul. Cela peut avoir diverses raisons : cela peut-être pour des raisons de performance, pour simplifier la conception du processeur, ou pour autre chose.

FPU

Dans certains cas, le processeur disposent d'unités de calcul supplémentaires, capables d'effectuer des calculs sur des nombres flottants. Il faut dire que les circuits pour faire un calcul sur un entier ne sont pas les mêmes que les circuits faisant la même opération sur des flottants. Certains processeurs s'en moquent et utilisent une seule unité de calcul capable d'effectuer à la fois des calculs sur des entiers que des calculs sur des flottants.

Mais dans d'autres processeurs, les circuits calculant sur les entiers et ceux manipulant des flottants sont placées dans des unités de calculs séparées. On se retrouve donc avec une unité de calcul spécialisée dans le traitement des nombres flottants : cette unité s'appelle la Floating Point Unit. On utilise souvent l'abréviation FPU pour désigner cette Floating Point Unit.

Les instructions supportées par les FPU et une unité de calcul sur des entiers sont souvent différentes. Les FPU peuvent effectuer d'autres instructions supplémentaires en plus des traditionnelles opérations arithmétiques : des racines carrées, des sinus, des cosinus, des logarithmes, etc. Et c'est normal : les résultats de ces opérations sont souvent des nombres à virgules et rarement des nombres entiers.

ALU spécialisées

Un processeur peut aussi disposer d’unités de calcul spécialisées, séparées de l'unité de calcul principale. Par exemple, un processeur peut contenir des unités chargées d'effectuer des instructions de décalage, des unités spécialisées dans le calcul de certaines instructions, etc. Pour donner un exemple, les divisions sont parfois exécutées dans des circuits à part. Cette séparation est parfois nécessaire : certaines opérations sont assez compliquées à insérer dans une unité de calcul normale, et les garder à part peut simplifier la conception du processeur.

Les auteurs