wiki:SujetTP8

ALMO TP n°8 - Périphériques orientés blocs

Préambule

L'objectif de ce TP est d'analyser le comportement d'une application logicielle de manipulation d'image s'exécutant sur la plateforme matérielle rappelée ci-dessous.

Les différentes lignes d'interruptions sont connectées comme suit :

  • L'interruption du Contrôleur I/O est connectée à l'entrée IRQ[0] de l'ICU.
  • L'interruption du TIMER est connectée à l'entrée IRQ[1] de l'ICU.
  • L'interruption du Contrôleur DMA est connectée à l'entrée IRQ[2] de l'ICU.
  • L'interruption du contrôleur TTY est connectée à l'entrée IRQ[3] de l' ICU.

On cherche essentiellement à mesurer le temps moyen de traitement d'une image, en nombre de cycles du processeur. Le traitement d'une image se décompose en trois étapes, comme expliqué dans le TD associé :

  • phase Load : chargement de l'image depuis un fichier sur disque vers un premier tampon mémoire appelé buf_in.
  • phase Modif : modification de cette image et recopie de l'image modifiée dans un second tampon mémoire appelé buf_out.
  • phase Display : affichage de l'image modifiée par copie du tampon buf_out vers la mémoire vidéo.

Comme d'habitude, commencez par recopier dans votre répertoire de travail les fichiers sources spécifiques à ce TP :

$ cp -r /Infos/lmd/2019/licence/ue/LU3IN004-2019oct/sesi-almo/soft/tp08/sujet ./tp08
$ cd tp08

Les images à afficher sont stockées dans le fichier images.raw, qui contient une séquence de 20 images. Pour réduire les temps de simulation, les images sont de petites tailles : 128 lignes de 128 pixels. Chaque pixel est codé sur un octet en 256 niveaux de gris.

Le simulateur utilisé est toujours simul_almo_generic.

1. Application séquentielle sans DMA

Dans un premier temps, on va déterminer les temps d'exécution de chacune des trois phases de traitement grâce à une application logicielle séquentielle qui exécute successivement les trois phases pour chaque image : chargement, modification et affichage, en affichant sur un terminal TTY la date de terminaison de chaque phase.

Les segments associés aux trois nouveaux périphériques (DMA, IOC et FBF) sont implantés aux adresses suivantes dans la zone protégée de l'espace adressable :

  1. seg_ioc_base se situe à l'adresse 0x92000000.
  2. seg_dma_base se situe à l'adresse 0x93000000.
  3. seg_fb_base se situe à l'adresse 0x96000000.
  • Complétez le fichier de script ld nommé seg.ld pour y définir les adresses de base de ces 3 nouveaux segments.
  • Ouvrez maintenant le fichier reset.s et complétez le de façon à installer dans le vecteur d'interruption les 4 ISR correspondant aux quatre périphériques présents dans la plateforme matérielle. Vous devez regarder le fichier irq_handler.c pour déterminer les noms de ces 4 ISR. Il faut également configurer le composant ICU pour qu'il laisse passer ces 4 lignes d'interruption.
  • Complétez le fichier main.c qui contient la fonction principale main(), en précisant les valeurs des arguments des différents appels systèmes. Vous devez regarder les fichiers stdio.[ch] pour vérifier le type et la signification des arguments. N'oubliez pas qu'il faut lire une nouvelle image dans le fichier à chaque itération dans la boucle.
    • En quoi consiste la modification de l'image réalisée par cette application avant affichage ?
  • Compilez le système logiciel en utilisant le Makefile qui vous est fourni, puis lancez l'exécution de la simulation avec la commande donnée ci-dessous.
    • L'option -IOCFILE informe le simulateur que la plateforme contient un contrôleur I/O sur disque, et que le fichier représentant le disque est images.raw.
    • L'option -FBFSIZE informe le simulateur que la plateforme contient un contrôleur graphique et que le tampon qui lui est associé a une capacité de 128 lignes de 128 pixels.
    • Les deux options -NICACHE et -NDCACHE permettent d'augmenter la capacité des caches L1.
$ simul_almo_generic -SYS sys.bin -APP app.bin -IOCFILE images.raw -FBFSIZE 128 -NICACHE 512 -NDCACHE 512
  • Relevez les dates correspondant aux événements significatifs. Les durées observées se comptant en centaines de milliers de cycles, on arrondira les dates à des multiples de 1000 cycles et on utilisera comme unité le Kcycle (1 Kcycle = 1000 cycles).
  • Construisez un tableau contenant, pour chacune des 5 images, la durée de la phase de chargement, la durée de la phase de traitement, et la durée de la phase d'affichage.

2. Application séquentielle avec DMA

