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. |
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 |
| 216 | processeur. 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 |
| 220 | terminal é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. |
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 | | |
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? |
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''. |
| 250 | Pour cela, on demande à GCC de construire une table de sauts au début du segment ''seg_data'', contenant les adresses |
| 251 | des 4 points d'entrée dans les 4 tâches allouées aux 4 processeurs. |