Changes between Version 100 and Version 101 of SoclibCourseTp4


Ignore:
Timestamp:
Dec 12, 2013, 11:33:58 AM (11 years ago)
Author:
alain
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • SoclibCourseTp4

    v100 v101  
    193193= 5. Architecture multi-processeurs générique =
    194194
    195 On veut maintenant modéliser une architecture matérielle multi-processeur générique, où le nombre de processeurs est défini par un paramètre NPROCS sur la ligne de commande.
     195On veut maintenant modéliser une architecture matérielle multi-processeur générique, où le nombre de processeurs peut varier entre 1 et 4. Ce paramètre NPROCS sera défini sur la ligne de commande.
    196196
    197197== 5.1 architecture matérielle ==
    198198
    199199Vous devez modifier le fichier '''tp4_top.cpp''' pour créer un nouveau fichier '''tp4_top_multi.cpp''' .
    200 Chaque processeur a besoin de son propre concentrateur d'interruption. Le composant matériel '''vci_icu''' est un composant mono-canal, qui ne peut servir
    201 qu'un seul processeur. Il faut donc utiliser le composant matériel multi-canaux '''vci_multi_icu''', qui peut servir jusqu'à 8 processeurs. Vous pouvez consulter la documentation ici.
    202 
    203 Comme chaque processeur peut - en principe - exécuter plusieurs tâches en pseudo-parallélisme, et que chaque tâche possède un terminal privé, on peut avoir un grand nombre de terminaux. On aura donc un contrôleur TTY indépendant pour chaque processeur.
    204 Pour ce qui concerne les timers, on souhaite avoir un timer indépendant pour chaque processeur, mais puisque le composant !VciTimer peut contenir jusque 256 timers indépendants, on utilisera un seul composant !VciTimer.
    205 On aura également un seul contrôleur de disque et un seul contrôleur DMA.
    206200
    207201Pour écrire ce modèle générique, vous suivrez les recommandations suivantes:
    208202
    209  * 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.
    210 
    211  * Pour les composants répliqués PROC[i], TTY[i] et ICU[i] ainsi que pour les signaux connectés à ces composants, vous définirez des tableaux de pointeurs indexés par l'index du processeurs (proc_id).
     203 * On vérifiera dans le code de la top-cell que le paramètre NPROCS est plus grand que 0 et inférieur ou égal à 4.
     204
     205 * Pour les composants répliqués PROC[i] ainsi que pour les signaux connectés à ces composants, vous définirez des tableaux de pointeurs indexés par l'index du processeurs (proc_id).
    212206
    213207 * 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.
    214208
    215  * Vous utiliserez une boucle indexée par l'index du processeur pour les constructteurs des composants PROC[i], ICU[i], et TTY[i].
     209 * Vous utiliserez une boucle indexée par l'index du processeur pour les constructteurs des composants PROC[i].
     210
     211 * Chaque processeur a besoin de son propre concentrateur d'interruption. Le composant matériel !VciIcu est un composant mono-canal, qui ne peut servir qu'un seul processeur. Il faut donc utiliser le composant matériel multi-canaux !VciMultiIcu, qui peut servir jusqu'à 8 processeurs. Vous pouvez consulter la documentation [https://www.soclib.fr/trac/dev/wiki/Component/VciMultiIcu ici].
     212
     213 * Pour ce qui concerne les timers, on souhaite avoir un timer indépendant pour chaque processeur, mais puisque le composant !VciTimer peut contenir jusque 256 timers indépendants, on utilisera un seul composant !VciTimer.
     214
     215 * Pour ce qui concerne le contrôleur DMA, on souhaite également avoir un canal DMA indépendant pour chaque
     216processeur. Il faut donc utiliser le composant matériel !VciMultiDma dont vous pouvez consulter la documentation
     217[https://www.soclib.fr/trac/dev/wiki/Component/VciMultiDma ici].
     218
     219 * Puisque chaque processeur peut exécuter 4 tâches en parallèle, et que chaque tâche doit disposer de son propre
     220terminal écran/clavier, le nombre de terminaux controlés par le composant !VciMultiTty est égal à 4*NPROCS.
     221
     222 * Pour ce qui concerne l'accès au disque, on aura un seul contrôleur de disque !VciBlockDevice pour toutes les applications.
    216223
    217224 * Pour l'index des initiateurs (SRCID), vous utiliserez les valeurs 0 à (NPROCS-1) pour les processeurs, et les valeurs NPROCS et (NPROCS+1) pour le composant IOC et pour le composant DMA respectivement.
    218225
    219  * Pour l'index des cibles (TGTID), vous utiliserez 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].
    220 
    221  * 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 dans le GIET comme : seg_icu_base + icu_segment_increment * proc_id. La valeur de cette variable ''icu_segment_increment'' 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.
    222 
    223  * Il faut définir NPROCS segments pour les NPROCS TTY[i]. L'adresse de base du segment associé au composant TTY[i] est définie dans le GIET comme : seg_tty_base + tty_segment_increment * proc_id. On prendra  également la valeur 0x00100000 pour la variable ''tty_segment_increment''.
    224 
    225226 * Pour la net-list, vous utiliserez des boucles indexées par l'index du processeur pour connecter les composants répliqués et signaux répliqués.
    226227 
    227  * Les interruptions non-répliquées (IRQ_IOC, IRQ_DMA) seront connectées au contrôleur d'interruptions ICU[0]. Les interruptions répliquées IRQ_TTY[i] et IRQ_TIMER[i] seront connectées au concentrateur d'interruptions ICU[i].
     228 * Puisque l'architecture contient maintenant plusieurs périphériques multi-canaux (ICU, TTY, TIMER, DMA) les longueurs des segments alloués à ces périphériques doivent être ajustées en conséquence.
     229
     230 * L'interruption IRQ_IOC sera connectée à l'entrée p_irq_in[0] du composant ICU. Les 4 interruptions répliquées IRQ_DMA[0:3] seront connectée aux entrées p_irq_in[4:7]. Les 4 interruptions IRQ_TIM[0:3] seront connectées aux entrées p_irq_in[8:11] Les 16 interruptions IRQ_TTY[0:15] seront connectées aux entrées p_irq_in[16:31].
     231
     232'''Question''' : Pour quelle raison les valeurs stockées dans les 4 registres de masque ICU_MASK[k] associés aux 4 canaux du composant !VciMultiIcu doivent-elles être non-recouvrantes?
     233
     234'''Question''' : Puisqu'il n'existe qu'un seul contrôleur de disque, qui peut - en principe - être utilisé par toutes les applications, comment le GIET doit-il gèrer les accès concurrents?
    228235
    229236'''Question''' : Modifiez le fichier '''tp4_top.cpp''' pour rendre l'architecture générique, conformément aux recommandations ci-dessus.
     
    233240== 5.2 Code de boot multi-processeurs ==
    234241
    235 Un 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.
     242Un vrai système d'exploitation tel que LINUX permet de lancer 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.
    236243
    237244On 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.
    238245
    239246Le mécanisme est le suivant :
    240  * Tous les processeurs exécutent le même code de boot, mais l'exécution de ce code dépend de l'index du processeur. L'index du processeur (''proc_id'') étant stocké dans le registre système ($15, 1) du processeur MIPS32, sa valeur peut être testée par le logiciel. Remarquez que la valeur de ce registre est initialisée par le constructeur, ce qui modélise une valeur ''cablée'' lors de la fabrication de la puce.
    241  * Les tâches s'exécutant en parallèle, chaque tâche (et donc chaque processeur) doit disposer de sa propre pile d'exécution. On définit un seul segment pour les différentes piles d'exécution, mais les ponteurs de pile des différents processeurs doivent  être initialisés à des  valeurs différentes en fonction du ''proc_id''.
    242  * Chaque processeur exécutant un programme utilisateur différent, le points d'entrée du programme  (registre EPC dans le cas du MIPS32) doit être initialisé à une valeur dépendant du ''proc_id''  (main_0, main_1, main_2, ... main_7).
     247 * Tous les processeurs exécutent le même code de boot, mais l'exécution de ce code dépend de l'index du processeur. L'index du processeur (''proc_id'') étant stocké dans le registre système ($15, 1) du processeur MIPS32, sa valeur peut être testée par le logiciel. Remarquez que la valeur de ce registre est initialisée par le constructeur C++, ce qui modélise une valeur ''cablée'' lors de la fabrication de la puce.
     248 * Les tâches s'exécutant en parallèle, chaque tâche (et donc chaque processeur) doit disposer de sa propre pile d'exécution. On définit un seul segment pour les différentes piles d'exécution, mais les pointeurs de pile des différents processeurs doivent  être initialisés à des  valeurs différentes en fonction du ''proc_id''.
     249 * Chaque processeur exécutant un programme utilisateur différent, le points d'entrée du programme  (registre EPC dans le cas du MIPS32) doit être initialisé à une valeur dépendant du ''proc_id''.
     250Pour cela, on demande à GCC de construire une table de sauts au début du segment ''seg_data'', contenant les adresses
     251des 4 points d'entrée dans les 4 tâches allouées aux 4 processeurs.
    243252
    244253== 5.3 Exécution parallèle sur architecture bi-processeurs ==
    245254 
    246255On commence par générer le code binaire pour une architecture comportant seulement 2 processeurs,
    247 de façon à exécuter en parallèle des deux programmes ''main_0'' et ''main_1'' définis dans la section précédente.
     256de façon à exécuter en parallèle des deux programmes ''main'' et ''main_display'' utilisés au début de ce TP.
    248257On s'efforcera cependant que ce code de boot soit facilement extensible pour s'adapter à des architectures contenant plus de 2 processeurs
    249258
     
    269278
    270279'''Question''' : Modifiez les fichiers '''reset.s''', '''ldscript''', et '''Makefile''' du répertoire '''soft''' pour les adapter au cas de 8 processeurs, compilez le logiciel embarqué puis lancez l'exécution sur le simulateur  '''simulator_multi.x''', avec 8 processeurs. 
     280
     281'''Question''' : Le GIET supporte des architectures contenant jusque 8 processeurs, et chaque processeur peut exécuter jusque 4 tâches en multiplexage temporel. Nous avons cependant limité l'architecture générique à 4 processeurs.
     282Quel est le facteur qui justifie cette limitation?
    271283
    272284= 6 Compte-rendu =