Changes between Version 88 and Version 89 of SoclibCourseTp4


Ignore:
Timestamp:
Dec 15, 2011, 8:04:47 PM (13 years ago)
Author:
alain
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • SoclibCourseTp4

    v88 v89  
    1818
    1919Il existe deux types de périphériques:
    20  * Un ''périphérique caractère'' (tel qu'un contrôleur TTY) supporte des requêtes de lecture ou d'écriture d'un seul caractère. Ce type de périphérique se comporte comme une cible sur le bus, puisqu'il ne peut que recevoir des commandes provenant d'un processeur, et qu'il n'a pas la possibilité de lire ou d'écrire lui-même  en mémoire. Le contrôleur de périphérique utilise une interruption  pour signaler au système d'exploitation qu'un événement (tel qu'un caractère frappé au clavier) s'est produit du côté du périphérique.
    21 
    22  * Un ''périphériques bloc'', tel qu'un contrôleur de disque, doit tranférer de grosses quantités de données entre la mémoire et le disque. Les transferts se font par blocs (un bloc contenant généralement 512 octets), et ces périphériques ont généralement une capacité DMA : Ils sont à la fois maître et cible sur le bus, cat ils reçoivent des commandes définissant le transfert à effectuer, mais peuvent ensuite directement lire ou écrire en mémoire. Le contrôleur de périphérique utilise une interruption pour signaler au système d'exploitation la fin du transfert.
     20 * Un périphérique ''orienté caractère'' (tel qu'un contrôleur TTY) supporte des requêtes de lecture ou d'écriture d'un petit  nombre de caractères. Ce type de périphérique se comporte généralement comme une cible sur le bus, puisqu'il ne peut que recevoir des commandes provenant d'un processeur, et qu'il n'a pas la possibilité de lire ou d'écrire lui-même  en mémoire. Le contrôleur de périphérique utilise une interruption  pour signaler au système d'exploitation qu'un événement (tel qu'un caractère frappé au clavier) s'est produit du côté du périphérique.
     21
     22 * Un périphérique orienté ''bloc'', tel qu'un contrôleur de disque, doit tranférer de grosses quantités de données entre la mémoire et le disque. Les transferts se font par blocs (un bloc contenant généralement 512 octets), et ces périphériques ont généralement une capacité DMA : Ils sont à la fois maître et cible sur le bus, cat ils reçoivent des commandes définissant le transfert à effectuer, mais peuvent ensuite directement lire ou écrire en mémoire. Le contrôleur de périphérique utilise une interruption pour signaler au système d'exploitation la fin du transfert.
    2323
    2424== 2.1 composants matériels ==
     
    2626Lorsque le nombre de périphériques augmente, le nombre de lignes d'interruption augmente également,
    2727et il faut un mécanisme permettant de concentrer plusieurs dizaines de requêtes d'interruption vers un seul signal
    28 connecté au processeur. C'est en interrogeant le composant matériel ICU que le système d'exploitation (en pratique le gestionnaire d'interruption) peut obtenir le numéro de la ligne d'interruption activé la plus prioritaire.
     28connecté au processeur. C'est en interrogeant le composant matériel ICU (Interrupt Controler Unit) que le système d'exploitation (en pratique le gestionnaire d'interruption) peut obtenir le numéro de la ligne d'interruption active la plus prioritaire.
    2929
    3030Le composant '''vci_icu''' est un contrôleur d'interruptions vectorisées. C'est une cible VCI dont vous trouverez  la spécification fonctionnelle [https://www.soclib.fr/trac/dev/wiki/Component/VciIcu ici].  Prenez le temps de la lire.
     
    6565
    6666Dans le TP3, le programme utilisateur utilise l'appel système '''tty_getc()''' pour lire un caracère.
    67 Cet appel système bloquant contient une boucle de scrutation dans laquelle, à chaque tour de boucle,
    68 on effectue une transaction sur le bus pour lire la valeur du registre STATUS du terminal TTY concerné.
     67Cet appel système contient une boucle de scrutation dans laquelle, à chaque tour de boucle,
     68le processeur effectue une transaction sur le bus pour lire la valeur du registre STATUS du terminal TTY concerné.
    6969On ne sort de cette boucle que lorsqu'un caractère a effectivement été saisi au clavier.
    7070
     
    7474qui est à la fois protégé (non accessible par les programmes utilisateur) et non cachable.
    7575 
    76 Plutôt que d'effectuer une scrutation sur le registre STATUS du contrôleur TTY, l'appel système '''tty_get_irq()'''
    77 teste la variable '''_tty_get_full''' rangée en mémoire. Si la valeur de cette variable indique qu'il n'y a pas de caractère
    78 disponible, le système d'exploitation peut (en principe) attribuer le processeur à un autre programme utilisateur. C'est la routine d'interruption (ISR) associée au terminal TTY qui se charge d'écrire le code ASCII du caractère dans le tampon  '''_tty_get_buf''', et de forcer à 1 la variable de synchronsation '''_tty_get_full''' pour signaler que le tampon est plein. Cette variable de synchronisation est remise à 0 par l'appel système ''tty_getc_irq()'' lorsque le caractère est transféré du tampon système '''tty_get_buf'''  vers le tampon mémoire défini par l'utilisateur.
     76Plutôt que d'accéder directement au registre STATUS du contrôleur TTY, l'appel système '''tty_get_irq()'''
     77teste la variable '''_tty_get_full''' rangée en mémoire. C'est la routine d'interruption (ISR) associée au terminal TTY qui se charge d'écrire le code ASCII du caractère dans le tampon  '''_tty_get_buf''', et de forcer à 1 la variable de synchronsation '''_tty_get_full''' pour signaler que le tampon est plein. Cette variable de synchronisation est remise à 0 par l'appel système ''tty_getc_irq()'' lorsque le caractère est transféré du tampon système '''tty_get_buf'''  vers le tampon mémoire défini par l'utilisateur.
    7978
    8079Dans une architecture monoprocesseur, le processeur peut exécuter plusieurs tâches (plusieurs programmes utilisateurs) en pseudo-paralléliseme, par multiplexage temporel. Chaque tâche possède alors son propre terminal écran/clavier, mais ces
    81 différents terminaux sont tous contrôlés par le même contrôleur TTY : Chaque terminal a son propre jeu de 4 registres,
     80différents terminaux sont tous contrôlés par le même contrôleur TTY : Chaque terminal possède son propre jeu de 4 registres,
    8281pour communiquer avec l'OS.
    8382 
     
    10099L'appel système '''ioc_completed()''', qui appelle lui-même la fonction système '''_ioc_completed()''' permet au programme utilisateur de se mettre en attente sur la fin d'un transfert. C'est donc une fonction bloquante qui ne rend la main au programme utilisateur que lorsque le transfert est effectivement terminé.
    101100
    102 '''Question''' : Que se passe-t-il si un programme utilisateur A effectue un appel système '''_ioc_read()''' alors que le contrôleur de disque est déjà en train d'exécuter un transfert à la demande d'un autre programme utilisateur B?
     101'''Question''' : Le contrôleur de disque utilisé ici ne peut effectuer qu'un seul transfert de données à la fois.
     102Que se passe-t-il si un programme utilisateur A effectue un appel système '''_ioc_read()''' alors que le contrôleur de disque est déjà en train d'exécuter un transfert à la demande d'un autre programme utilisateur B?
     103
     104'''Question''': Si deux programmes utilisateurs s'exécutant en parallèle sur deux processeurs différents demandent simultanément à utiliser le contrôleur de disque, comment le GIET peut-il garantir que le périphérique ne sera alloué qu'à un seul des deux demandeurs?
     105
    103106 
    104107= 3 Modélisation de l'architecture matérielle =
     
    115118
    116119'''Question''' : Complétez le fichier '''tp4_top.cpp''' pour définir les arguments des constructeurs des  composants ICU, TIMER, IOC, FBF, DMA et BUS. Pour le composant IOC on fera en sorte que le cheminom désignant le fichier
    117 externe puisse être redéfini par un paramètre sur la ligne de commande au lancement du simulateur. Pour le composant
    118 FBF, on choisira une taille d'écran de 128 lignes de 128 pixels.
     120externe puisse être redéfini par un paramètre sur la ligne de commande au lancement du simulateur. Pour le composant FBF, on choisira une taille d'écran de 128 lignes de 128 pixels.
    119121
    120122'''Question''' : Complétez la net-list dans le fichier '''tp4_top.cpp''' pour  connecter les 4 lignes d'interruption utilisées dans cette architecture mono-processeur, et pour connecter sur le bus les 3 initiateurs et les 3 cibles.
     
    174176
    175177'''Question''' : Ecrivez un nouveau programme main_1 dans un fichier '''main_1.c'''. Vous  utiliserez les appels système '''ioc_read()''' et '''ioc_completed()''' pour charger une image dans un tampon mémoire de 128*128 octets tab[128][128], déclaré dans la fonction main(). Dans quel segment sera rangéé ce tableau tab[128][128]?
    176 Utilisez l'appel système '''fbf_write()''' pour afficher cette image sur l'écran graphique.
     178Utilisez l'appel système '''fbf_sync_write()''' pour afficher cette image sur l'écran graphique.
    177179N'oubliez pas de tester systématiquement la valeur du code de retour chaque fois que vous utilisez un appel système.
    178180Modifiez le Makefile pour utiliser main_1.c au lieu de main_0.c, compilez le logiciel embarqué, et exécutez-le sur le simulateur.
     
    193195composant !VciTimer peut contenir jusque 256 timers indépendants, on utilisera un seul composant !VciTimer.
    194196
    195  * Le GIET ne pouvant supporter que 8 processeurs, on vérifiera que le paramètre NPROCS est inférieur ou égal à 8.
    196 
    197  * Il faut définir des tableaux de pointeurs indexés par l'index du processeurs (proc_id) pour les composants répliqués PROC[i], TTY[i] et ICU[i] ainsi que pour les signaux connectés à ces composants.
     197 * Le GIET ne pouvant supporter que 8 processeurs, on vérifiera dans le code de la top-cell que le paramètre NPROCS est inférieur ou égal à 8.
     198
     199 * Pour les composants répliqués PROC[i], TTY[i] et ICU[i] ainsi que pour les signaux connectés à ces composants, il   faut définir des tableaux de pointeurs indexés par l'index du processeurs (proc_id).
    198200
    199201 * Pour les tableaux de signaux, il est recommandé d'utiliser le constructeur générique de tableaux '''alloc_elems<type>(name, size)'''. Ce constructeur est défini dans le fichier '''alloc_elems.h''', qu'il ne faut pas oublier d'inclure dans la top-cell.
     
    205207 * Pour l'index des cibles (TGTID), on utilisera les valeurs (0) à (6) pour les composants matériels non répliqués (ROM, RAM GCD, TIMER, IOC, DMA, FBF). On utilisera les valeurs (7) à ( 7 + NPROCS -1) pour les composants TTY[i]. On utilisera les valeurs (7 + NPROCS) à (7 + 2*NPROCS -1) pour les composants ICU[i].
    206208
    207  * il faut définir NPROCS segments pour les composants ICU[i]. L'adresse de base du segment associé au composant ICU[i] est définie comme : seg_icu_base + 0x00100000 * proc_id (cette contrainte est imposée par le GIET).
    208 
    209  * Il faut définir NPROCS segments pour les NPROCS TTY[i]. L'adresse de base du segment associé au composant ICU[i] est définie comme : seg_tty_base + 0x00100000 * proc_id (cette contrainte est imposée par le GIET).
     209 * il faut définir NPROCS segments pour les composants ICU[i]. L'adresse de base du segment associé au composant ICU[i] est définie comme : seg_icu_base + icu_segment_increment * proc_id. La valeur de cette variable devra donc  être définie dans le fichier '''tp4_top_multi.cpp pour le matériel, et dans le fichier '''ldscript''' pour le logiciel. On prendra par exemple la valeur 0x00100000.
     210
     211 * Il faut définir NPROCS segments pour les NPROCS TTY[i]. L'adresse de base du segment associé au composant ICU[i] est définie comme : seg_tty_base + tty_segment_increment * proc_id. On prendra  également la valeur 0x00100000.
    210212
    211213 * Pour la net-list, il faut utiliser des boucles indexées par l'index du processeur pour connecter les composants répliqués et signaux répliqués.
     
    221223Un vrai système d'exploitation tel que LINUX (ou MutekH) permet de créer dynamiquement de nouvelles tâches (i.e. de nouveaux programmes utilisateurs) alors que la machine est déjà démarrée (mécanisme ''pthread_create()'' pour les threads POSIX, ou mécanisme fork/exec pour les processus UNIX). Le GIET n'est pas un vrai système d'exploitation, car il ne supporte pas la création ou la destruction dynamique de tâches : Les tâches doivent être créées une fois pour toute au démarrage de la machine, c'est à dire dans le code de boot.
    222224
    223 Bien que le GIET supporte le fonctionnement multi-tâches (un seul processeur exécute plusieurs tâches en pseudo-parallélisme par multiplexage temporel), on va utiliser ici un mécanisme plus simple où chaque processeur n'exécute qu'une seule tâche, qui lui est assignée dans le code de boot.
     225On va utiliser ici un mécanisme simple où chaque processeur n'exécute qu'une seule tâche, qui lui est assignée une fois pour toutes dans le code de boot.
    224226
    225227Le mécanisme est le suivant :