UNE RESSOURCE PLUS RÉCENTE EST DISPONIBLE ICI
Remarque
préliminaire : ce cours de SystemC n'est pas
un manuel complet de SystemC. C'est plutôt une introduction aux bases
du langage. Nous y avons inclus ce qui nous semble important, en
laissant de côté les aspects les plus complexes et pointus. Il part
aussi du principe que vous avez suivi le cours
sur les HDL en général, ainsi qu'au choix au moins un des
deux cours sur Verilog
ou VHDL.
License d'utilisation de ce document :
Ce cours est séparé en chapitres. Il est conseillé de les suivre dans l'ordre, même si ce n'est pas une nécessité absolue.
Chaque chapitre est séparé en sous-parties. Vous pouvez
naviguer dans les chapitres et sous-parties à l'aide du menu en haut de
page.
Les icônes en bas de page vous permettent de passer au chapitre
précédent ou suivant, ou de revenir à l'accueil du site sur les HDL.
Un enseignant se tient à votre disposition pendant les heures de cours, mais vous pouvez toujours nous contacter en mail.
Dernier détail, merci d'utiliser un navigateur acceptant les CCS et le javascript (firefox, mozilla, ...)
Bon courage !
SystemC est, comme Verilog et VHDL, un langage de description de matériel. C'est le fruit de contributions de plusieurs sociétés. En 1989, Synopsys met son outil commercial Scenic dans le domaine libre, et crée la version 0.9 de SystemC. Une première contribution de Frontier Design donne lieu à la version 1.0, et une autre de CoWare aboutit en 2000 à la version 1.1, première version officielle de SystemC. L'OSCI (Open SystemC Initiative) est alors crée, rassemblant une multitude de sociétés et laboratoires de recherche. Cette organisation a fusionné en 2011 avec Accellera, une association de normalisation de standards pour le design des systèmes électroniques. C'est maintenant Accellera Systems Initiative qui est en charge de diffuser, promouvoir et rédiger les spécifications de SystemC.
Les spécifications de SystemC ont été étendues en 2001 à la modélisation de systèmes abstraits (de très haut niveau, avant partitionnement matériel / logiciel), aboutissant à la version 2.0. En 2005, l'IEEE a approuvé une version de référence de SystemC, appelée IEEE1666-2005 et correspondant à la version 2.2.0 de SystemC.
En 2011 une révision du standard est approuvée, elle intègre entre autre la modélisation transactionnelle de TLM-2.0. Elle est appelée IEEE1666-2011 et est téléchargeable directement sur le site de l'IEEE.
Ce cours n'aborde pas en détail la modélisation transactionnelle.Les concepts abordés s'appliquent ainsi aux versions 2.2.0 et 2.3.0 de SystemC.
Bien que libre, la bibliothèque SystemC ne peut être téléchargée que depuis le site d'Accelera. Elle a été installée sur les machines du département COMELEC, dans le répertoire /comelec/softs/opt/systemc/systemc-2.3.0 et a été compilée pour les architectures x86 64bits sur Linux. Nous verrons plus loin comment l'utiliser.
Pour vous simplifier la vie, vous avez quand même accès au User Guide, et aux Functional Specifications for SystemC 2.0, mais en accès local seulement (depuis une machine du département).
Vous avez aussi une Quick Reference Card de la société Transfer, qui résume sur deux pages toutes les constructions de SystemC.
SystemC a pour objectif de modéliser des systèmes numériques matériels et logiciels à l'aide de C++. Il permet donc de modéliser non seulement des systèmes matériels, mais aussi des systèmes logiciels, mixtes ou non-partitionnés (où on ne sait pas encore ce qui sera fait en logiciel, et ce qui sera fait en matériel).
La modélisation d'un système complet passe par des niveaux
comportementaux plus détaillés que ceux
abordés précédemment.
La description de ces niveaux se fait à l'aide des termes suivants :
Le processus de modélisation d'un SoC se décompose alors ainsi :
Développement d'un système : raffinement des modèles matériels / logiciels
L'un des inconvénients majeurs des flots habituels vient de la multitude des langages mis en oeuvre :
SystemC étant une extension du C++ (donc du C), un seul et même langage est utilisé de la première étape du flot de conception jusqu'à l'étape TLM (BCA) ou CABA, que ce soit pour la partie logicielle que pour la partie matérielle. Arrivé au stade BCA, ou à un niveau suffisamment bas et raffiné, on peut :
A chaque étape, le même environnement de test (écrit en SystemC) peut être utilisé, garantissant la fonctionnalité du système (matériel + logiciel). Si on arrive à l'utilisation de Verilog ou VHDL, un cosimulateur se charge de simuler les deux langages en même temps.
Flot de conception SystemC
SystemC est une extension du langage C++, plus précisément une bibliothèque de classes C++ contenant des modèles de matériel, ainsi que toutes les briques de base pour modéliser un système matériel qui n'aurait pas été inclus dans la bibliothèque de base.
Cette bibliothèque C++ comprend aussi en standard un moteur de simulation événementiel rapide, permettant de se passer d'un simulateur externe. D'autres simulateurs existent, plus ou moins performants, comme le simulateur SystemCass du LIP6 permettant, dans certaines conditions, de multiplier les vitesses de simulation par 20.
La figure ci-dessous résume l'architecture de la bibliothèque.
Les types de données usuels C++ ont été enrichis par des types de
données adaptées à la modélisation de matériel (logique multivaluée,
décimaux virgule
fixe, ...).
Les autres éléments se répartissent en deux ensembles,
Certains de ces types de données servent à représenter du matériel (modules, ports, signaux, fifo), d'autres à représenter du logiciel (sémaphores, mutex), et certains sont suffisamment abstraits pour pouvoir représenter les deux (canaux, événements, interfaces, ...).
Organisation de SystemC
Un modèle écrit en SystemC est donc un programme C++
utilisant les classes de la bibliothèque SystemC. Il doit donc être compilé.
A l'école, vous travaillerez sur des PC Linux avec la suite de
compilation C/C++ GNU (gcc/g++).
Le processus de développement est le même que pour tout programme C/C++ :
Les différents composants structurels de SystemC seront étudiés en détail plus tard. Mais voici d'ores et déjà un aperçu rapide de la façon dont est construit un modèle SystemC d'un système numérique.
Comme en Verilog ou VHDL, un système est une hiérarchie d'objets. Généralement de sont des modules imbriqués et/ou des processus. Les modules communiquent entre eux par des canaux.
Le plus haut de la hiérarchie d'un système complet (module à tester + testbench) n'est pas un module top (comme on en a l'habitude en Verilog/VHDL), mais la fonction SystemC sc_main (l'équivalent du main des programmes en C).
Un module en SystemC est composé d'autres modules, de canaux de communication entre ces modules (signaux, ou canaux plus abstraits), et éventuellement de processus.
Un module possède un ou plusieurs ports. Les ports sont juste des points d'entrée ou de sortie, qui ne font rien de particulier.
Par contre, les ports doivent déclarer les fonctions qui seront utilisées pour communiquer à travers eux. Exemples :
- un port en entrée destiné à être relié à un signal normal déclarera qu'il utilise la fonction read des signaux.
- un port similaire mais bidirectionnel déclarera qu'il utilisera les fonctions read et write
- un port destiné à être relié à une fifo (un canal de communication abstrait, de haut niveau), déclarera selon le côté de la fifo où il st sensé se trouver, qu'il utilisera les fonction read, nb_read (read non bloquant), num_available, write, nb_write, num_free...
La déclaration des fonctions qu'il va utiliser est appelée interface.
Une interface est une déclaration des fonctions (ou "méthodes", pour prendre la terminologie C++) qui pourront être utilisées à travers les ports d'un module. Une interface ne contient pas de code, c'est seulement une déclaration de fonctions.
Les interfaces permettent au compilateur de détecter très tôt le branchement d'un port à un canal qui ne lui est pas adapté.
Les canaux sont les moyens de communication entre les modules. Ils peuvent être basique et concrets (signaux), ou plus évolués / plus abstraits (fifo, réseau ethernet, ...). Ils peuvent aussi contenir d'autres canaux, voire même des modules si ce sont des canaux de très haut niveau.
Les canaux contiennent (entre autres) l'implémentation du code C++ déclaré dans les interfaces. On dit qu'ils implémentent une interface.
On branche un canal à un module par l'intermédiaire d'un port, ce port devant déclarer l'interface implémentée par le canal. L'intérieur du module peut alors accéder au canal en appelant les fonctions déclarées dans l'interface. De façon imagée, les ports publient une offre d'embauche (l'interface) et les canaux aptes à y répondre font le boulot. L'interface est donc ce qui lie les ports et les canaux en décrivant comment l'information transite par les ports. Ce qui est symbolisé dans le schéma ci-dessous par l'image (qui combine port et interface). Tout ce dont a besoin un module pour pouvoir utiliser un port est de connaître l'interface qu'il publie. Autrement dit, on peut modifier à loisir le contenu d'un canal, le raffiner progressivement, sans avoir à toucher quoi que ce soit d'autre. Il suffit que son interface reste la même.
Les processus en SystemC sont similaire à ceux de Verilog et VHDL. Il décrivent une fonctionnalité, un comportement. Un processus ne doit pas être appelé directement; c'est le moteur de simulation SystemC qui se charge de l'appeler (le déclencher) sur certains événement particuliers : ceux qui sont dans sa liste des sensibilité.
Les processus peuvent éventuellement communiquer directement avec les canaux. Ils n'ont pas besoin de port pour cela, ils appellent directement les méthodes du canal.
En résumé, l'architecture d'un module en SystemC ressemble à ceci :
Organisation structurelle en SystemC
Si les modules sont des réservoirs d'eau, les ports sont des robinets. Que sont alors les canaux et les interfaces ?
Même si SystemC n'utilise pas toutes les possibilités du C++, il est parfois nécessaire de comprendre certaines constructions inhabituelles pour les programmeurs C.
Pour cela, les FAQ C++ sont des ressources très importantes, et tout particulièrement la C++ FAQ Lite. Si votre programme ne compile pas, si vous ne comprenez pas les messages du compilateur ou de l'éditeur de lien, la solution s'y trouve probablement.
Les habitués du C ont l'habitude de placer les déclarations dans un fichier .h et l'implémentation dans un fichier .c. Pour le C++, la situation est parfois plus compliquée, notamment à cause des templates.
Certains placent tout leur code directement dans les déclarations de classe, dans les .h. Ce n'est pas bon (voir la FAQ pour savoir pourquoi).
Il est préférable de garder déclarations et implémentations dans des fichiers séparés (.h et .cpp).
Cela pose néanmoins un problème avec les template. Pour plus d'informations, voir les URL suivantes :
- https://www.parashift.com/c++-faq-lite/templates.html#faq-35.9
- https://gcc.gnu.org/onlinedocs/gcc-3.4.3/gcc/Template-Instantiation.html#Template-Instantiation
Personnellement, je recommande, en attendant une version de g++ qui supporte la recompilation des template, d'adopter la troisième solution de la FAQ, c'est-à-dire :
- déclarations dans un .h
- implémentation dans un .cpp
- instanciation de la classe templatée dans un les fichiers .cpp qui en ont besoin.
SystemC est une bibliothèque C++, qui fournit des classes C++ adaptées à la modélisation de matériel ainsi qu'un moteur de simulation événementiel rapide, le tout sous licence libre !
Il permet de garder un même langage d'un bout à l'autre du flot de conception, excepté peut-être à la toute fin (mais on a alors des moyens de s'assurer de la cohérence des modèles).
Un modèle SystemC est écrit en C++, c'est généralement un module.
Les modules sont les briques structurelles de base. Ils instancient d'autres modules, ainsi que des canaux et des processus. Ils communiquent avec l'extérieur par des ports. La communication proprement dite se fait au travers de canaux reliés au port.
Pour qu'un canal soit relié à un port, les deux doivent avoir la même interface (déclaration de fonctions). L'implémentation de ces fonctions est faite dans le canal.