SocLib: Prise en main d'une plateforme virtuelle

Ce TD est une prise en main de la bibliothèque SocLib. Vous allez successivement aborder les thèmes suivants :

  • construction d'un système complet basé sur SocLib
  • co-simulation logiciel/matériel sur une plateforme virtuelle
  • ajout de périphériques

Vous serez en mesure, à la fin de ce TP, de concevoir et de décrire votre propre système à base du cœur de processeur LM32 et d'y ajouter vos propre périphériques.

Le LM32 est un processeur Risc dont la description HDL est opensource et distribué par Lattice semi.

Il est nécessaire d'avoir terminé ce TD avant la prochaine séance.

Voici les étapes successive de ce TD:

Présentation de SocLib

Logo SocLib
 

SocLib est une bibliothèque libre (GPL), de composants (IP) pour la modélisation de SoC. Ces modèles sont écrit en écrite en C++ et SystemC.

SocLib est le résultat d'un travail collectif réalisé par un ensemble de laboratoires universitaires et industriels.

Les composants de cette bibliothèque disposent d'un modèle de haut niveau, écrit en SystemC, destiné à des simulations rapides.

Pour accélérer les simulations, les modèles SystemC sont écrits sous forme de machines à états de Moore ou Mealy, utilisant au maximum trois processus :

  • un processus synchrone sur front montant de l'horloge, stockant l'état interne du système (généralement nommée transition).
  • un processus synchrone sur front descendant de l'horloge, générant les sorties qui ne dépendent que de l'état interne de la machine de Moore (généralement nommé genMoore).
  • un processus synchrone sur front descendant de l'horloge et sensibles aux entrées, générant les sorties dans pourune machine de Mealy (généralement nommé genMealy).

Style de mdélisation dans SocLib

Les IP disponibles sont nombreuses, on peut citer:

  • processeurs
    • sparc V8
    • MIPS
    • lm32
    • ARM
    • PPC405
    • ...
  • caches
    • cache générique instruction/data séparées configurable
    • ... Réseau d'interconnexion
    • crossbar VCI configurable
    • Bus multiplexé WB
    • réseau virtuel, configurable en terme de latence et de débit maximal
    • ...
  • Mémoires
    • RAM simple
    • RAM multisegments, pouvant être pré-chargées directement à partir d'un fichier ELF
  • divers
    • un port série virtuel (TTY), pour faciliter les interactons lors des simulations
    • Une interface vers un serveur gdb
    • une table de routage pour le bus VCI
    • ...

La majorité des composants utilisent l'interface VCI Advanced (VCI: Virtual Component Interface). La documentation de référence de l'interface VCI est accessible localement ici:

/comelec/softs/opt/soclib/TPT/doc/VCI.pdf

mais l'étude détaillée de son fonctionnement n'est pas indispensable pour ce projet.

Vous pouvez trouver plus d'informations sur les éléments disponibles dans la bibliothèque SocLib sur http://www.soclib.fr.

Configurer l'environnement

Pour faciliter la prise en main de la bibliothèque SocLib nous vous proposons d'étudier un exemple "simple" un hello world!

Configuration de l'environnement de travail:

Pour commencer vous devez d'abord configurer votre environnement.

Nous vous proposons un script pour définir correctement le chemin vers les outils SocLib (PATH) et quelques quelques autres outils nécessaires à la simulation telle que le chemin vers la bibliothèque SystemC.

Pour les SHELL sh ou zsh vous pouvez juste:

source /comelec/softs/opt/soclib/TPT/env.sh

Récupérer le code du HelloWorld:

Le code du helloworld est disponible à travers un dépôt Git. Vous pouvez cloner le dépôt et faisant:

git clone git@gitlab.enst.fr:se303/soclib_hello_world PS. Si vous voulez que placer le dépôt dans un sous-répertoire de votre dépôt personnel, vous pouvez utiliser git read-tree (voir la note plus bas) ou si vous avez une version récente de git le script git subtree

Compilez et exécutez le HelloWorld:

Faites make, si tout se passe bien vous devriez obtenir un exécutable simulation.x. Lancez cet exécutable et admirez.

Note

