TP2: Déploiement de l'application MJPEG sur une architecture SoC monoprocesseur
}}}
[[PageOutline]]
TP Précédent: MjpegCourse/Station
= 0. Objectif =
La première partie de ce TP vise à montrer comment décrire - avec DSX -
une architecture matérielle de système intégré sur puce, en utilisant les
composants matériels de la bibliothèque SoCLib. On rappelle que la
bibliothèque SoCLib contient un ensemble modèles de simulation de composants
matériels (IP cores), décrits en langage SystemC. L'intérêt d'utiliser DSX
(plutôt que de décrire directement l'architecture en langage SystemC),
est qu'il permet de décrire facilement des architectures génériques
(nombre variable de processeurs ou de bancs mémoire par exemple).
La seconde partie du TP vous permettra d'utiliser DSX pour décrire et
contrôler précisément le déploiement de l'application logicielle !SplitMsg
(TCG décrit avec DSX), sur l'architecture matérielle décrite dans la première
partie. On validera ce déploiement en simulant l'exécution d>u code binaire
de l'application logicielle (généré par DSX) sur le modèle SystemC de
l'architecture matérielle (également généré par DSX).
La troisième partie du TP vous permettra d'atteindre notre véritable but, qui est
de de déployer l'application MJPEG du TP1 sur l'architecture de SoC monoprocesseur
décrite dans la première partie, en contrôlant précisément le placement des tâches sur
les processeurs ou coprocesseurs, et le placement des tampons de communication
sur les bancs mémoire embarqués.
= 1. Description de l'architecture matérielle =
On se limitera dans ce TP à une architecture ne contenant qu'un seul processeur
programmable de type MIPS R3000. Cette architecture matérielle est
appelée '!VgmnNoirqMono'.
[[Image(MjpegCourse/VgmnNoirqMono:vgmn_noirq_mono.png, align=right)]]
* Elle est organisée autour d'un micro-réseau générique à interface VCI (composant VGMN).
Ce composant est générique en ce sens qu'il accepte un nombre quelconque d'inititiateurs
VCI, et un nombre quelconque de cibles VCI, ainsi qu'un paramètre définissant
la latence du réseau: nombre minimal de cycles pour une traversée du réseau
"one-way".
* Elle comporte un contrôleur de verrous (composant LOCKS), utilisé pour protéger
l'accès aux canaux de communication MWMR.
* Elle comporte deux contrôleurs mémoire RAM0 et RAM1
* Elle comporte un contrôleur de terminal TTY.
'''Attention''': les deux coprocesseurs matériels d'entrée/sortie TG et RAMDAC, ne doivent
pas être décrits dans l'architecture !VgmnNoirqMono. Ces deux coprocesseurs, ainsi que
les deux contrôleurs MWMR leur permettant d'accéder aux canaux MWMR ne sont utilisés
que par l'application MJPEG, et pas par l'application !SplitMsg. Ils seront
automatiquement générés dans la phase de "déploiement" de l'application MJPEG,
lorsqu'on précisera que les tâches `tg` et `ramdac` du TCG sont implémentés comme des
composants matériels.
Commencez par créer un répertoire de travail TP2.
Pour faciliter la réutilisation, l'architecture matérielle est généralement décrite
dans un fichier séparé. Créez, dans le répertoire TP2, le fichier `vgmn_noirq_mono.py`.
[MjpegCourse/VgmnNoirqMono VgmnNoirqMono] contient une descrition incomplète que vous
devez compléter, en consultant la documentation SoclibComponents qui définit les
paramètres des différents composants de la bibliothèque SoCLib.
[[Image(MjpegCourse:q.gif)]] Q1: '''''Quelle est la syntaxe utilisée par DSX pour exprimer
que le port P,,0,, du composant matériel C,,0,, est connecté au port P,,1,, du composant matériel C,,1,,?'''''
Une fois la description de la plateforme complète, nous pouvons la tester en générant
une netlist SystemC décrivant la ''top-cell''. Créez un fichier contenant:
{{{
#!/usr/bin/env python
from vgmn_noirq_mono import VgmnNoirqMono
archi = VgmnNoirqMono()
archi.generate(Caba())
}}}
* Rendez ce nouveau fichier de description exécutable, lancez-le. Ne réalisez pas la compilation
de la plateforme résultante: nous n'avons pas encore de logiciel à exécuter dedans.
Si tout se passe bien, vous devriez avoir un nouveau répertoire `caba` dans le répertoire courant.
La description SystemC de la ''top-cell'' est dans `caba/top.h.new`. DSX alloue automatiquement des adresses aux
segments mémoire pour lesquels les adresses de base ne sont pas imposées par l'utilisateur.
[[BR]]
[[Image(MjpegCourse:q.gif)]] Q2: '''''Visualisez le fichier de "top-cell" pour déterminer les adresses
et les tailles des 6 segments de l'espace adressable définis dans cette application.'''''
= 2. Déploiement de l'application SplitMsg =
On va commencer par déployer l'application !SplitMsg, qui ne comporte que deux tâches et un canal
sur notre architecture de SoC monoprocesseur.
* Créez dans le répertoire TP2 un sous-répertoire 'splitmsg' (Important!)
* Recopiez dans ce répertoire la description DSX de l'application !SplitMsg du TP1.
* Modifiez cette description DSX en ajoutant après la description du TGG l'instanciation de l'architecture matérielle !VgmnNoirqMono.
{{{
#########################################################
# Section B : Hardware architecture
#
# The file containing the architecture definition
# must be included, and the path to the directory
# containing this file must be defined
#########################################################
from soclib import *
import sys
sys.path.append("..")
from vgmn_noirq_mono import VgmnNoirqMono
archi = VgmnNoirqMono()
}}}
* Définissez le mapping de l'application !SplitMsg sur l'architecture !VgmnNoirqMono.
Vous devez consulter la page DsxMapping pour plus d'informations.
Dans cette section, un objet `Mapper` doit être créé.
Supposons qu'on crée une variable `mapper`, l'architecture matérielle doit
être référencée à travers mapper.hard.''nom'' pour accéder aux composants
créés par self.''nom'' dans la description de la plateforme.
De même les objets logiciels doivent être accédés à travers mapper.tcg!['nom'].
Il va falloir placer toutes les tâches, tous les canaux de communication,
tous les objets logiciels associés aux processeurs et enfin les objets globaux du système.
{{{
#########################################################
# Section C : Mapping
#
#########################################################
mapper = Mapper(archi, tcg)
# mapping the "prod0" and "cons0" tasks
mapper.map("prod0",
run = mapper.hard.processor,
stack = mapper.hard.cram0,
desc = mapper.hard.cram0,
status = mapper.hard.uram0,
code = mapper.hard.cram0)
mapper.map("cons0",
run = mapper.hard.processor,
stack = mapper.hard.cram0,
desc = mapper.hard.cram0,
status = mapper.hard.uram0,
code = mapper.hard.cram0)
# mapping the MWMR channel
mapper.map( "fifo",
lock = mapper.hard.locks,
status = mapper.hard.cram1,
desc = mapper.hard.cram1)
# mapping the software objects associated to a processor
mapper.map("processor",
desc = mapper.hard.cram0,
priv = mapper.hard.cram0,
status = mapper.hard.uram0)
# mapping the software objects used by the embedded OS
mapper.map(mapper.tcg,
desc = mapper.hard.cram1,
shared = mapper.hard.uram1,
code = mapper.hard.cram1)
}}}
* La dernière étape consiste à générer le code
{{{
######################################################
# Section D : Code generation
######################################################
# Embedded software linked with the Mutek/S OS
# SystemC simulator for the hardware architecture at Cycle Accurate/Bit Accurate abstraction level
muteks = MutekS()
simulator = Caba()
mapper.generate( muteks, simulator )
# The software application for a POSX workstation can still be generated
posix = Posix()
tcg.generate(posix)
# Global Makefile generation
TopMakefile( muteks, simulator, posix )
}}}
[[Image(MjpegCourse:q.gif)]] Q3: '''''Quels objets logiciels doit-on placer dans
l'espace addressable pour une tâche ? pour un canal mwmr ? pour un processeur ?'''''
* Relancez l'exécution de la description DSX de votre application
{{{
$ ./SplitMsg.py
}}}
* Générez le code binaire et le modèle SystemC de l'architecture matérielle.
{{{
$ make
}}}
Une fois la compilation effectuée, visualisez le fichier de "top cell" généré par DSX spécifiquement pour
ce déploiement. Il se situe dans muteks/caba/top.h. Déterminez les adresses
et les tailles des 6 segments de l'espace adressable définis dans cette application.[[BR]]
[[Image(MjpegCourse:q.gif)]] Q4: '''''En quoi diffèrent-ils de ces mêmes segments
vus à la question 2 ?'''''
* Executez l'application logicielle sur la station de travail
{{{
$ ./exe.posix
}}}
* Simulez l'exécution de l'application logicielle sur le modèle SystemC du SoC
{{{
$ ./exe.muteks_caba
}}}
[[Image(MjpegCourse:q.gif)]] Q5: '''''Qu'observez-vous ? En quoi est-ce différent de ce
qui se passe dans la version pour station de travail ?'''''
= 3. Déploiement de l'application MJPEG =
L'application MJPEG est différente de l'application !SplitMsg car elle utilise deux
périphériques d'entrée/sortie spécialisés :
* le coprocesseur ''Tg'': un composant matériel qui récupère le flux binaire MJPEG
(en analysant un signal radio-fréquence par exemple), effectue la conversion
analogique/numérique et écrit le résultat dans un canal MWMR
* le coprocesseur ''Ramdac'': un composant matériel qui lit une image décompressée
dans un canal MWMR et génère le signal video pour affichage sur l'écran.
Pour pouvoir déployer ces deux tâches sous forme de coprocesseurs matériels, il faut
prévenir DSX qu'il existe des coprocesseurs implémentant ces tâches. Nous allons donc
modifier les déclarations des modèles de tâches en conséquence.
Retournez dans le répertoire mjpeg du TP1, et exécutez la commande {{{make mrproper}}}
qui détruit tous les fichiers générés par les différentes compilations effectuées.
Ce ménage est indispensable pour vous éviter de dépasser votre quota d'espace
disque. Recopiez ce répertoire `mjpeg` nettoyé dans votre répertoire TP2.
Dans la description DSX de l'application MJPEG, modifiez la définition des modèles de tâches
`tg` et `ramdac` pour introduire leurs implémentations matérielles.
Comme ces deux implémentations sont définies dans soclib, la directive
{{{from soclib import *}}} doit être présente avant la description des tâches dans
votre fichier de description.
* Pour la tâche `tg`, ajoutez un deuxième élément dans la liste des implémentations disponibles:
{{{
tg = TaskModel( 'tg',
outfifos = [ 'output' ],
impl = [ SwTask( 'tg',
stack_size = 1024,
sources = [ 'src/tg.c' ],
defines = [ 'FILE_NAME' ] ),
HwTask( Tg )
] )
}}}
* De même, pour la tâche `ramdac`, ajoutez l'implémentation suivante:
{{{
HwTask( Ramdac )
}}}
* En vous inspirant de ce qui a été fait pour déployer !SplitMsg, déployez l'application MJPEG
sur la plateforme.
* Les coprocesseurs `tg` et `ramdac` sont spécifiques, ils doivent
faire l'objet d'un déploiement non pas en tant que tâches logicielles sur un processeur, mais
en tant que coprocesseurs rattachés par un contrôleur MWMR à un interconnect VCI. Le déploiement
valide pour `tg` est par exemple:
{{{
mapper.map( 'tg0',
vci = mapper.hard.vgmn )
}}}
* De même déployez `ramdac` sur la plateforme.
* Relancez la description, recompilez, lancez la simulation. Ajoutez le flag `-e` sur la ligne de commande
pour que la simulation ne soit pas limitée au premier million de cycles.
{{{
$ ./description
$ make
$ ./exe.muteks_caba -e
}}}
L'avion fait le "tour" en 25 images. Vous avez un compteur de cycles sur le terminal qui contient le simulateur.
[[BR]]
[[Image(MjpegCourse:q.gif)]] Q6: '''''Combien faut-il de cycles, approximativement, pour décompresser 25 images ?'''''
[[Image(MjpegCourse:q.gif)]] Q7: '''''Supposant un SoC cadencé à 200MHz, combien d'images sont affichées en une seconde ?'''''
= 4. Influence du système d'exploitation embarqué =
L'environnement DSX permet actuellement d'utiliser deux systèmes d'exploitation embarqués.
* Mutek/S, un micro-noyau "statique" , très performant, mais ne fournissant pas la compatibilité POSIX. En particulier, il ne permet pas la création dynamique de tâches au moment de l'exécution.
* Mutek/D, un micro-noyau fournissant aux applications l'API des threads POSIX (y compris la création dynamique de tâches).
Modifiez la description DSX de l'application MJPEG, pour utiliser l'OS Mutek/D. La section D devient:
{{{
muteks = MutekS()
simulator_s = Caba()
mapper.generate( muteks, simulator_s )
mutekd = MutekD()
simulator_d = Caba()
mapper.generate( mutekd, simulator_d )
posix = Posix()
tcg.generate(posix)
TopMakefile( muteks, simulator_s, mutekd, simulator_d, posix )
}}}
Il faut définir deux simulateurs différents (simulator_s et simulator_d) suivant qu'on utilise MUTEK/S ou MUTEK/D,
car DSX calcule automatiquement la capacité des deux bancs mémoire physique en fonction des la taille des différents
objets logiciels à ranger en mémoire. Le code généré pour MUTEK/S étant beaucoup plus compact, on a des mémoires
plus petites dans le cas de MUTEK/S.
(Notez le changement dans la `TopMakefile`)
* Relancez la description, recompilez, lancez la simulation du SoC avec Mutek/D
(attention, il y a deux simulateurs avec des noms différents)
{{{
$ ./description
$ make
$ ./exe.mutekd_caba -e
}}}
[[Image(MjpegCourse:q.gif)]] Q8: '''''Combien de cyles faut-il pour décompresser 25 images avec MUTEK/D? Comment expliquer ce résultat?'''''
[[Image(MjpegCourse:q.gif)]] Q9: '''''En consultant la description SystemC de l'architecture matérielle générée par DSX, déterminez la capacité mémoire des deux bancs mémoire RAM0 et RAM1 suivant qu'on utilise MUTEK/S ou MUTEK/D.'''''
= 5. Compte-rendu =
Vous rendrez une archive dans le même format que la semaine précédente, nommée `binome0_binome1.tar.gz`, contenant exactement les fichiers:
{{{
tp2/
tp2/rapport.pdf
tp2/vgmn_noirq_mono.py
tp2/splitmsg/
tp2/splitmsg/producer.c
tp2/splitmsg/consumer.c
tp2/splitmsg/splitmsg.py
tp2/mjpeg/mjpeg.py
tp2/mjpeg/src/
tp2/mjpeg/src/iqzz.c
tp2/mjpeg/src/libu.c
}}}
* Les fichiers `splitmsg.py` et `mjpeg.py` seront complets, avec vos descriptions de tâches et le mapping.
Pour mjpeg, il y aura les directives de génération de code pour Mutek/S et Mutek/D.
* Le répertoire `mjpeg/src` contiendra uniquement les implémentation de vos deux tâches libu et iqzz
(éventuellement mises à jour par rapport à la semaine dernière) vous ayant servi à exécuter les tests de ce TP.
* Le rapport sera court (une table des matières pour dire que tout est sur la même page est superflue), répondant aux questions
posées dans le texte, nommé `tp2/rapport.pdf`.
Vous livrerez cette archive avant mardi 20 fevrier 2007, 18h00 à [MailAsim:nipo Nicolas Pouillon].
= Suite =
TP Suivant: MjpegCourse/Multipro