II.7.4.1.1. La variété des architectures
cibles :
La variété des processeurs
Il existe de très nombreux processeurs, qui ne sont pas
compatibles entre eux et qui ne comprennent pas le même langage. En
première analyse, il pourrait sembler que seul le compilateur soit
concerné par cette diversité de processeurs, et qu'il suffit de
choisir le compilateur correspondant au processeur pour s'affranchir des
incompatibilités.
En fait, cette première vue est inexacte : le type du
processeur a une influence non négligeable sur le code de haut niveau du
logiciel, et notamment dans le cas des applications embarquées. Pour
voir pourquoi, nous allons montrer quelques caractéristiques d'un
processeur qui peuvent conduire à des adaptations difficiles voire
impossibles à la compilation :
- les types des données : les processeurs
possèdent en général un type de données
privilégié, correspondant à la taille de leurs registres.
Pour qu'une application soit performante, il est préférable
d'utiliser ce type au maximum pour les variables. Evidemment, suivant le
processeur ce type n'est pas le même : cela peut être entier sur 8
bits, 16bits, 32bits, ou d'autres types plus exotiques. Une solution
apportée par le langage C est de nommer ce type privilégié
le type int, auquel cas, c'est bien le compilateur qui décide du type
à prendre. Mais cela pose toujours des problèmes lorsqu'il s'agit
de communiquer ces données : le type doit correspondre à
l'émission et à la réception, et si les deux n'ont pas le
même type de base il faut en choisir un et l'imposer aux deux. On se
retrouve donc toujours dans une situation où il faut changer de type
suivant le processeur et son environnement ;
- la représentation des données : les
données sont représentées en mémoire par des
paquets de bits. Cependant, il existe de nombreuses manières pour
interpréter ces bits (par exemple en complément à deux, en
mantisse et exposant, etc.) et il est aussi possible de les interpréter
en grosboutistes (big-endians) ou en petit-boutistes
(little-endians). Il est important de noter que pour un même
type il peut exister plusieurs représentations possibles ;
- les instructions : chaque type de processeur dispose d'un
jeu d'instructions qui lui est propre. C'est au compilateur de produire le code
compréhensible par le processeur, et en fait n'importe quel programme de
haut niveau doit pouvoir être traduit par ce dernier. Cependant, une
description de haut niveau générale ne prend pas en compte les
spécificités d'un processeur, notamment en termes de performance.
Il est parfois préférable de changer l'algorithme pour un
processeur donné. En outre, un certain nombre d'instructions ne peuvent
pas être représentées à haut niveau : c'est le cas
par exemple des instructions de contrôle de consommation que
possèdent de nombreux processeurs utilisés dans les
systèmes embarqués. Dans ces deux cas le compilateur ne peut pas
agir ;
- les interruptions : la plupart des processeurs disposent
d'un mécanisme d'interruptions qui permet de générer des
événements. Ces mécanismes sont toujours très
spécifiques à chaque à chaque processeur et peuvent
être d'une grande complexité. Cependant, ils sont très
rarement pris en compte
Chapitre II conception des logiciels embarqués
par le compilateur, car ils ne font pas partie du modèle
de programmation classique (séquentiel continu).
Comme on le voit, les différences entre les processeurs
sont de plusieurs ordres et ne peuvent être prises en compte par les
seuls compilateurs.
La variété des communications
Suivant l'architecture cible, des modes de communication
très différents peuvent être utilisés. Il peut y
avoir des différences d'un point de vue topologique : communications
point à point ou non, hiérarchique ou non, à base de
barres croisées ou non, etc. Les différences peuvent être
d'un point de vue protocolaire : avec ou sans connexion, avec ou sans
poignée de main, avec ou sans rafale, etc. Enfin, elles peuvent
être d'un point de vue matériel : avec ou sans mémoire,
avec ou sans accès direct à la mémoire (DMA), etc.
Toutes ces caractéristiques peuvent se combiner, ce qui
fait un très grand nombre de cas possibles, pour chacun desquels un
ciblage différent sera nécessaire.
La variété des circuits connectés au
processeur
Suivant l'architecture cible, des circuits différents
peuvent être utilisés, et même s'ils peuvent avoir des
fonctionnalités identiques, ils risquent d'avoir des modes de
fonctionnement et de communication différents. Cela implique que chaque
circuit induit des détails logiciels différents et change donc
les opérations de ciblage à effectuer.
Logiciel abstrait
Le but de ciblage est d'adapter le logiciel aux architectures
cibles. Ce logiciel est donc très général et utilise des
primitives abstraites pour interagir avec l'extérieur. Nous avons vu
dans les sections précédentes que les éléments
d'architecture étaient très variés. Pour pouvoir les
relier avec le logiciel, il convient de fournir au concepteur du logiciel les
primitives abstraites correspondantes.
Pour simplifier et clarifier la programmation, il convient que
le nombre de primitives soit le plus faible possible. Dès lors, une
partie du travail de ciblage sera d'adapter ces quelques primitives à la
diversité des architectures cibles.
Conséquences sur la variété des
architectures cibles
Comme nous venons de le voir, le nombre d'architectures cibles
possibles pour une même application au départ est énorme.
Evidemment de très nombreuses configurations ne sont pas valables, mais
il est souvent difficile a priori de savoir si une architecture sera valable ou
non (notamment du point de vue temporel). Dès lors, il arrive souvent
que le choix d'une architecture soit effectué au terme d'une suite
d'essais sur différentes architectures.
Dans ces conditions, il apparaît important que le
ciblage soit le plus rapide possible et demande le moins d'efforts possible.
Ainsi, il sera possible d'obtenir plus rapidement une réalisation finale
valide, il sera aussi possible de tester un plus grand nombre d'architecture,
ce qui donne plus de chances pour atteindre un optimum.
|