Exemple en utilisant read-tree:

  • Se mettre dans la branche master de son dépôt:

    git checkout master
                 
  • Ajouter un remote hello-remote vers le nouveau dépôt puis récupérer son état:

    git remote add hello-remote git@gitlab.enst.fr:se303/soclib_hello_world.git
    git fetch hello-remote
                 
  • Créer une branche locale avec l'état du master du nouveau dépôt:

    git checkout -b hello_master_branch hello-remote/master
                 
  • Revenir dans master:

    git checkout master
                 
  • Récupérer la nouvelle branche crée dans le sous-répertoire hello_world puis faire un commit:

    git read-tree --prefix=hello_world -u hello_master_branch
    git commit -m "Récupération du hello world..."
                 

Pour récupérer des modifications:

  • Se mettre dans la branche hello_master_branch:

    git checkout hello_master_branch
    git pull
                 
  • Revenir dans master et merger en utilisant la stratégie subtree:

    git checkout master
    git merge -s subtree hello_master_branch --allow-unrelated-histories
                 

Pour merger une autre branche dans le même sous-répertoire:

  • Se mettre dans la branche hello_master_branch:

    git checkout hello_master_branch
    git merger hello-remote/models
                 
  • Revenir dans master et merger en utilisant la stratégie subtree:

    git checkout master
    git merge -s subtree hello_master_branch --allow-unrelated-histories
                 

Analyse du HelloWorld

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:

  • Un interconnect et le LM32 utilisant l'interface WishBone
  • Des modules utilisant l'interface VCI de la bibliothèque SocLib

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:

  • Un initiateur fait une requête (de lecture ou d'écriture) en fournissant l'adresse de la cible (et éventuellement des données en écriture).
  • La requête est maintenue tant qu'elle n'est pas acceptée par la cible.
  • Après que la cible ait accepte la requête, elle répond en indiquant l'identifiant de l'initiateur à l'origine de la requête.
  • La réponse est maintenue tant qu'elle n'est pas acceptée par l'initiateur.

Dans les modèle 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 structure VciParams, regroupe ce 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:

  • cell_size : taille de la cellule 4(octets) => interface 32 bits
  • plen_size : la taille des paquets (transferts multiples/bursts) est codée sur 8 bits
  • addr_size : la taille du bus d'adresse est de 32 bits
  • rerror_size: les messages d'erreurs codés sur sur 1 bit (erreur ou ok)
  • clen_size : nombre de paquets dans une chaine codé sur 1 bit
  • rflag_size : les indicateurs d'erreur sont codés sur 1 bit
  • srcid_size : l'identifiant des sources est codé sur 8bits (jusqu'à 256 initiateurs)
  • pktid_size : l'identifiant des paquets est sur 1bit
  • trdid_size : l'identifiant des threads est sur 1bit
  • wrplen_size: le dernier paramètre correspond à l'adressage circulaire des bursts

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

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

soclib::caba::VciSignals<vci_param> 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;
  • wb_data_width : largeur du bus de données
  • wb_addr_width : largeur du bus d'adresses

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 de d'adressage:

La table de 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:

  • La taille du bus d'adresse ( nombre de bits)
  • Le nombre de bits utilisés pour router les requêtes VCI
  • Le nombre de bits utilisés pour router les réponses VCI
  • Le masque des adresses cachables.
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 à 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", sont 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ée sont toutes définies dans le fichiersegmentation.h.

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:

  • Le nom de l'instance, ici lm32
  • l'indice du processeur dans un le cas d'un système multiprocesseurs, ici 0
  • la table de mapping principalement pour définir les zones "cachées"
  • l'indice de l'initiateur correspondant (n'est pas utilisé dans la version WishBone)
  • la configuration des caches instructions et données (ici 2 ways, 128 sets et 8 mots de 32bits par set)
  • L'argument de template du LM32Iss "false" indique que le lm32 est big endian contrairement à la convention SocLib.

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:

  • Le nom de l'instance, ici "wbinterco"
  • La table de mapping
  • Le nombre de maîtres, ici 1 (le lm32)
  • Le nombre d'esclaves, ici 3 (la rom, la ram et l'uart)

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().

  • Si cette fonction est appelés avec un argument, cet argument représente la durée en temps du simulateur de l'exécution.
  • Si elle est appelée sans argument, la simulation est lancée jusqu'à l'exécution de la fonction sc_stop().
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()

L'interface WishBone dans les modèles SocLib

L'interface WishBone

Comme nous allons être amené à utiliser principalement l'interface WishBone, voici une description des signaux et des interfaces.

Signal WishBone

