Brevet FR3103595A1 — publié le 20210528

Simulateur rapide d'un calculateur et d'un logiciel mis en œuvre par ce calculateur, le calculateur comprenant au moins un processeur, une hiérarchie mémoire comprenant plusieurs niveaux de mémoires caches, des mémoires externes et un réseau d'interconnexions assurant la communication entre les mémoires caches et les mémoires externes ; le simulateur comprenant une pluralité de co-simulateurs respectivement associés à une tâche, et étant configuré pour fonctionner par quantum d'instructions, un co-simulateur dit fonctionnel (CSF) étant configuré pour faire fonctionner le logiciel simulé en faisant abstraction de l'architecture du calculateur, au moins un autre co-simulateur dit architectural (CSAi) étant configuré pour simuler, en parallèle, le comportement architectural lié à l'architecture du calculateur et déterminer les valeurs de paramètres extra-fonctionnels du calculateur, et un module de transfert (MT) configuré pour transférer un événement signalé par le co-simulateur fonctionnel (CSF) à un co-simulateur architectural (CSAi) souscrit à cet événement. Figure pour l’abrégé : Fig. 5 Simulateur rapide d'un calculateur et d'un logiciel mis en œuvre par ce calculateur L’invention porte sur un simulateur rapide d'un calculateur et d'un logiciel mis en œuvre par ce calculateur, et un procédé correspondant. Un calculateur classique comprend une ou plusieurs unités de calcul ou processeurs, une hiérarchie mémoire comprenant plusieurs niveaux de mémoires caches (les calculateurs à hautes performances incluent typiquement trois niveaux de mémoires caches), des mémoires externes (dites RAM pour acronyme de "Random Access Memory" en langue anglaise) et un réseau d’interconnexions (NoC pour acronyme de "Network-on-Chip" en langue anglaise), assurant la communication entre les caches et les mémoires externes. De tels calculateurs peuvent également comprendre un certain nombre de périphériques, comme des contrôleurs série, des disques durs, ou des périphériques PCI (pour acronyme de "Peripheral Component Interconnect" en langue anglaise. Afin d’accélérer le développement de tels calculateurs, des prototypes virtuels rapides sont souvent réalisés dans les premières phases de conception, pouvant réduire le délai de mise sur le marché ou "time-to-market" en langue anglaise, principalement des deux manières qui suivent. Il est possible de prendre des décisions architecturales : le prototype virtuel peut modéliser les parties critiques de l’architecture du calculateur, comme les mémoires caches, et d’en tester différents modes de fonctionnement et différentes capacités afin de dimensionner correctement ces éléments pour l’architecture finale. Il est également possible d'utiliser un développement logiciel : avec un modèle fidèle du processeur, des logiciels peuvent être développés, débuggés et testés avant même que la plateforme physique ne soit disponible, permettant de paralléliser les conceptions matérielle et logicielle. Pour qu’un prototype virtuel soit utile, deux conditions doivent être remplies : - Il doit être disponible tôt, et donc pouvoir être développé rapidement. Les modèles développés sont donc souvent assez abstraits et non-détaillés. - Il doit être rapide, car le concepteur doit être capable de réaliser plusieurs itérations et tester différentes configurations rapidement. La rapidité du prototype virtuel se caractérise par la vitesse à laquelle il est capable d’exécuter le logiciel simulé. Typiquement, les simulateurs modernes sont capables de simuler plusieurs centaines de millions d’instructions par seconde (MIPS). Une technique très souvent adoptée pour remplir ces deux conditions, est la modélisation dite vaguement chronométrée ou "loosely-timed" en langue anglaise. Cette méthode modélise les différents composants (périphériques, mémoires) de manière assez abstraite, réduisant à la fois le temps de développement et le temps de conception. La modélisation loosely-timed, illustrée schématiquement sur la figure 1, opère comme suit. Le simulateur cède le contrôle à un des processeurs du système pendant un quantum d’instructions. Pendant toute la durée du quantum, le processeur exécute des instructions sans redonner la main au simulateur. Cela permet de réduire le nombre de changements de contexte du simulateur, et d'améliorer significativement les performances de simulation. Le modèle du processeur interprète les instructions du logiciel simulé. Ces instructions peuvent être des instructions arithmétiques ALU_instr() pour Arithmetic and Logic Unit instruction, qui peuvent être simulées très rapidement (typiquement en utilisant des opérateurs simples), des instructions d’accès entrées/sorties IO_access(), qui peuvent être simulées lentement (typiquement en utilisant des appels système), mais qui sont rares, et enfin des instructions d’accès mémoire RAM_access(), qui génèrent des transactions vers les modèles de mémoires caches, mémoires externes et réseau NoC pour simuler un accès mémoire. Chaque élément traversé pendant le quantum du processeur met à jour l’horloge locale du processeur en rajoutant sa propre latence. Par exemple, comme illustré sur la figure 1, la mémoire cache de premier niveau L1 Cache prend deux cycles, donc deux cycles sont rajoutés (T+=2) au temps local T du processeur. Sur l'exemple illustré, l’exécution de chaque instruction prend un cycle. On peut voir sur la figure 1 que le temps de simulation peut vite devenir problématique. En effet, le nombre d’accès mémoire dans un programme classique peut être très grand, et basculer constamment entre l’interprétation des instructions et la simulation de la hiérarchie mémoire a un impact sérieux sur la localité du code du simulateur. La localité du code correspond au fait d’exécuter les mêmes bouts de code plusieurs fois pendant l’exécution du simulateur. En effet, si l’interpréteur visite souvent les mêmes zones de code simples, une bonne partie des instructions exécutées peut rester en cache, ce qui est désirable pour une exécution fluide. Cependant, en faisant des transitions entre des instructions de l’interpréteur d’instructions et les modèles de mémoires caches, de réseaux de communications NoC et de mémoires externes RAM, qui peuvent être assez complexes, on obtient l'effet indésirable de réduire sévèrement cette localité. Etant donné la sévérité de ce problème, plusieurs solutions ont été proposées comme suit. Le document US 2018/0173825 A1 divulgue une approche consistant à paralléliser la simulation, en simulant chaque processeur dans une tâche, ou "thread" en langue anglaise, d’exécution unique. Cela permet d’avoir des accélérations significatives lorsque le nombre de cœurs simulés est grand, typiquement supérieur à 16. Cependant, cette approche ne s’attaque pas au problème de performance dû à la simulation des accès mémoires exposé précédemment. Aussi, pour la simulation d’un système embarqué classique, ayant entre quatre et huit cœurs de calculs, cette approche ne produit pas d’accélération. Les approches des documents Mutli-threaded TCG (Tiny Code Generator)", Bellard, F. (2005, April), QEMU, a fast and portable dynamic translato, in USENIX Annual Technical Conference, FREENIX Track (Vol. 41, p. 46), et "QEMU and SystemC in separate threads", de Delbergue, G., Burton, M., Konrad, F., Le Gal, B., & Jego, C. (2016, January), QBox: an industrial solution for virtual platform simulation using QEMU and SystemC TLM-2.0, in 8th European Congress on Embedded Real Time Software and Systems (ERTS 2016), ont pour but d’accélérer au maximum les simulations en mettant l’accent sur la localité du code. Afin de ne pas interrompre l’exécution du processeur durant un quantum, les accès mémoires sont traduits par de simples accès à la mémoire RAM de la machine hôte (machine exécutant la simulation). Bien sûr, cela ne permet donc pas d’avoir un prototypage suffisamment détaillé pour pouvoir dimensionner correctement les éléments mémoires, car la hiérarchie mémoire est entièrement négligée durant la simulation. Ces approches emploient également un parallélisme spatial tel que décrit précédemment, où chaque cœur est exécuté dans le contexte d’une tâche à part. Une autre approche est d’adopter une parallélisation non pas spatiale, mais temporelle. L’idée de base est d'effectuer la même simulation en deux couches: une couche fonctionnelle qui sert à faire avancer le simulateur, et une couche temporelle qui sert à modéliser le comportement temporel de différentes parties du système. Les documents qui suivent mettent en œuvre une telle réalisation : "Trace Driven Virtual Synchronization", de Yun, D., Kim, S., & Ha, S. (2012), A parallel simulation technique for multicore embedded systems and its performance analysis, IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems, 31(1), 121-13; "Graphite: Distributed Parallel Multicore Simulator", de Miller, J. E., Kasture, H., Kurian, G., Gruenwald, C., Beckmann, N., Celio, C., ... & Agarwal, A. (2010, January), Graphite: A distributed parallel simulator for multicores, In HPCA-16 2010 The Sixteenth International Symposium on High-Performance Computer Architecture (pp. 1-12). IEEE; "TQSim: Cycle-approximate processor simulator based on QEMU", de Kang, S. H., Yoo, D., & Ha, S. (2016), "TQSIM: A fast cycle-approximate processor simulator based on QEMU". Journal of Systems Architecture, 66, 33-47; et " GreenSoCs : Gathering Memory Hierarchy Statistics in QEMU" de Clement Deschamps, Frédéric Pétrot, Mark Burton, Eric Jenn, DVCon 2019. TQSim utilise l’émulateur QEMU pour une exécution fonctionnelle du logiciel simulé, sans aucune information sur le temps dû aux différents aspects architecturaux (mémoires, processeurs). Ce temps est calculé par un simulateur séparé qui modélise plus précisément ces aspects. TQSim simule la hiérarchie mémoire dans le même contexte que la simulation fonctionnelle, ce qui, dans le cas de hiérarchies complexes, peut être très problématique en termes de performances, comme expliqué précédemment. D’autres aspects du processeur, tels que le pipeline et le prédicteur de branchements, sont simulés dans une tâche à part, permettant de masquer leur impact sur la vitesse de simulation. Comme l’approche TQSim est basée sur l’échantillonnage des instructions exécutées, i.e., seule une partie des instructions est instrumentée au début de chaque quantum, les modèles de mémoires et de processeurs doivent être des modèles analytiques représentant de manière abstraite les caractéristiques des différents composants. L’approche de GreenSoCs vise à simuler la hiérarchie mémoire en parallèle d'un simulateur fonctionnel. On appelle simulateur fonctionnel, un simulateur configuré pour faire fonctionner le logiciel simulé, en faisant abstraction de l'architecture du calculateur. On entend par comportement architectural toute action du calculateur simulé visant à reproduire un comportement du calculateur réel n’impactant non pas le fonctionnement logique du logiciel simulé, mais les caractéristiques extra-fonctionnelles, telles que la performance ou la consommation énergétique. Par exemple, les mémoires caches ne changent pas le fonctionnement d’un programme, mais peuvent améliorer sa performance. Un point critique dans ces deux dernières approches TQSim et GreenSoCs est que le logiciel simulé ne perçoit jamais l’impact des différents sous-systèmes modélisés dans le contexte temporel. Ainsi, le contexte temporel est l’unique point de vérité de la simulation, contrairement à l’approche que l’on propose, où le logiciel simulé a une vue correcte du temps et de l’état d’exécution, prenant en compte les aspects extra-fonctionnels simulés dans d'autres tâches. Un but de l'invention est de pallier les problèmes précédemment cités. Aussi, il est proposé, selon un aspect de l'invention, un simulateur rapide d'un calculateur et d'un logiciel mis en œuvre par ce calculateur, le calculateur comprenant au moins un processeur, une hiérarchie mémoire comprenant plusieurs niveaux de mémoires caches, des mémoires externes et un réseau d'interconnexions assurant la communication entre les mémoires caches et les mémoires externes. Le simulateur comprend une pluralité de co-simulateurs respectivement associés à une tâche (thread), et est configuré pour fonctionner par quantum d'instructions, un co-simulateur dit fonctionnel étant configuré pour faire fonctionner le logiciel simulé en faisant abstraction de l'architecture du calculateur, au moins un autre co-simulateur dit architectural étant configuré pour simuler, en parallèle, le comportement architectural lié à l'architecture du calculateur et déterminer les valeurs de paramètres extra-fonctionnels (ou résultats de simulation) du calculateur, et un module de transfert configuré pour transférer un événement signalé par le co-simulateur fonctionnel à un co-simulateur architectural souscrit à cet événement. Un tel simulateur permet d’envisager des simulations comprenant à la fois une exécution fluide et fonctionnellement fidèle du logiciel simulé, et une reproduction détaillée et chronométrée de tous les composants architecturaux du calculateur simulé. Traditionnellement, seul l’un des deux modes est envisageable : simulation rapide sans détails architecturaux, ou simulation précise mais très lente. Le simulateur proposé sépare les co-simulateurs architecturaux du co-simulateur fonctionnel pour faciliter l’intégration de nouveaux co-simulateurs, modélisant de nouveaux détails architecturaux, dans un simulateur existant. Le simulateur proposé prend systématiquement en compte les états des co-simulateurs architecturaux au sein du co-simulateur fonctionnel, afin que le logiciel ait une vue à jour de l’état du calculateur. Dans un mode de réalisation, les paramètres extra-fonctionnels du calculateur comprennent les temps de cycles processeur, et/ou l'énergie, et/ou la fiabilité. Ainsi le simulateur peut être utilisé non seulement pour valider le fonctionnement d’un logiciel, mais aussi de l’optimiser au niveau des performances, de l’énergie ou de la fiabilité, en prenant en compte tous les aspects architecturaux. Selon un mode de réalisation, le comportement architectural comprend des paramètres représentatifs de l'architecture du calculateur. Par exemple, les paramètres représentatifs de l'architecture du calculateur comprennent un nombre d'accès mémoires caches et externes du calculateur, et/ou les communications du réseau d'interconnexions. Ainsi l’utilisateur est en mesure de comprendre les détails du comportement du calculateur suite à l’exécution du logiciel simulé. Dans un mode de réalisation, chaque co-simulateur architectural est configuré pour simuler un unique type d'événement. Ainsi il est facile de développer des co-simulateurs architecturaux simulant différents comportements architecturaux et à divers niveaux de précision de manière séparée et modulaire. De plus, tous les co-simulateurs architecturaux étant découplés du simulateur principal, différentes caractéristiques de l’architecture peuvent être évaluées simultanément sans impacter la fluidité de la simulation. Selon un mode de réalisation, une simulation étant décomposée en époques numérotées à partir de 0, et une époque correspondant à au moins un quantum, le co-simulateur fonctionnel est configuré pour, au début d'une époque impaire, attendre que chaque co-simulateur architectural ait fini le traitement des événements de l'époque impaire qui précède, et au début d'une époque paire, attendre que chaque co-simulateur architectural ait fini le traitement des événements de l'époque paire qui précède. Ainsi la simulation fonctionnelle émettant des événements lors d’une époque, est toujours effectuée en parallèle du traitement par les co-simulateurs des évènements émis lors de l’époque précédente, garantissant ainsi un usage optimal du parallélisme. Dans un mode de réalisation, le simulateur comprend deux copies de l'état d'un co-simulateur architectural, une copie dite paire S'(i) pour une époque paire et une copie dite impaire S''(i) pour une époque impaire, l'état S(i) d'un co-simulateur architectural comprenant les paramètres représentatifs de l'architecture du calculateur, dans lequel : - un co-simulateur architectural est configuré pour écrire dans la copie paire S'(i) durant une époque paire et pour écrire dans la copie impaire S''(i) durant une époque impaire, et - le co-simulateur fonctionnel CSF est configuré pour lire puis réinitialiser la copie paire S'(i) entre la fin d'une époque impaire et le début de l'époque paire suivante, et pour lire puis réinitialiser la copie impaire S''(i) entre la fin d'une époque paire et le début de l'époque impaire suivante. Ainsi lorsque le co-simulateur fonctionnel entame une époque impaire, il peut lire et réinitialiser les états impairs S’’(i) des co-simulateurs architecturaux sans avoir à bloquer l’exécution des co-simulateurs architecturaux, qui eux écrivent en parallèle dans leur état pair S’(i). Selon un mode de réalisation, une époque correspond à un unique quantum. Il est également proposé, selon un autre aspect de l'invention, un procédé de simulation rapide d'un calculateur et d'un logiciel mis en œuvre par ce calculateur, le calculateur comprenant au moins un processeur, une hiérarchie mémoire comprenant plusieurs niveaux de mémoires caches, des mémoires externes et un réseau d'interconnexions assurant la communication entre les mémoires caches et les mémoires externes comprenant une pluralité de co-simulateurs respectivement associés à une tâche, le procédé fonctionnant par quantum d'instructions, et comprenant les étapes de : - simulation du logiciel par un co-simulateur dit fonctionnel, en faisant abstraction de l'architecture du calculateur, - simulation, en parallèle, par au moins un autre co-simulateur dit architectural du comportement architectural lié à l'architecture du calculateur et détermination des valeurs de paramètres extra-fonctionnels du calculateur, et - transfert d'un événement signalé par le co-simulateur fonctionnel à un co-simulateur architectural souscrit à cet événement. L'invention sera mieux comprise à l'étude de quelques modes de réalisation décrits à titre d'exemples nullement limitatifs et illustrés par les dessins annexés sur lesquels : illustre schématiquement un simulateur utilisant une modélisation loosely-timed d'un quantum d'instructions pour un processeur, selon l'état de l'art ; illustre schématiquement un simulateur avec découplage séquentiel entre la simulation fonctionnelle et la simulation architecturale, d'un système de la figure 1, selon un aspect de l'invention ; illustre schématiquement un simulateur selon la figure 2, selon un aspect de l'invention ; illustre schématiquement un simulateur selon deux aspects de l'invention ; et illustre schématiquement un simulateur selon un aspect de l'invention. Sur l'ensemble des figures, les éléments ayant des références identiques sont similaires. Il y a deux intérêts à simuler les modèles liés à la hiérarchie mémoire comme dans le cas de la figure 1. D’une part, cela permet d’obtenir des statistiques utiles sur les différents composants, ce qui est utile pour la caractérisation de l’architecture et du logiciel. D’autre part, cela permet d’ajuster le temps du simulateur, et aussi les différentes horloges perçues par les processeurs en comptabilisant les délais dus à la simulation de ces composants. Cependant, ces deux fonctionnalités ne requièrent en aucun cas que les modèles soient simulés à l’instant où l’instruction d’accès mémoire est exécutée. En effet, comparé à l'exemple de la figure 1 de l'état de l'art, il est possible de différer la simulation des mémoires caches, du réseau d'interconnexions NoC et des mémoires externes à la fin du quantum d'instructions, améliorant ainsi la localité au sien d’un quantum. Ceci est illustré sur la figure 2. Les temps dus aux accès mémoire seraient donc ajoutés à la fin du quantum, assurant ainsi que le temps passé à exécuter ces instructions est le même dans les deux cas. Aussi, les statistiques seront disponibles au niveau des modèles en fin de quantum. La simulation architecturale de la hiérarchie mémoire, est remplacée par un accès direct à la mémoire (direct_mem_access()). L’invention permet d'exécuter un co-simulteur architectural des accès mémoire en parallèle de la simulation fonctionnelle du logiciel simulé par le co-simulateur fonctionnel. Tout d’abord, on sépare le co-simulateur mémoire (à droite comme exemple de co-simulateur architectural) du co-simulateur fonctionnel du logiciel simulé sur le processeur (gauche). Les instructions simulées, ainsi que les modèles utilisés pour simuler les éléments mémoires, sont les mêmes que sur l’exemple de la figure 2. Au lieu de simuler les accès mémoire en ligne ou en continu, comme sur la partie gauche de la figure 2, les accès mémoires sont traduits en deux opérations de base : - Accès direct à la mémoire (direct_mem_access() sur la figure 3) consistant à compléter l’accès mémoire en chargeant ou en stockant la donnée directement sur l’espace mémoire cible, sans simuler le comportement réel de la mémoire. Ceci peut être émulé à l’aide d’instructions Load/Store de la machine hôte (machine exécutant le simulateur), et est quasi-instantané. - Notification de l’accès mémoire (notify() sur la figure 3) devant impérativement être la plus rapide possible pour ne pas perturber le flot d’exécution du processeur. Sur la figure 3, elle consiste en une simple écriture d’un événement sur une file d’attente (FIFO) lock-free. La pile FIFO lock-free ne fait pas d’appels systèmes et permet d’assurer une insertion efficace. L’événement écrit dans la file d’attente comporte des informations sur l’accès mémoire, dans cet exemple : l’instant où s’est déroulé l’accès (time), l’identifiant du processeur qui fait l’accès (cpu), l’adresse mémoire de l’accès (addr), la taille de la donnée demandée (size), et le type d’accès (lecture/écriture, rd/wr). Le co-simulateur mémoire consomme un à un les événements présents dans la file d’attente, et parcourt les différents modèles concernés. Un délai T’ propre au simulateur mémoire est mis à jour au fur et à mesure, en temps de cycles processeur. A la fin du quantum, ce temps T’ est comptabilisé sur le temps local du CPU, aboutissant ainsi au même état à la fin du quantum que sur la partie gauche de la figure 2, mais avec une réduction considérable dans le temps de simulation. Après cet exemple simple, on détaille maintenant la mise en œuvre générale de la présente invention pour accommoder n’importe quel co-simulateur architectural et assurer un parallélisme maximal. Le simulateur de l'invention comprend un co-simulateur fonctionnel configuré pour faire fonctionner le logiciel simulé, en faisant abstraction de l'architecture du calculateur. Le co-simulateur fonctionnel a pour objectif d’exécuter correctement les instructions du logiciel simulé. Il doit assurer ce fonctionnement correct de la manière la plus simple possible, en faisant abstraction de tout aspect architectural qui ne serait pas directement visible d’un point de vue fonctionnel. Le co-simulateur fonctionnel a la possibilité de signaler un certain nombre d’événements qui surviennent lors de l’exécution. Un événement peut être un accès en lecture à la mémoire (instruction load), une instruction de branchement, etc. La simulation doit comprendre un nombre fini E de types d’événements. Chaque événement est identifié par son type, un entier unique entre 0 et E. Chaque événement est accompagné d’une structure de données propre, comprenant des détails sur l’événement. Par exemple, à quel instant a eu lieu l’événement, quelle est la source de l’événement, etc. Cette structure peut être différente selon le type d’événement. Le simulateur comprend également, en plus du co-simulateur fonctionnel, au moins un co-simulateur architectural configuré pour simuler, en parallèle, le comportement architectural lié à l'architecture du calculateur et déterminer les valeurs de paramètres extra-fonctionnels du calculateur. On associe un identifiant unique numéroté entre 0 et N à chaque co-simulateur architectural. Le simulateur comprend également un module de transfert, ou "dispatcher" en langue anglaise, configuré pour transférer un événement signalé par le co-simulateur fonctionnel à un co-simulateur architectural souscrit à cet événement. Chaque co-simulateur architectural i comprend : - une file d’événements associée au co-simulateur architectural i notée EQ(i), une seule file pouvant contenir plusieurs types d’événements (entre 0 et E types). Le co-simulateur architectural souscrit aux types d’événements qu’il veut gérer avant le début de la simulation. Cette souscription se fait auprès du module de transfert, détaillé plus tard. La file d’événements est accessible par le module de transfert. - un état S(i) accessible par le co- simulateur fonctionnel, comprenant : * un délai dT (temps additionnel passé à réaliser la fonction des composants simulés par le co-simulateur architectural i). Si les composants simulés par le co-simulateur architectural i permettent de réduire le temps d’exécution estimé par le co-simulateur fonctionnel au lieu de le pénaliser, alors dT peut être négatif. Pour un co-simulateur architectural qui n’affecte pas le temps de simulation (e.g. un simulateur de puissance), dT reste toujours à 0. * un nombre K de compteurs C(k), k étant un entier entre 0 et K. Ces compteurs sont mis à jour lors de l’exécution du co-simulateur architectural. Comme exemple de compteurs on peut citer : le nombre d’accès à une mémoire, le nombre de succès, ou "hits" en langue anglaise, dans une mémoire cache, etc. Accéder à ces compteurs lors de l’exécution à partir du co-simulateur fonctionnel permet entre-autres de simuler correctement une unité de surveillance ou "monitoring" en langue anglaise, de performance PMU pour acronyme de "Performance Monitoring Unit" en langue anglaise, présente sur les processeurs actuels. Ainsi, le logiciel simulé peut avoir accès à des informations sur le matériel simulé en cours d’exécution. - une procédure F(i) qui décrit le fonctionnement du ou des composants simulés par le co-simulateur architectural i. Cette fonction prend l’état S(i), ainsi que le prochain événement présent dans la file EQ(i), et met à jour l’état S(i). Une seule procédure F(i) peut modéliser plusieurs composants architecturaux (e.g. toute la hiérarchie mémoire au lieu d’une partie). Les événements signalés par le co-simulateur fonctionnel sont transmis à une au module de transfert. Le module de transfert a pour objectif de transmettre un événement aux co-simulateurs architecturaux qui y sont souscrits. Pour ce faire, le module de transfert maintient une correspondance ("mapping" en langue anglaise) entre les différents types d’événements, et les co-simulateurs architecturaux qui y sont souscrits. Ce mapping peut être efficacement implémenté en utilisant un vecteur de vecteurs EM, EM(e) étant un vecteur contenant tous les co-simulateurs architecturaux i qui sont souscrits au type d’événement e. Plus formellement, lorsqu’un événement de type e est signalé au niveau du module de transfert, celui-ci insère l’événement dans EQ(i) pour chaque i dans EM(e). Pour une efficacité maximale, on peut associer un type d’événements à chaque co-simulateur architectural, ce qui revient à tout simplement insérer chaque événement signalé de type e dans EQ(e). Le module de transfert peut être exécuté dans le même contexte que le simulateur principal de manière synchrone. Comme illustré sur la figure 4, sur la gauche est représentée une version de base et sur la droite une version améliorée. Ci-suit le principe de fonctionnement de la version de base (partie gauche de la figure 4). Lors d'une initialisation, on fait une instanciation de chaque co-simulateur architectural i, responsable de l’initialisation de son état S(i). Chaque co-simulateur architectural i consomme le contenu de sa file d’événements EQ(i) dans un contexte (tâche) différent. Chaque co-simulateur i enregistre auprès du module de transfert, d'une part une référence vers sa file d’événements EQ(i), et d'autre part la liste de types d’événements es que le co-simulateur architectural i peut traiter. Le module de transfert ajoute donc i dans le vecteur EM(e) pour chaque événement de type e dans la liste es. Chaque co-simulateur architectural i enregistre auprès du co-simulateur fonctionnel une référence vers son état interne S(i). Ensuite, a lieu une phase de simulation, effectuée par quantums d’instructions. Durant un quantum, le co-simulateur fonctionnel simule le nombre défini d’instructions sur un processeur de la plateforme simulée. Une instruction simulée peut être accompagnée d’un signalement d’événement. Dans ce cas, le co-simulateur fonctionnel invoque le module de transfert en indiquant le type de l’événement, ainsi que les données qui y sont associées. Le module de transfert, suivant le type d’événement, écrit l’événement dans la ou les files d’événements EQ(i) concernées, et redonne immédiatement le contrôle au co-simulateur fonctionnel, lui permettant de reprendre l’exécution immédiatement. De manière concurrente et en parallèle de l’exécution du co-simulateur fonctionnel, chaque co-simulateur architectural lit les événements e à partir de leur file d’événements EQ(i) et appellent leur fonction interne F(i). A la fin du quantum d’instructions, le co-simulateur fonctionnel attend que le ou les co-simulateurs architecturaux aient fini de traiter leurs événements respectifs, et utilise le contenu des états S(i) afin de mettre à jour ses registres internes (horloge, PMU etc.). Les états S(i) sont réinitialisés à chaque lecture. Ainsi, les compteurs correspondent uniquement à l’exécution du quantum courant, et sont faciles à exploiter par le co-simulateur fonctionnel. Ci-suit le principe de fonctionnement de la version améliorée, pour maximiser le parallélisme (partie droite de la figure 4). L’approche de base peut être très efficace pour des quantums d’un nombre élevé d’instructions, cependant, l’intérêt est vite limité pour de petits quantums, pour les raisons suivantes : - Le simulateur fonctionnel doit attendre que le ou les co-simulateurs architecturaux aient fini de traiter tous les événements, y compris ceux signalés au sein du quantum courant. Si l’ensemble des co-simulateurs architecturaux est complexe, cela peut très vite impacter la fluidité de l’exécution fonctionnelle. - Si des événements arrivent tard dans le quantum, des co-simulateurs architecturaux peuvent être inactifs pendant une bonne partie du quantum, ce qui ne tire pas avantage du parallélisme de la machine hôte (cf figure 3, sur laquelle le co-simulateur fonctionnel reste en attente du co-simulateur mémoire lorsqu’il a fini son quantum). La version améliorée est illustrée sur la partie gauche de la figure 4. On suppose que le ou les co-simulateurs architecturaux peuvent être lents, et donc le but est de s’assurer qu’à chaque quantum, les co-simulateurs architecturaux sont en train de traiter des événements en parallèle des instructions du co-simulateur fonctionnel. On définit dans la simulation des époques, une époque correspondant à un nombre entier de quantums, supérieur ou égal à un. La simulation démarre à l’époque 0, puis passe à l’époque 1, puis 2, etc. Le passage d’une époque à l’autre peut être effectué lors du passage d’un quantum à l’autre pour simplifier l’implémentation. On distinguera alors entre les époques paires et les époques impaires (l’époque 0 est paire, 1 est impaire, etc.). A la fin d’un quantum d’instructions correspondant à une époque paire, le co-simulateur fonctionnel doit juste attendre que le ou les co-simulateurs architecturaux aient fini le traitement des événements de la dernière époque impaire. Au passage au quantum suivant, qui correspond à une époque impaire, l’exécution se fait en parallèle du traitement des événements du quantum précédent, qui était pair. De même, à la fin d’un quantum d’instructions correspondant à une époque impaire, le co-simulateur fonctionnel doit juste attendre que le ou les co-simulateurs architecturaux aient fini le traitement des événements de la dernière époque paire. Au passage au quantum suivant, qui correspond à une époque paire, l’exécution se fait en parallèle du traitement des événements du quantum précédent, qui était impair. L’implémentation de cette approche nécessite de dupliquer l’état S(i) d’un co-simulateur architectural i, en deux copies : - S’(i) pour les époques paires, et - S’’(i) pour les époques impaires. Un co-simulateur architecturale i écrit dans l’état S’(i) pour les époques paires, et le co-simulateur fonctionnel lit S’(i) à la fin d’une époque impaire, et écrit dans l’état S’'(i) pour les époques impaires, et le co-simulateur fonctionnel lit S’'(i) à la fin d’une époque paire. Comme illustré sur les figures 4 et 5, la présente invention fait en sorte qu’au début d’un nouveau quantum d'instructions, le co-simulateur fonctionnel doit juste attendre que les événements de la même parité aient été traités par les co-simulateurs architecturaux. Les figures montrent que cela permet d’exécuter tout un quantum pendant que les co-simulateurs architecturaux traitent à la fois les événements du quantum précédent, et ceux nouvellement émis lors du quantum courant, ce qui réduit considérablement le temps d’exécution, comme on peut le voir sur la figure 4, où on arrive à exécuter trois quantums d’instructions au lieu de deux, avec le même temps de simulation. La synchronisation est détaillée comme suit. Un facteur clé dans la performance de simulation est le mécanisme utilisé pour la synchronisation entre la tâche du simulateur fonctionnel et les tâches de co-simulation. Dans la présente approche, aucun mécanisme de synchronisation bloquant (mutex, sémaphore) ne doit être utilisé à l’intérieur d’un quantum. En revanche, un tel mécanisme peut être utilisé entre des quantums. La duplication des états des co-simulateurs architecturaux assure une cohérence des données sans aucune synchronisation. En effet, les variables d’état écrites par la tâche du co-simulateur fonctionnel (réinitialisation de l’état) sont celles écrites par les co-simulateurs architecturaux à une époque précédente, et sont différentes que celles qui sont écrites par les co-simulateurs architecturaux à l’époque courante. Les files d’événements EQ(i) sont des files dites lock-free. C’est-à-dire qu’aucun mutex n’est acquis avant d’insérer ou d’extraire un élément dans la file. Simulateur rapide d'un calculateur et d'un logiciel mis en œuvre par ce calculateur, le calculateur comprenant au moins un processeur, une hiérarchie mémoire comprenant plusieurs niveaux de mémoires caches, des mémoires externes et un réseau d'interconnexions assurant la communication entre les mémoires caches et les mémoires externes ; le simulateur comprenant une pluralité de co-simulateurs respectivement associés à une tâche, et étant configuré pour fonctionner par quantum d'instructions, un co-simulateur dit fonctionnel (CSF) étant configuré pour faire fonctionner le logiciel simulé en faisant abstraction de l'architecture du calculateur, au moins un autre co-simulateur dit architectural (CSAi) étant configuré pour simuler, en parallèle, le comportement architectural lié à l'architecture du calculateur et déterminer les valeurs de paramètres extra-fonctionnels du calculateur, et un module de transfert (MT) configuré pour transférer un événement (e) signalé par le co-simulateur fonctionnel (CSF) à un co-simulateur architectural (CSAi) souscrit à cet événement. Simulateur selon la revendication 1, dans lequel les paramètres extra-fonctionnels du calculateur comprennent les temps de cycles processeur, et/ou l'énergie, et/ou la fiabilité. Simulateur selon l'une des revendications précédentes, dans lequel le comportement architectural comprend des paramètres représentatifs de l'architecture du calculateur. Simulateur selon la revendication 3, dans lequel les paramètres représentatifs de l'architecture du calculateur comprennent un nombre d'accès mémoires caches et externes du calculateur, et/ou les communications du réseau d'interconnexions. Simulateur selon l'une des revendications précédentes, dans lequel chaque co-simulateur architectural est configuré pour simuler un unique type d'événement. Simulateur selon l'une des revendications précédentes, dans lequel, une simulation étant décomposée en époques numérotées à partir de 0, et une époque correspondant à au moins un quantum, le co-simulateur fonctionnel (CSF) est configuré pour, au début d'une époque impaire, attendre que chaque co-simulateur architectural (CSAi) ait fini le traitement des événements de l'époque impaire qui précède, et au début d'une époque paire, attendre que chaque co-simulateur architectural (CSAi) ait fini le traitement des événements de l'époque paire qui précède. Simulateur selon la revendication 6, comprenant deux copies de l'état (S(i)) d'un co-simulateur architectural (CSAi), une copie dite paire (S'(i)) pour une époque paire et une copie dite impaire (S''(i)) pour une époque impaire, l'état (S(i)) d'un co-simulateur architectural (CSAi) comprenant les paramètres représentatifs de l'architecture du calculateur, dans lequel : un co-simulateur architectural (CSAi) est configuré pour écrire dans la copie paire (S'(i)) durant une époque paire et pour écrire dans la copie impaire (S''(i) durant une époque impaire, et le co-simulateur fonctionnel (CSF) est configuré pour lire puis réinitialiser la copie paire (S'(i)) entre la fin d'une époque impaire et le début de l'époque paire suivante, et pour lire puis réinitialiser la copie impaire (S''(i) entre la fin d'une époque paire et le début de l'époque impaire suivante. Simulateur selon la revendication 1, dans lequel, une époque correspond à un unique quantum. Procédé de simulation rapide d'un calculateur et d'un logiciel mis en œuvre par ce calculateur, le calculateur comprenant au moins un processeur, une hiérarchie mémoire comprenant plusieurs niveaux de mémoires caches, des mémoires externes et un réseau d'interconnexions assurant la communication entre les mémoires caches et les mémoires externes comprenant une pluralité de co-simulateurs respectivement associés à une tâche, le procédé fonctionnant par quantum d'instructions, et comprenant les étapes de : simulation du logiciel par un co-simulateur dit fonctionnel (CSF), en faisant abstraction de l'architecture du calculateur, simulation, en parallèle, par au moins un autre co-simulateur dit architectural (CSA) du comportement architectural lié à l'architecture du calculateur et détermination des valeurs de paramètres extra-fonctionnels du calculateur, et transfert (MT) d'un événement signalé par le co-simulateur fonctionnel à un co-simulateur architectural souscrit à cet événement.