1.46k likes | 1.85k Views
Le MIPS. Microprocesseur RISC débuts en 1985, gamme de processeurs : R2000 / R3000 / R4000 / R8000 / R10000 Équipe de nombreux types de machine Playstation, Nintendo 64, stations Silicon Graphics (dédiées à la 3D), société MIPS filiale de SGI machine à chargement/rangement
E N D
Le MIPS Microprocesseur RISC débuts en 1985, gamme de processeurs : R2000 / R3000 / R4000 / R8000 / R10000 Équipe de nombreux types de machine Playstation, Nintendo 64, stations Silicon Graphics (dédiées à la 3D), société MIPS filiale de SGI machine à chargement/rangement machine à registres généraux
Application de l'approche RISC Performances d'un processeur sur l'exécution de plusieurs instructions : approche CISC : plusieurs cycles pour une instruction. Instruction simple Instruction complexe
Fetch instruction Opération UAL Accès Mémoire Ecriture Résultat Application de l'approche RISC Utilisation intéressante du temps : instructions simples effectuées en peu de cycles, instructions complexes en plus de cycles (le nombre de cycles nécessaires). Mais complique énormément une gestion de pipelines éventuels, car les instructions n'ont pas le même format ni la même séquence d'exécution. Approche RISC : toute instruction s'exécute de manière similaire, en suivant un chemin de données bien défini : Fetch, UAL , Mémoire, Résultat. cycle 1 cycle 2 cycle 3 cycle 4
Exécution en pipeline Amélioration potentielle du nombre d'instructions par cycle en utilisant un pipeline : chaque cycle de l'instruction utilise une partie du processeur. A chaque cycle, on choisit de commencer le traitement d'une nouvelle instruction : M R F UAL R F UAL M M R F UAL Flot d'instructions R F UAL M cycle
4 cycles 8 cycles 8 cycles 12 cycles 4 cycles 8 cycles Exécution en pipeline Suppose que le pipeline contienne toujours des instructions utiles et qu'il n'y ait pas besoin de rajouter des cycles vides pour synchronisation. Exemple d'un pipeline CISC, utilisé sur 6 instructions En gris : utilisation exclusive d'une ressource, ici l'UAL.
Exécution en pipeline Sans pipeline : en tout 44 cycles pour 6 instructions : 7,33 cycles/instruction. Avec pipeline : cycles de délai lorsqu'une ressource n'est pas utilisable, matérialisé par : 29 cycles
Exécution en pipeline Avec pipeline, même s'il y a du remplissage : 29 cycles, soit 4,83 cycles/instruction . Gain contrebalancé par : gestion du pipeline pour tenir compte des cycles vides, des instructions de longueur variable : compliqué évènements qui perturbent le déroulement séquentiel du programme : sauts conditionnels, interruptions compilateur a du mal à ordonner les instructions pour tirer le meilleur parti du pipeline.
Machine à chargement/rangement Efficacité du découpage si les 4 phases F, UAL, M, R consomment une quantité de temps à peu près comparable. Or les accès mémoire sont longs : calcul de l'adresse, accéder aux opérandes en mémoire, les traiter, les ranger. Choix d'une architecture à chargement/rangement (instructions LOAD et STORE). Seules ces instructions permettent un accès à la mémoire. Gain en terme de bande passante (réduction des accès) Jeu d'instructions plus simple Optimisation de l'utilisation des registres par compilateur
Machine à chargement/rangement Chargement retardé (delayed LOAD). Lors d'une opération de chargement, la donnée à charger dans un registre n'est pas disponible immédiatement pour l'instruction suivante si l'on utilise un pipeline : Donnée chargée disponible comme opérande LOAD M F UAL R R F UAL M M R F UAL R F UAL M
Machine à chargement/rangement Chargement retardé (delayed LOAD). Solution : insérer des cycles d'attente lors de l'exécution de l'instruction 2, entre les phases F et UAL : lors de la phase UAL, l'instruction 2 peut avoir besoin de la donnée de l'instruction 1. Technique simple : faire apparaître cette dépendance au compilateur, toute instruction de chargement à un délai de latence de 1 cycle, qui correspond au début de traitement d'une nouvelle instruction. L'instruction suivant une instruction de chargement est dite dans la fenêtre ou intervalle de retard de chargement.(Load delay slot)
Machine à chargement/rangement Si cela apparaît au niveau du compilateur : pas de dépendance dans le pipeline entre l'instruction de chargement et celle qui est dans son load delay slot. Il existe une instruction qui n'a aucune dépendance avec les autres : NOP ! Pas besoin de faire un contrôle matériel du pipeline. Mais utilisation du NOP augmente la taille du code, augmente le délai d'exécution sans faire de tâche utile ! Autre solution : utiliser une instruction utile dans le load delay slot, optimisation faite par un compilateur.
Machine à chargement/rangement Exemple : code pour C=A+B; F=D Load R1,A Load R2,B dans le load delay slot de Load R1,A : pas de dépendance Add R3,R1,R2 dans le load delay slot de Load R2,B : dépendance à R2 : attente Load R4,D autre version : Load R1,A Load R2,B dans le load delay slot de Load R1,A : pas de dépendance Load R4,D dans le load delay slot de Load R2,B : pas de dépendance Add R3,R1,R2 dans le load delay slot de Load R4,D : pas de dépendance
Branchements retardés Les instructions de branchement/sauts introduisent aussi des délais dans le pipeline car il faut calculer l'adresse de destination avant de procéder à la phase F (Fetch) de l'instruction suivante. Lorsqu'un accès à la mémoire d'instructions nécessite un cycle entier, et que l'instruction de saut correspondante indique l'adresse de destination, il est impossible de faire tout de suite la phase F de l'instruction suivante sans insérer un délai d'un cycle SAUT M F UAL R Branch delay slot M R F UAL R F UAL M adresse trouvée disponible pour phase F suivante
Branchements retardés Les instructions de branchement conditionnels peuvent causer des retards supplémentaires : condition à évaluer. Technique choisie : comme pour le chargement retardé, on exécute, dans le branch delay slot, une ou plusieurs instructions avant d'effectuer le saut. Si cela n'est pas possible, insertion de NOPs, mais un compilateur est capable de réordonner des instructions pour remplir efficacement le branch delay slot. On cherche à mettre dans ce branche delay slot une instruction écrite avant dans le programme assembleur, et qui ne présente pas de dépendance avec le saut.
Branchements retardés Illustration : programme avec saut première version : avec branchements retardés explicitement A: move s0,a0 transfert de registre à registre move s1,a1 idem addiu s0,s0,1 addition s0 s0+1 beq s0,$0,SUITE saut à suite si S0=0 nop branch delay slot 'rempli' avec nop B: move a0,s0 move a1,s1 SUITE: store A,t3 autres instructions syscall jal FIN
Branchements retardés Illustration : programme avec saut deuxième version : branch delay slot 'intelligemment rempli' A: move s0,a0 transfert de registre à registre addiu s0,s0,1 addition s0 s0+1 beq s0,$0,SUITE saut à suite si S0=0 move s1,a1 branch delay slot avec instruction indépendante du saut et des valeurs testées par le saut. B: move a0,s0 move a1,s1 SUITE: store A,t3 autres instructions syscall jal FIN
Branchements retardés Souvent, une instruction qui se situe avant un branchement peut être exécuté après le début de traitement du branchement sans affecter la logique du programme ou le branchement lui-même.
Temps d'accès aux instructions Le temps nécessaire à accéder à une instruction dépend très largement du système physique de mémoire utilisé et devient le facteur limitant dans la conception des processeurs à cause de la vitesse à laquelle il est nécessaire de fournir des instructions au CPU. Utilisation de caches mémoires pour accélérer ces traitements : séparation en cache pour les instructions : joue le rôle de mémoire d'instruction (schéma de contrôle du MIPS de l'année dernière) cache pour les données : joue le rôle de mémoire de données
Temps d'accès aux instructions CPU @ données Cache d'instructions Cache de données données @ Mémoire principale
Le système de gestion de mémoire Système de gestion de la mémoire de type MMU (Memory Management Unit) intégré au coprocesseur CP0 (contrôle, pas arithmétique) selon le mode utilisé (utilisateur ou noyau), adresses référencées sont ou non traduites en adresses physiques à l'aide d'un TLB (buffer de traduction d'adresse virtuelle vers physique). Invisible la plupart du temps pour le programmeur, mais une mauvaise utilisation d'adresses (mauvaises valeurs) peut provoquer des erreurs du TLB. Ce ne sont pas des erreurs de bus ou d'alignement !
Le MIPS Respecte entièrement la philosophie RISC registres : 32 registres de 32 bits instructions : toutes codées sur 32 bits, découpage cohérent pour un traitement rapide registre PC et adresses codées sur 32 bits la mémoire est adressable par octet, transferts de 8, 16 ou 32 bits possibles mémoire maximale adressable : 232 octets = 22.210.210.210 octets = 4 Go
Le MIPS Constitué de deux parties distinctes le CPU : registres généraux registres HI et LO UAL PC le CP0 : processeur de contrôle système intégrant TLB pour la gestion de mémoire virtuelle registres de gestion mémoire registres de traitement des exceptions registres d'état
Le MIPS Registres généraux : nommage particulier : $0 à $31 $0 : vaut toujours 0 (câblage) $31 : utilisé par certaines instructions comme sauvegarde ne pas utiliser $31 comme un registre général autre convention de nommage, plus pertinente mais contredit le caractère général des registres
Format des instructions MIPS Toutes les instruction du R2000 sont des instructions 32 bit, et il y a 3 formats d'instruction différents, cela pour simplifier le décodage et utiliser un séquenceur câblé. Les opérations plus complexes peuvent être simulées grâce à une suite d'instructions simples, on les trouvera sous la forme de pseudo-instructions. Exemple : un transfert de registre à registre n'est pas implémenté, mais la pseudo-instruction move réalise cette opération. Lorsque l'on écrit move Rsource,Rdest, en fait on réalise l'instruction MIPS : add Rdest,Rsource,$0
Format des instructions MIPS • On distingue 3 formats d'instructions : • les instructions de type I : opérande de type valeur immédiate; • les instructions de type R, les opérandes sont des registres • les instructions de type J, (Jump, saut), l'opérande est l'adresse choisie • Ces formats ne correspondent pas aux différentes catégories d'instructions
Catégories des instructions MIPS • répartition en 6 catégories : • Load/Store • calculatoires : arithmétiques, logiques, décalages/rotations • sauts et branchements • instructions du coprocesseur arithmétique (R2010 FPA) • instructions du coprocesseur de contrôle CP0 (gestion de la mémoire virtuelle, gestion des interruptions et exceptions) • instructions spéciales : appels système, points d'arrêt
Retour sur les formats d'instruction Type I op rs rt immediate Type J op target Type R op rs rt rd shamt funct
Retour sur les formats d'instruction Avec : op : opcode sur 6 bits rs : n° de registre source sur 5 bits rt : n° de registre de transit sur 5 bits rd : n° de registre de destination sur 5 bits immediate : valeur immédiate 16 bits target : adresse cible sur 26 bits shamt : valeur de décalage sur 5 bits (pour les instructions de décalage, rotations) funct : champ de fonction sur 6 bits
Le langage Assembleur En fait, leS langageS d'assemblage. A chaque architecture son langage (dommage). Produit le code réputé le plus efficace en rapidité d'exécution proche de la machine (quoique…) donc hélas éloigné du programmeur productivité plus faible en assembleur qu'en C code produit par les compilateurs de plus en plus sophistiqués. Utilité pour certaines applications (temps réel)
Le langage Assembleur Au départ : traduction quasi-directe en langage machine (traduction 'à la main' en hexadécimal, en binaire, en trous ! avec des tables de conversion) des programmes : 010101000011111101010101001001010101001001111010100011101010010101000101111010100000111111100001111100000101000000111111000000000000001101000011111000001 0x6461425b 0x64646120 0x73736572 0x206e6920 0x61746164 0x6174732f 0x72206b63 0x5d646165 0x20200020 0x7272455b 0x6920726f 0x7973206e 0x6c616373 0x00205d6c 0x425b2020 0x6b616572 0x6e696f70 0x00205d74 0x525b2020 0x72657365 0x20646576
Le langage Assembleur Aujourd'hui, langage assembleur traduit en langage machine de manière plus complexe une instruction assembleur : plusieurs instructions du microprocesseur ex du MIPS : 0x3c011001 lui $1, 4097 [mess1] la $a0,mess1 0x34240016 ori $4, $1, 22 [mess1] Instructions du microprocesseur Instructions en assembleur Code + opérandes en hexadécimal
Le langage Assembleur Aujourd'hui, langage assembleur traduit en langage machine de manière plus complexe : existence de pseudo-instructions (qui ne sont pas comprises par tous les assembleurs MIPS). Piège pour l'évaluation de performances, en nombre de cycles/instructions : cycles / instructions en langage machine, et non cycles / instructions en assembleur ! En général, pseudo-instructions très bien traduites : utilisation naturelle, pas de précaution à prendre pour leur emploi.
Le langage Assembleur Pas de typage fort des données : emploi sans contrôle des octets ou groupes de 16 ou 32 bits selon les besoins Pas de protection du code vis-à-vis des données : localisation mémoire différente (explicite) mais accès indifférent code auto-modifiable un programme peut écrire dans la zone mémoire où sont stockées ses instructions ! (très simple en MIPS !)
Le langage Assembleur • Connaissance du "modèle de la mémoire" du processeur ou de l'assembleur. • Attention aux différences possibles entre : • Simulation d'un processeur : interprétation du code binaire ou des instructions assembleur • Exécution du programme en code binaire sur une cible (processeur + carte) • Simulateur : tentation de faire plus simple que la réalité ! C'est le cas avec le MIPS !
Le langage Assembleur Modèle de mémoire simplifié : segment de donnée (DATA) / segment de code (TEXT) 0x7fffffff STACK adresses DYNAMIC (heap) DATA STATIC 0x10000000 TEXT 0x00400000 Réservé
Modèle des registres Noms associé à un rôle que jouent les registres lors de programmes comportant plusieurs langages source (C et ASM le plus souvent) noms normaux noms conventionnels remarque $0 $0 vaut 0 $1 $at ne pas utiliser $2 - $3 $v0 - $v1 valeur de retour de procédures $4 … $7 $a0 … $a3 4 premiers arguments de fonctions $8 .. $15 et $24,$25 $t0 … $t9 valeurs temporaires $16-$23 $s0 … $s9 ne doivent pas être modifiés par fonctions $26 - $27 $k0 - $k1 ne pas utiliser $28 $gp pointeur global : accès valeurs statiques $29 $sp pointeur de pile $30 $fp pointeur de haut de zone de pile (frame) $31 $ra ne pas utiliser
Modèles des registres En pratique : utiliser, pour des programmes simples : $0, $v0, $v1, $a0 … $a3, $t0 … $t9 (16 registres) Modes d'utilisation : mode utilisateur (ou U / User) mode noyau (ou K / Kernel) protection de ressources, accès au mode noyau facile cependant ! Modèle mémoire différent selon le mode U : 2 Go K : jusqu'à 4 Go
Forme d'un programme • Un programme en assembleur est constitué d'instructions et de directives • Instruction : ordre donné au processeur pour effectuer une action lors de l'exécution du programme • Directive : ordre donné à l'assembleur pour préparer la traduction du code source en langage machine
Forme d'un programme Exemples d'instructions : addu $t0,$t1,$t6 effectue $t0 $t1+$t6 (registres) j $ra effectue : saut à l'adresse donnée par $ra bgezal $s4,destination compliquée ! exemple de directives : .text indique que les lignes suivantes seront rangées dans le segment TEXT .data indique que les lignes suivantes seront rangées dans le segment DATA .byte 6 stocke la valeur 6 dans un octet de la mémoire
Écrire un programme Exemple avec un programme affichant "hello world !" .data hello: .asciiz "hello world\n" .text .globl main main: li $v0,4 la $a0,hello syscall j $ra directives instructions labels
Écrire un programme Les lignes indispensables : programme minimal .data (directive)segment de données .text (directive)segment de programme .globl main (directive) exportation du label 'main' main: (label) repère de début de programme j $ra (instruction) retour au système (fin du prog) Données ajoutées dans le segment de données, instructions dans le segment de texte.
Écrire un programme Choix de la zone mémoire à utiliser avec les directives .data et .text: possibilité de préciser l'adresse de départ de la zone en l'ajoutant à la suite des directives .data ou .text syntaxe : .data adresse .text adresse équivalent de ORG en 68000, il est possible d'utiliser plusieurs directives .data ou plusieurs directives .text dans un même programme source en assembleur. Par défaut : .data :adresse 0x10010000 .text :adresse 0x00400000
Quelques directives Mettre des valeurs dans la mémoire : principalement insérer des constantes, ou initialiser des "variables". À utiliser dans le segment de données .data ! Ne sont pas des instructions exécutables la plupart du temps. Principe : l'octet (les octets) situé(s) à une certaine adresse mémoire a la valeur précisée. Syntaxe .byte b1[,b2,…,bn] : stocke les valeurs 8 bits listées dans des octets consécutifs .half h1[,h2,…,hn] : stocke les valeurs 16 bits listées dans des octets consécutifs .word w1[,w2,…,wn] : stocke les valeurs 32 bits listées dans des mots consécutifs
Quelques directives • .float f1[,f2,…,fn] : stocke les valeurs float (32 bits) listées dans des mots consécutifs • .double d1[,d2,…,dn] : stocke les valeurs float (32 bits) listées dans des mots consécutifs • .ascii[z] "chaîne" : stocke les codes ascii des caractères de la chaîne en mémoire à des adresses consécutives. Stocke un 0 à la fin si asciiz est employé. • Notations : utilisation de constantes numériques • notation en base 10 par défaut, avec signe possible • notation en base 16 possible en faisant précéder le nombre de '0x', nombre non signés en hexadécimal !
Directives de remplissage de RAM Exemples .data .byte 0xff, .byte 0x3e, 12,-5 donnera en mémoire, avec la présentation utilisée par le simulateur (attention, les PC sont des machines petit-boutistes !) [0x10010000] 0xfb0c3eff 0x00000000 0x00000000 0x00000000 Mots de 32 bits adresse
Directives de remplissage de RAM Exemples .data .half 0xa5a5,0xb6b7 donnera en mémoire, avec la présentation utilisée par le simulateur (attention, les PC sont des machines petit-boutistes !) [0x10010000] 0xb6b7a5a5 0x00000000 0x00000000 0x00000000 Mots de 32 bits adresse
Directives de remplissage de RAM Ces directives peuvent aussi préciser le nombre de fois où ces valeurs doivent être écrites en RAM. Syntaxe : .format val1:nb1 écrit nb1 fois de suite la valeur val1 en RAM Dans ce cas, on ne précisera qu'une seule valeur par ligne. (erreur du simulateur sinon)
Directives de remplissage de RAM exemple : .data .half 0xa5a5:3 .half 0xb6b7 .byte 12:3 .byte 0xfb:2 donnera en mémoire : [0x10010000] 0xa5a5a5a5 0xb6b7a5a5 0xfb0c0c0c 0x000000fb
Les constantes à virgule Écriture des nombres en virgule flottante, formats .float et .double : on utilise une notation scientifique exemples : .data .float 1.1 .float -1.1e-24 donnera en mémoire [0x10010000] 0x3f8ccccd 0x97aa377d ne pas utiliser de notation en hexadécimal pour les constantes à virgule : pour ces notations, utiliser .word avec les constantes à virgule, on ne peut pas utiliser les répétitions de placement en mémoire.
Réservation d'octets La directive .space permet de "réserver" un certain nombre d'octets, comme le permettait la directive DS.B du 68000. L'espace 'réservé' est rempli avec des 0.