Mixer les langages «La co-simulation»
2023-2024
Utiliser SyetemC pour la simulation et la vérification de modèle RTL écrits dans d’autres langages.
Les modèles RTL sont généralement écrits en utilisant les sous-ensembles synthétisables des langages HDL communs (VHDL, Verilog/SystemVerilog)
Même dans ce cas, SystemC peut être utilisé pour concevoir un environnement de simulation pour vérifier et valider le modèle RTL.
Les avantages de l’utilisation de SystemC viennent principalement de:
D’un autre côté:
La co-simulation consiste en la mise en œuvre d’une simulation dans laquelle les éléments ont été écrits dans des langages différents.
Pour pouvoir le faire:
Si on doit faire une simulation évènementielle, les langages utilisés doivent prévoir les concepts:
De plus, on doit pouvoir représenter la structure des modules simulés dans les deux langages.
Les langages RTL communément utilisés (VHDL, Verilog/SystemVerilog) ont été conçus autour de ces concepts. SystemC ajoute ces concepts à C++.
De plus, il faut pouvoir exprimer les données manipulées avec la bonne granularité (entier, bits, vecteurs/bus…) dans les deux langages. Il n’est généralement pas possible de faire passer d’un langage vers l’autre des structures de données plus complexes (interfaces SystemVerilog, des structures…).
Généralement le point bloquant vient de l’outil utilisé:
Ce que nous allons faire ici c’est simuler un design HDL décrit en Verilog/SystemVerilog dans un environnement en SystemC.
Cet environnement contiendra de quoi générer des stimuli et vérifier les réponses du bloc HDL (DUT : Design Under Test).
Il serait aussi envisageable d’insérer un module SystemC dans un banc de test (testbench) écrit dans un autre langage, mais ce ne sera pas présenté dans ce cours.
Nous allons voir deux exemples de simulation d’un module RTL (Verilog/SystemVerilog) dans un testbench écrit en SyetemC.
Deux approches:
Ici nous allons mettre en œuvre deux approches differentes:
Modelsim
Avec Modelsim on doit utiliser un module wrapper SystemC qui est compilé avec le testbench. Ce module est une coquille vide qui ne contient pas de code comportemental, mais doit:
foreign module
) du simulateur
pour le lier au module HDL pour mettre en relation le wrapper avec le
module HDL durant la phase d’élaboration.Ce wrapper peut être écrit à la main ou généré automatiquement après
compilation du module HDL (scgenmod --help
pour plus
d’informations.)
module counter ( input clk, nrst, enable,
output logic[7:0] Q
);
// ...
endmodule
#ifndef _SCGENMOD_counter_
#define _SCGENMOD_counter_
#include "systemc.h"
class counter : public sc_foreign_module
{
public:
<bool> clk;
sc_in<bool> nrst;
sc_in<bool> enable;
sc_in<sc_uint<8> > Q;
sc_out
(sc_module_name nm, const char* hdl_name)
counter: sc_foreign_module(nm),
("clk"),
clk("nrst"),
nrst("enable"),
enable("Q")
Q{
(hdl_name);
elaborate_foreign_module}
~counter()
{}
};
#endif
Contrairement à un sc_module
, ici on hérite d’un
sc_foreign_module
qui est une classe propre à Modelsim.
L’interface de ce module (ses entrées/sorties) correspondent à celles
du module HDL. Les types qui existent dans les deux langages ne sont pas
les même, Modelsim (se référer à la documentation de l’outil) prévoit
plusieurs possibilités. Dans cet exemple, on fait correspondre aux bits
Verilog des bool
et aux vecteurs des
sc_uint<>
mais nous aurions pu utiliser
respectivement des sc_logic
et des sc_lv
.
Le constructeur de ce module prend 2 arguments, l’un correspondant au
nom de l’instance (sc_module_name
) au sens SystemC et
l’autre correspondant au nom du module HDL auquel il doit être lié.
Sinon, le constructeur ne fait qu’appeler une méthode
elaborate_foreign_module
qui déclenchera un mécanisme
interne du simulateur pour l’élaboration du module RTL.
#include <systemc.h>
#include "counter.h"
int sc_main(int argc, char * argv[]) {
//..
// inst. name RTL module
("counter_0", "counter");
counter counter_0.clk( xx );
counter_0//...
("counter_1", "counter");
counter counter_1.clk( xx );
counter_1//...
return 0;
}
Ensuite, le module wrapper peut être instancier et utilisé comme un module SystemC standard.
Modelsim
La génération du module wrapper peut être automatisée en utilisant la
commande scgenmod
de Modelsim après compilation du module
HDL. scgenmod
possède aussi des options pour préciser les
correspondances entre les types HDL et SystemC.
La commande de Modelsim pour compiler des fichiers SystemC est
sccom
. Elle utilise en interne une version de
g++
fournie avec l’outil. Aussi, sccom --link
doit être appelé après la compilation pour l’édition de liens.
sccom
définit la macro MTI_SYSTEMC
qui peut
être testée pour écrire du code spécifique pour Modelsim.
Verilator
Utiliser un “convertisseur” qui converti le Verilog en C++/SystemC:
Verilator
: https://www.veripool.org/wiki/verilatorVerilator est un outil qui analyse du code HDL (seulement Verilog ou SystemVerilog) et qui génère un AST (Abstract Syntaxic Tree).
À partir de cet AST il peut:
Il a été développé pour générer des simulateurs rapides à partir de modèles RTL.
C’est un outil libre dont le code source est distribué sous les termes de la licence LGPLv3. Le code source est disponible ici et des versions binaires sont disponibles dans la majorité des distributions Linux.
Verilator permet donc de générer un modèle de simulation SystemC à partir d’un module Verilog ou SystemVerilog.
Le module généré peut alors être intégré dans une simulation SystemC standard.
Verilator
L’outil sait aussi générer un Makefile pour automatiser la compilation.
Pour le module Verilog précédent (counter
) on obtient le
module SystemC Vcounter
:
#ifndef _Vcounter_H_
#define _Vcounter_H_
#include "systemc.h"
#include "verilated_sc.h"
#include "verilated.h"
(Vcounter) {
SC_MODULEpublic:
<bool> clk;
sc_in<bool> nrst;
sc_in<bool> enable;
sc_in<sc_uint<8> > Q;
sc_out
....
}
#endif
Ce modèle peut être instancié directement dans un autre module
SystemC ou directement dans le sc_main
.
Pour obtenir ce module verilator
est utilisé avec les
options suivantes:
verilator -sc --pins-sc-uint counter.sv
La première option indique que l’on veut un modèle SystemC, la
seconde qu’on veut des sc_uint
pour les signaux de
l’interface dont la largeur est supérieure à 1.
Si l’on souhaite spécialiser le code, la macro VM_SC
peut être testée.
En réalité, le module généré est un peu plus complexe et contient des références à des objets internes de l’outil.
// Verilated -*- SystemC -*-
// DESCRIPTION: Verilator output: Primary design header
//
// This header should be included by all source files instantiating the design.
// The class here is then constructed to instantiate the design.
// See the Verilator manual for examples.
#ifndef _Vcounter_H_
#define _Vcounter_H_
#include "systemc.h"
#include "verilated_sc.h"
#include "verilated.h"
class Vcounter__Syms;
//----------
(Vcounter) {
SC_MODULEpublic:
// PORTS
// The application code writes and reads these signals to
// propagate new values into/out from the Verilated model.
<bool> clk;
sc_in<bool> nrst;
sc_in<bool> enable;
sc_in<sc_uint<8> > Q;
sc_out
// LOCAL SIGNALS
// Internals; generally not touched by application code
// LOCAL VARIABLES
// Internals; generally not touched by application code
(__Vcellout__counter__Q,7,0);
VL_SIG8
// INTERNAL VARIABLES
// Internals; generally not touched by application code
* __VlSymsp; // Symbol table
Vcounter__Syms
// PARAMETERS
// Parameters marked /*verilator public*/ for use by application code
// CONSTRUCTORS
private:
(Vcounter); ///< Copying not allowed
VL_UNCOPYABLEpublic:
(Vcounter);
SC_CTORvirtual ~Vcounter();
// API METHODS
private:
void eval();
public:
void final();
// INTERNAL METHODS
private:
static void _eval_initial_loop(Vcounter__Syms* __restrict vlSymsp);
public:
void __Vconfigure(Vcounter__Syms* symsp, bool first);
private:
static QData _change_request(Vcounter__Syms* __restrict vlSymsp);
void _ctor_var_reset();
public:
static void _eval(Vcounter__Syms* __restrict vlSymsp);
private:
#ifdef VL_DEBUG
void _eval_debug_assertions();
#endif // VL_DEBUG
public:
static void _eval_initial(Vcounter__Syms* __restrict vlSymsp);
static void _eval_settle(Vcounter__Syms* __restrict vlSymsp);
static void _settle__TOP__1(Vcounter__Syms* __restrict vlSymsp);
} VL_ATTR_ALIGNED(128);
#endif // guard
Par défaut, ce fichier d’en-tête, ainsi qu’un fichier C++, sont
générés dans un sous-répertoire obj_dir
. La méthode
eval
est l’unique méthode SystemC (SC_METHOD
)
dans laquelle se trouve tout le comportement du module RTL.
L’observation des signaux interne n’est pas donc possible par défaut
pour obtenir la meilleure performance.
On peut aussi demander à Verilator de générer un
Makefile
pour automatiser la compilation. Par exemple:
verilator -sc --pins-sc-uint -exe counter.sv sc_main.cpp -o ../sim.exe
Générera un Makefile (Vcount.mk
) dans le répertoire
obj_dir
permettant de compiler un exécutable nommé
sim.exe
dans le répertoire courant.
Pour obtenir la documentation de l’outil et la liste des options:
verilator --help
Reprendre l’exemple du PGCD
.
Voici le code SystemVerilog d’un module RTL calculant le
PGCD
de deux nombres codés sur 8 bits. Il possède la même
interface et le même comportement que le module demandé dans le chapitre
“Niveaux d’abstraction et raffinement”.
module PGCD (
input clk,
input valid,
input [7:0] a,
input [7:0] b,
output ready,
output [7:0] pgcd
);
[7:0] max, min;
logic wire [7:0] d = max-min;
@(posedge clk)
always_ff if (valid)
begin
<= (a>b)? a:b;
max <= (a>b)? b:a;
min end
else
begin
<= (d>min)? d : min;
max <= (d>min)? min : d;
min end
assign pgcd = max;
assign ready = (min==max);
endmodule
Travail à faire : mettre en place un environnement
de simulation en SystemC en reprenant le sc_main
existant,
permettant de simuler ce module SystemVerilog en utilisant Modelsim et
Verilator.
sc_main
doit instancier un module
testeur
qui génère des séquences de test et vérifie la
validité du résultat renvoyé.sc_main
doit être compatible avec les deux
outils.© Copyright 2016-2024, Tarik Graba, Télécom Paris. | |
Le contenu de cette page est mis à disposition selon les termes de la Licence Creative Commons Attribution - Partage dans les Mêmes Conditions 4.0 International . | |
Ce document reprend des parties du cours en ligne sur SystemC d'Alexis Polti disponible ici. |