Un signal WishBone est une structure de signaux SystemC. Cette structure rassemble les signaux de données et d'adresse ainsi que les signaux de contrôle.

    template <typename wb_param>
        class WbSignal {
            public:
                sc_core::sc_signal<typename wb_param::wb_data_t>      MWDAT;    // masters output data
                sc_core::sc_signal<typename wb_param::wb_data_t>      MRDAT;    // masters input data
                sc_core::sc_signal<typename wb_param::wb_add_t>       ADR;      // master output address
                sc_core::sc_signal<bool>                              ACK;      // Acknowledge from slave
                sc_core::sc_signal<bool>                              CYC;      // cycle valid
                sc_core::sc_signal<bool>                              ERR;      // error from slave
                sc_core::sc_signal<bool>                              LOCK;     // lock request
                sc_core::sc_signal<bool>                              RTY;      // retry from slave
                sc_core::sc_signal<typename wb_param::wb_sel_t>       SEL;      // BE
                sc_core::sc_signal<bool>                              STB;      // commande valid
                sc_core::sc_signal<bool>                              WE;       // write enable
        }

Port maître WishBone

Un port maître WishBone est une structure regroupant des port SystemC.

Les noms des ports ont les suffixes _I et _O en fonction de leur sens vu par le maître.

Un port maître peut être connecté à :

  • Un signal WishBone, c'est l'utilisation standard.
  • Un autre port WishBone maître, il devient alors transparent

On ne peut pas connecter un port maître directement à un port esclave sans signal intermédiaire.

    template <typename wb_param>
        class WbMaster {
            public:
                sc_core::sc_out<typename wb_param::wb_data_t>        DAT_O;
                sc_core::sc_in <typename wb_param::wb_data_t>        DAT_I;
                sc_core::sc_out<typename wb_param::wb_add_t>         ADR_O;
                sc_core::sc_in <bool>                                ACK_I;
                sc_core::sc_out<bool>                                CYC_O;
                sc_core::sc_in <bool>                                ERR_I;
                sc_core::sc_out<bool>                                LOCK_O;
                sc_core::sc_in <bool>                                RTY_I;
                sc_core::sc_out<typename wb_param::wb_sel_t>         SEL_O;
                sc_core::sc_out<bool>                                STB_O;
                sc_core::sc_out<bool>                                WE_O;

                ...
        }

Port esclave WishBone

Un port esclave WishBone est une structure regroupant des port SystemC.

Les noms des ports ont les suffixes _I et _O en fonction de leur sens vu par le esclave.

Un port esclave peut être connecté à :

  • Un signal WishBone, c'est l'utilisation standard.
  • Un autre port WishBone esclave, il devient alors transparent

On ne peut pas connecter un port esclave directement à un port maître sans signal intermédiaire.

    template <typename wb_param>
        class WbSlave  {
            public:
                sc_core::sc_in <typename wb_param::wb_data_t>       DAT_I;
                sc_core::sc_out<typename wb_param::wb_data_t>       DAT_O;
                sc_core::sc_in <typename wb_param::wb_add_t>        ADR_I;
                sc_core::sc_out<bool>                               ACK_O;
                sc_core::sc_in <bool>                               CYC_I;
                sc_core::sc_out<bool>                               ERR_O;
                sc_core::sc_in <bool>                               LOCK_I;
                sc_core::sc_out<bool>                               RTY_O;
                sc_core::sc_in <typename wb_param::wb_sel_t>        SEL_I;
                sc_core::sc_in <bool>                               STB_I;
                sc_core::sc_in <bool>                               WE_I;

                ...
        }

Les paramètres WishBone

Les ports et signaux WishBone sont paramétrables. On peut préciser la largeur du bus de données et du bus d'adresse.

Les données transportées par cette interface sont des sc_uint de largeur paramétrable.

    template < int data_width, int add_width >
        class WbParams {
            public:
                // Constants which can be used externally
                static const int DataWidth = data_width;
                static const int AddWidth  = add_width;
                static const int BeWidth   = data_width/8;
                // Signal types
                typedef sc_dt::sc_uint<datawidth>   wb_data_t;
                typedef sc_dt::sc_uint<addwidth>    wb_add_t;
                typedef sc_dt::sc_uint<datawidth/8> wb_sel_t;

                ...
        }

Le code source  complet est accessible ici:

/comelec/softs/opt/soclib/soclib/communication/wishbone/​

Les outils SocLib

Compilation de la plateforme de simulation:

Si vous analysez le Makefile, fourni, vous verrez que la compilation de la plateforme fait appel à la commande soclib-cc.