L'appel système bloquant fb_sync_write() utilisé dans la première partie du TP effectue le transfert de la phase Display par une technique purement logicielle de type memcpy : chaque octet est successivement lu dans le tampon buf_out, puis écrit dans le tampon vidéo. Cette technique n'est pas très efficace pour deux raisons : d'une part, elle génère beaucoup de transactions sur le bus (deux transactions pour transférer un seul octet), et d'autre part, le processeur ne peut être utilisé pour faire d'autres calculs puisque c'est lui qui déplace les données en exécutant des instructions de lecture et d'écriture en mémoire. On va donc utiliser le contrôleur DMA disponible dans la plateforme pour accélérer le transfert dans la phase Display.

  • Sauvez le fichier main.c sous un autre nom, puis éditez-le et modifiez l'application pour que la phase Display utilise dorénavant l'appel système non-bloquant fb_write(), qui configure et démarre le contrôleur DMA pour que celui-ci effectue le transfert du tampon buf_out vers le tampon vidéo par rafales de 32 mots (128 octets). Notez que l'application logicielle doit maintenant utiliser l'appel système bloquant fb_completed() pour s'assurer que le transfert est terminé avant de passer à l'image suivante.
  • Recompilez l'application, puis relancez l'exécution. Relevez les dates correspondant aux événements significatifs, et reconstruisez un tableau similaire à celui de la partie précente. Qu'observez-vous ?

3. Application pipe-line

Il est possible de réduire encore la durée moyenne de traitement d'une image, en remarquant que durant la phase Load (chargement d'une image depuis le disque vers le tampon buf_in), ainsi que pendant la phase Display, le processeur ne fait aucun traitement utile.

On va donc essayer de paralléliser les trois phases Load, Modif et Display, en écrivant une application qui traite jusqu'à trois images à la fois, en utilisant le fait qu'on possède 3 processeurs ou coprocesseurs : le contrôleur I/O, le processeur MIPS32 et le contrôleur DMA. Le schéma (presque) périodique de fonctionnement pipe-line est décrit ci-dessous.

Il faut maintenant deux tampons mémoire d'entrée, buf_in_0 et buf_in_1, que l'on utilise alternativement pour stocker les images paires et impaires venant du disque, ainsi que deux tampons mémoire de sortie, buf_out_0 et buf_out_1, pour stocker les images modifiées paires et impaires.

Période 0 Période 1 Période 2 Période 3 Période 4 Période 5 Période 6
IOC Load[0] Load[1] Load[2] Load[3] Load[4]
MIPS32 Modif[0] Modif[1] Modif[2] Modif[3] Modif[4]
DMA Display[0] Display[1] Display[2] Display[3] Display[4]

Le fonctionnement général est le suivant :

  • Durant les périodes paires :
    1. Chargement de l'image (2 * i) dans buf_in_0,
    2. Modification de l'image (2 * i - 1) stockée dans buf_in_1 et écriture dans buf_out_1,
    3. Transfert de l'image (2 * i - 2) stockée dans buf_out_0 vers la mémoire vidéo.
  • Durant les périodes impaires :
    1. Chargement de l'image (2 * i + 1) dans buf_in_1,
    2. Modification de l'image (2 * i) stockée dans buf_in_0 et écriture dans buf_out_0,
    3. Transfert de l'image (2 * i - 1) stockée dans buf_out_1 vers la mémoire vidéo.

Grâce à l'utilisation alternative des tampons mémoires pairs et impairs, à aucun moment on ne lit et on n'écrit simultanément dans le même tampon.

  • Sauvez le fichier main.c sous un autre nom, puis éditez-le et modifiez l'application pour qu'elle respecte le 7 périodes décrites ci-dessus. Pour simplifier, on se limitera à une séquence de 5 images et on n'utilisera pas de boucle.

Attention : il faut s'assurer que les traitements parallèles exécutés dans la période (n) sont terminés quand on passe de la période (n) à la période (n + 1). On introduira dans le programme l'affichage des dates permettant de déterminer les durées d'exécutions des 7 périodes.

  • Recompilez, relancez l'exécution, et relevez les dates permettant de déterminer les durées d'exécution. Quel est le temps de traitement d'une image quand on est en régime établi (périodes 2, 3 et 4) ?
  • Améliorez l'application pour qu'elle puisse traiter une séquence d'images de longueur quelconque. Cette application doit comporter 3 parties :
    • un prologue correspondant au remplissage initial du pipe-line (ce prologue correspond aux périodes 0 et 1 de l'application en 7 périodes)
    • une boucle permettant de traiter un nombre quelconque d'images en régime établi (ceci correspond aux périodes 2, 3 et 4 de l'application en 7 périodes)
    • un épilogue permettant de vider le pipe-line (cet épilogue correspond aux périodes 5 et 6 de l'application en 7 périodes)
Last modified 5 years ago Last modified on Aug 26, 2019, 11:16:04 AM