Description de la partie matérielle:

SoC de base

La partie matérielle du système est décrite dans le fichier C++ top.cpp

Le SoC contient deux types de modules:

L’interface VCI:

L’interface utilisée par la majorité des modules de SocLib est une interface VCI. Elle fonctionne sur le principe de requêtes/réponses dissociées:

Dans les modèles SystemC de la bibliothèque SocLib, cette interface est paramétrable. Pour le HelloWorld, nous avons une interface 32 bits données/adresse avec jusqu’à 256 initiateurs sans modes spéciaux d’adressage.

La structure VciParams, regroupe ces paramètres et sert de "template" aux modules utilisant l’interface VCI.

typedef soclib::caba::VciParams<4,8,32,1,1,1,8,1,1,1> vci_param;

Avec dans l’ordre:

La structure vci_param est en suite utilisée pour paramétrer tous les modules et interfaces VCI.

Par exemple, la définition du signal VCI servant à connecter la mémoire ROM:

soclib::caba::VciSignals signal_vci_rom("signal_vci_vcirom");

L’interface WishBone:

C’est l’interface que vous utiliserez pour vos périphériques. Son fonctionnement est plus simple que celui du VCI les requêtes sont bloquantes jusqu’à l’acquittement.

L’interface WishBone peut aussi être paramétrée en définissant la largeur du bus de données et du bus d’adresses. Pour le helloworld, les données et les adresses font 32 bits.

typedef soclib::caba::WbParams<32,32> wb_param;

Comme pour les paramètres VCI , les paramètres WishBone sont ensuite utilisés pour tous les signaux et toutes les interfaces WishBone.

Par exemple, le signal servant à connecter le processeur au bus:

 soclib::caba::WbSignal<wb_param> signal_wb_lm32("signal_wb_lm32");

La table d’adressage:

La table d’adressage permet de décrire les plages de l’espace mémoire réservée à chaque élément du système. C’est un module pour la "simulation" qui permet de vérifier qu’il n’y a pas d’incohérence dans les adresses des différents modules. Il permet aussi de centraliser ces informations.

La table prend 4 arguments à la construction:

soclib::common::MappingTable maptab(32, IntTab(8), IntTab(8), 0x80000000);

Dans cet exemple nous utilisons 32 bits pour les adresses dont les 8 bits de poids fort permettent d’identifier les cibles/esclaves. Si le bit 31 de l’adresse est non nul alors les requêtes vers cette plage mémoire ne passent pas par le cache du processeur.

On ajoute à cette table des segments correspondants aux cibles/esclave. On précise un nom, une adresse de base, une taille, un index et un indicateur de "cachabilité" (cet index doit être cohérent avec le masque donné à la définition de la table)

maptab.add(Segment("rom" , ROM_BASE , ROM_SIZE , IntTab(0), true));

Dans cet exemple, on définit un segment correspondant à la mémoire ROM. Le nom de ce segment est "rom", son adresse de base est ROM_BASE et sa taille est ROM_SIZE. Il sera identifié comme la cible "0" et les requêtes vers cette ROM passeront par le cache du processeur.

Toutes les requêtes à faite une adresse appartenant à l’intervalle [ROM_BASE, ROM_BASE+ROM_SIZE] seront transmise au contrôleur de ROM.

Les constantes utilisées sont toutes définies dans le fichier segmentation.h. Ainsi, nous pouvons avoir un fichier unique décrivant la carte mémoire (map) qui pourra être utilisé pour le logiciel embarqué.

La cohérence de cette table est vérifiée avant le début de la simulation.

Le processeur:

Nous disposons d’un ISS (Instruction Set Simulator) qui permet de simuler l’exécution d’un flot d’instruction sur un lm32.

Cet ISS est n’est pas un module C++, il n’est donc pas instancié directement dans la plateforme. La bibliothèque SocLib propose des modules génériques (des wrappers d’iss) avec des configurations de cache et des interfaces différentes qui permettent d’encapsuler les ISS. Ces Wrappers permettent de simuler indifféremment un mips, un sparc ou un lm32… Le code responsable de la gestion du cache, et des entrées/sorties des processeurs est ainsi mutualisé.

Wrapper d’ISS

Ici, comme nous allons travailler avec l’interface WishBone et que notre CPU a une cache, nous utilisons le WbXcacheWrapper.

soclib::caba::WbXcacheWrapper
      <wb_param, soclib::common::Iss2Simhelper<soclib::common::LM32Iss<false> > >
      lm32("lm32", 0, maptab,IntTab(0), 2,128,8, 2,128,8);

Dans cet exemple on construit un modèle de LM32 avec les paramètres suivants:

Interconnexion:

Nous utiliseront le WbInterc (WishBone interconnect). Ce module simule le comportement d’une interconnexion à bus multiplexé avec arbitrage à priorité tournante (round robin) .

soclib::caba::WbInterco<wb_param> wbinterco("wbinterco",maptab, 1, 3);

Les paramètres du constructeur sont:

Connecter les différents éléments:

Le WbInterco possède, en plus d’un port d’horloge (p_clk) et d’un port de remisee à zéro (p_resetn), un port pour relier les maîtres (p_from_master) et les esclaves (p_to_slave). Ces deux derniers ports sont des vecteurs où l’indice de chaque connexion doit correspondre à l’indice du périphérique dans la table d’adressage. Ces ports sont reliés à des signaux WishBone qui sont reliés aux ports des éléments respectifs.

wbinterco.p_clk(signal_clk);
wbinterco.p_resetn(signal_resetn);
wbinterco.p_from_master[0](signal_wb_lm32);
wbinterco.p_to_slave[0](signal_wb_rom);
wbinterco.p_to_slave[1](signal_wb_ram);

Ici, nous avons le signal venant du lm32 relié au port maître 0, la rom au port esclave 0 et la ram au port esclave 1.

Connecter les modules VCI à l’interconnect WishBone:

Les éléments VCI ne peuvent pas être connectés directement au bus WishBone. Nous devons utiliser un adaptateur (wrapper) qui converti les requêtes venant des maîtres WishBone en transaction VCI.

Ce wrapper se comporte comme esclave WishBone et maître VCI. Il possède un port d’horloge (p_clk), un port de reset (p_resetn), un port WishBone esclave pour se connecter à l’interconnect et un port VCI maître pour se connecter au module VCI.

soclib::caba::WbSlaveVciInitiatorWrapper<vci_param, wb_param> tty_w ("tty_w") ;
tty_w.p_clk            (signal_clk);
tty_w.p_resetn         (signal_resetn);
tty_w.p_vci            (signal_vci_tty);  // Vers le module tty
tty_w.p_wb             (signal_wb_tty);   // Vers WbInterco

Le wrapper a comme arguments de template les paramètres WishBone et VCI et comme argument de constructeur le nom du module SystemC.

Commencer la simulation:

La simulation est initiée en utilisant la fonction sc_start().

sc_start(SC_ZERO_TIME);               // démarre la simulation mais ne fait pas avancer le temps
signal_resetn = false;                // Remise à zéro du système
sc_start(sc_core::sc_time(1, SC_NS)); // avance la simulation de "1ns"
signal_resetn = true;                 // Fin de la remise à zéro du système
sc_start();                           // lance la simulation
                                      // La simulation s'arrêtera à l'appel de sc_stop()

Retour au sommaire