Cet outil, fait partie des utilitaires fournits avec la bibliothèque SocLib. Il permet de compiler une plateforme sans forcément en connaitre l'organisation interne des fichiers sources de chaque module.

Les module de la bibliothèque SocLib ne sont pas pré-compilés et comme ils utilisent énormément les templates C++, leur compilation peut se révéler assez complexe.

Pour comprendre la problématique liée à la compilation séparée des classes templatées en C++, vous pouvez voir ce point de la FAQ C++.

L'outil appelle à un certain moment un compilateur C++, g++ par défaut mais on peut en préciser un autre.

Les fichiers intermédiaires générés par soclib-cc ainsi que les fichiers objets peuvent être retrouvés dans /tmp/soclib_build_

soclib-cc --help

vous donnera la liste des arguments supportés par cet outil. La documentation officielle est aussi accessible ici.

Le fichier de description de plateforme:

soclib-cc a besoin d'un fichier de description de la plateforme à compiler. Pour notre hello_world, il s'agit du fichier platform_desc.

Ce fichier contient la liste des éléments de la bibliothèque SocLib utilisés dans la plateforme virtuelle. Il contient aussi la liste des paramètres de chaque module.

Il faut y préciser le fichier C++ contenant la description de la plateforme (top.cpp), le type de modèles à utiliser (pour nous "caba" pour cycle accurate bit accurate càd description au cycle et au bit près).

Si un nouvel élément est ajouté à la plateforme, il faudra compléter la liste use des éléments de la plateforme.

La documentation officielle du fichier de description est disponible sur le site de soclib.

Modification des paramètre de compilation

Les paramètres de compilation utilisés par soclib-cc tels que:

  • le compilateur
  • les options de compilation
  • les options d'édition de liens
  • ...

peuvent être modifiés dans l'un des fichiers de configuration suivant:

  • ~/.soclib/global.conf : configuration globale pour l'utilisateur
  • ./soclib.conf : configuration pour la plateforme actuelle

La liste complète des options et la syntaxe à utiliser est disponible sur le site de soclib.

Analyse du logiciel

Le logiciel qui sera exécuté par le LM32 se trouve dans le répertoire soft.

Le fichier Makefile qui s'y trouve, décrit les opérations nécessaires pour la construction de l'exécutable soft.elf.

Le programme principal se trouve dans le fichier main.c. Pour l'instant ce programme calcul puis affiche les 9 première valeurs du suite de Fibonacci.

La compilation de la partie logicielle se fait pour une cible LM32. La chaîne de compilation comprend un compilateur C (gcc) et une bibliothèque C (la newlib) fonctionnelle.

Le script de d'édition de liens soclib.ld précise l'organisation mémoire et défini quelques symboles comme par exemple l'adresse du tty virtuel (uart).

Remarque : Arrêt de la simulation à partir du code exécuté par le processeur

A la fin du programme la fonction exit est appelée. Dans l'implémentation que nous vous fournissons, celle-ci fait appel à l'instruction break du LM32 qui génère une exception (un breakpoint logiciel).

Cette exception est interceptée par le module SystemC Iss2Simhelper qui arrête la simulation en appelant sc_stop().

Si vous voulez, vous aussi, arrêter la simulation dans le code C vous pouvez soit appeler la fonction exit ou générer la même exception en utilisant l'instruction break. Le code assembleur suivant utilise la directive asm et peut être inséré dans votre code C:

asm volatile("break");

Comment le logiciel est-il chargé dans la plateforme virtuelle:

Dans le fichier SystemC qui décrit le système, un module loader est utilisé pour le chargement du logiciel dans la RAM. Ce module prend comme argument de constructeur le chemin vers le fichier ELF qui est utilisé.

Le chemin est relatif au répertoire d'où sera exécutée la simulation.

soclib::common::Loader loader("soft/soft.elf");

Ce loader est ensuite passé en argument des instances de mémoires qui seront ainsi automatiquement chargées en fonction des sections du fichier ELF et du mapping mémoire.

soclib::caba::VciRom<vci_param> rom("rom", IntTab(0), maptab, loader);

Le chargement se fait au moment de l'exécution de la simulation, on peut donc modifier le code du logiciel sans recompiler la plateforme virtuelle (ie. faire make dans le répertoire soft)

  • Liens utiles:
    • La documentation de référence du Lattice Mico32 (LM32) est accessible localement ici:

/comelec/softs/opt/soclib/TPT/doc/LatticeMico32ProcessorReferenceManual.pdf

remarque: nous n'utilisons que le cœur du processeur, pas les périphériques fournis par Lattice

Ajout d'un esclave WB

Ajouter un esclave WishBone à votre HelloWorld

Ajout d'un esclave WB

Cette section présente la façon avec la quelle vous pouvez ajouter un esclave à la structure du SoC et donne un exemple simple de modèle d'esclave WishBone.

Ajouter l'esclave au HelloWorld:

Pour commencer on vous propose un esclave simple, celui-ci contient un compteur de requêtes qui s'incrémente à chaque écriture. On peut récupérer la valeur de ce compteur en lisant à n'importe quelle adresse dans la plage d'adresses réservées à l'esclave WishBone.

Dans le sous dossier IPs/wb_simple_slave vous trouverez les trois fichiers suivants:

  • Un .h fichier d'en-tête où le module est déclaré
  • Un fichier .cpp contenant le code du module
  • Un fichier .sd contenant la description des dépendances pour l'outilsoclib-cc.

Modification du fichier top.cpp:

  1. Premièrement, il ajoutez le fichier d'en-tête
#include "wb_simple_slave.h"
  1. Ajoutez une entrée à la table d'adressage, par exemple:
maptab.add(Segment("wb_slave"  , WBS_BASE  , WBS_SIZE  , IntTab(3), false));

N'oubliez pas de définir les adresses dans le fichier segmentation.h.

  1. Ajoutez un signal Wishbone pour relier le module esclave.
 soclib::caba::WbSignal<wb_param> signal_wb_slave("signal_wb_slave");
  1. Ajoutez un esclave à l'interconnect en augmentant le nombre d'esclave:
soclib::caba::WbInterco<wb_param> wbinterco("wbinterco",maptab, 1,4);
  1. Enfin, instanciez et reliez ses port aux signaux prévus ainsi qu'à l'interconnect
soclib::caba::WbSimpleSlave<wb_param> simple_slave ("WB_simple_slave");
simple_slave.p_clk              (signal_clk);
simple_slave.p_resetn           (signal_resetn);
simple_slave.p_wb               (signal_wb_slave);

...

wbinterco.p_to_slave[3](signal_wb_slave);

Modification du fichier de description de plateforme:

Il faut modifier le fichier de description de plateforme utilisé par soclib-cc (platform_desc) en y ajoutant l'esclave à la liste des modules utilisé.

Uses('caba:wb_simple_slave'),

Le nom du module pour soclib-cc est celui qui est indiqué dans le fichier .sd.

De plus, pour que l'outil soclib-cc le retrouve, il faut donner le chemin vers le répertoire qui contient le fichier .sd de l'esclave. Ceci peut être fait en lui passant le chemin avec l'option -I. soclib-cc cherche récursivement aussi dans les sous répertoires.

Modifiez éventuellement le Makefile où une variable SOCLIB_INCLUDES est déjà prévue.

Accéder à l'esclave à partir du lm32:

Pour tester l'esclave WishBone, vous pouvez modifier le fichier le programme principale (soft/main.c).

Faites des lectures/écritures aux adresses réservées à l'esclave et observez le résultat sur la console et sur les traces de simulation.

Vous pouvez par exemple:

  • Écriture:
*((volatile unsigned int*) WB_TARGET) = valeur;
  • Lecture:
valeur = *((volatile unsigned int*) WB_TARGET);

N'oubliez pas de définir WB_TARGET à partir de WBS_BASE et WBS_SIZE.

Ajout d'un maitre WB

Ajout d'un maitre WishBone:

 

Ecrire Un maître WishBone:

Le sous dossier IPs/wb_simple_master contient le squelette d'un module WishBone maitre. Attention, ce module ne fait rien, il ne fait que signaler son existence au reset puis à chaque front d'horloge.

Modifier le maître pour faire quelques requêtes d'écriture puis de lecture vers un esclave WishBone.

Votre maître pourra, par exemple, lire des données ou modifier des données en RAM ou accéder à l'esclave que vous aviez ajouté dans la partie précédente.

Souvenez vous que ceci n'est qu'un modèle et que vous n'êtes pas obligés de suivre les recommendations de codage SocLib. Si vous pensez que c'est plus simple, vous pouvez utiliser des SC_THREAD à la place des SC_MTHODE de l'exemple.

  • Liens utiles: /comelec/softs/opt/soclib/TPT/doc/wishbone.pdf
    • La norme WishBone

Question

  • Comment faire pour garantir que les accès du maître ajouté et de processeur ne sont jamais en conflit?