Préambule

Objectifs

Les éléments de base de SystemC (signaux, ports, ...) sont des classes génériques, des template au sens C++. Selon les objets qu'ils représentent, on doit les spécialiser pour un type particulier, préciser leur nombre de bits, leur nature (entier ou flottant), ...

L'objectif de ce chapitre est de vous présenter les types additionnels définis par SystemC. A l'issue de ce chapitre, vous serez en mesure de choisir le meilleur type pour l'objet que vous voulez modéliser, en termes d'adéquation et de vitesse de simulation.

Plan du chapitre

Les modèles SystemC peuvent manipuler différents types de données : les types natifs C++ bien sûr, mais aussi certains types évolués spécifiquement dédiés au matériel. Les types natifs simulant souvent plus vite que les types évolués SystemC...

Voici les principaux types de SystemC :

Back to top

Les types bits

SystemC propose deux types de bit : sc_bit et sc_logic

sc_bit

Attention : ce type est maintenant obsolète (depuis SystemC 2.2.0). Il n'est cité ici qu'à titre indicatif. On utilisera plutôt le type bool.

Ce type est destiné à représenter un bit ne pouvant prendre que deux valeurs, '0' (false) et '1' (true). Si on besoin de Z et X, il faut prendre sc_logic.

Il dispose de tous les opérateurs habituels logiques et de comparaison. Il peut aussi être mixé à volonté avec le type bool et les expressions logiques C/C++.

Exemple :

sc_bit a;
sc_bit b;
bool c;

a = '1';
b = a;
a &= b;

if((i==0) || c || a) {...}

sc_logic

Ce type est une extension de sc_bit à la logique 4-valuée. Il représente un bit pouvant prendre les valeurs '0', '1', 'Z' et 'X'. Par défaut, un object sc_logic non initialisé vaut 'X'.

Il dispose des même opérateurs que les types sc_bit et bool, et peut être intermixé avec eux (le type de l'expression résultante est alors sc_logic).

On peut affecter un sc_logic à un sc_bit et vice-versa. L'affectation de 'X' ou 'Z' à un sc_bit provoquera un résultat indéfini et un warning à l'exécution.

Exemple :

sc_logic out;
bool data, enable;

if(enable)
out = data;
else
out = 'Z';

 

 

Back to top

Les types entiers

SystemC propose une extension du type int (généralement sur 32 bits), signés et non-signés, allant de 1 bit à autant qu'on veut : sc_int, sc_uint, sc_bigint, sc_biguint.

sc_int<n>, sc_uint<n>

Ces types sont des entiers signés et non signés (resp.), représentés sur n bits, n allant de 1 à 64 (inclus).
La version signée est représentée en complément à 2.
Si les entiers utilisés n'ont besoin que de 32 bits maximum, on peut compiler son modèle avec l'option -D_32BIT_ ce qui accélèrera les simulations.

Ces types sont utiles pour les opération arithmétiques, mais beaucoup moins rapides à la simulation que le type natif int / unsigned int. Toutes les opérations arithmétiques sont effectuées sur 64 bits, puis tronquées à la taille correcte.

Ils supportent les opération arithmétiques habituelles, ainsi que :

Le MSB est à gauche (n-1), le LSB est à droite (0).

Exemple :

sc_int<12> val1, val2; // entiers signés sur 12 bits
sc_int<64> res; // entier signé sur 64 bits
sc_uint<10> val3; // entier non signé sur 10 bits
sc_int<3> val4; // entier signé sur 3 bits

val1 = 13; // val1 prend "0000000001101"
val2 = val1.range(3,1); // val2 prend "0000000000110", soit +6
val4 = val1.range(3,1); // val4 prend "110", soit -2

res = (val1, val2); // res vaut "00000000011010000000000110"

bool c = val4[1]; // c vaut '1' (true)

 

sc_bigint<n>, sc_biguint<n>

Ces types sont des extensions de sc_int et sc_uint à un nombre de bits arbitraire illimité (en fait, le nombre maximal de bits est fixé par la constante MAX_NBITS dans le fichier sc_constants.h. Pour accélérer les simulations, il peut être nécessaire de la redéfinir).

Ces types se comportent exactement comme sc_int et sc_uint, mais simulent beaucoup plus lentement.

Exercice

 

Back to top

Les vecteurs de bits

Les types vecteurs de bits ne doivent pas être confondus avec les types entiers.
Ce sont des tableaux de bits, pas des nombres. Ils sont optimisés pour les manipulations de bits, et ne disposent pas d'opérations arithmétiques.

sc_bv<n>

Vecteur de bits 2-valués. Il dispose de méthodes de :

Les valeurs littérales sont représentées par des chaînes de caractères.

Exemple :

sc_bv<8> x;
sc_bit y;

x = "01000111";
y = x[6]; // y vaut '1'

sc_bv<16> data16;
sc_bv<32> data32;

data32.range(15,0) = data16;
data16 = (data32.range(7,0), data32.range(23,16));
(data16.range(3,0),data16.range(15,12)) = data32.range(7,0);

 

sc_lv<n>

Vecteur de bits 4-valués (sc_logic). Il accepte donc les valeurs 'X' et 'Z' en plus de celles des sc_bv.
Il est typiquement utilisé pour modéliser des bus de données trois-états (sortie de RAM, ...).

Son comportement est le même que celui des sc_bv, mais simule moins vite.

Pour effectuer des opération arithmétiques sur un sc_bv ou sc_lv, il faut passer par une variable temporaire de type int, sc_int, ... Lors de la conversion, si un 'X' ou 'Z' est présent, le résultat est indéfini, et un warning est déclenché à l'exécution.

 

 

Back to top

Les nombres en virgule fixe

Attention : pour accélérer les temps de compilations, ces types ne sont normalement pas disponibles. Pour pouvoir les utiliser, il est nécessaire de spécifier #define SC_INCLUDE_FX avant #include "systemc.h" dans votre code.

Les système numériques travaillant sur des nombres décimaux les représentent souvent en virgule fixe. SystemC propose quatre types pour représenter ces nombres en virgule fixe, avec différents modèles de quantification et de dépassement.

 
signés   non-signés  
  paramètres déterminés à la compilation  
  sc_fixed  
sc_ufixed
paramètres dynamiques
sc_fix
sc_ufix


Types flottants en virgule fixe

Ces types acceptent aussi une version suffixée par "_fast" si la mantisse est sur moins que 53 bits.

sc_fixed<>, sc_ufixed<>

Ces types ont des paramètres de quantification et de débordement définis à la compilation, et sont respectivement signés et non signés.

Syntaxe :

sc_fixed<wl, iwl, q_mode, o_mode, n_bits> object_name, object_name, ... ;

sc_ufixed<wl, iwl, q_mode, o_mode, n_bits> object_name, object_name, ... ;

Exemple :

float adder(float a, float b)
{
sc_fixed_fast<4,2,SC_RND,SC_WRAP> Inputa = a;
sc_fixed_fast<6,3,SC_RND,SC_WRAP> Inputb = b;
sc_fixed_fast<7,4,SC_RND,SC_WRAP> Output;

Output = (Inputa + Inputb);
return (Output);
}
 

sc_fix<>, sc_ufix<>

Ces types sont les mêmes que sc_fixed et sc_ufixed, mais leurs paramètres peuvent être changés lors de l'exécution.

Les paramètres sont précisés à l'aide du type sc_fxtypes_params, qui prennent en arguments les même paramètres que sc_fixed et sc_ufixed.
sc_fxtypes_context précise les paramètres par défaut des sc_fix et sc_ufix.

Exemple :

sc_fxtype_params param1 (10,4,SC_RND, SC_SAT); 
// xxxxxx.yyyy
// round to closest representable number
// saturate on overflow

sc_fix_fast valeur (param1);

sc_fxtype_params myparams(SC_RND, SC_SAT);
sc_fxtype_context mycontext(myparams);
sc_fix_fast adder(sc_fix_fast a, sc_fix_fast b)
{
// specify output wl and iwl to be one bit larger
// than wl and iwl of a sc_fix_fast Output(a.wl() + 1, a.iwl() + 1);
sc_fix_fast Output(a.wl() + 1, a.iwl() + 1);
Output = a + b;
return(Output);
}

 

 

Back to top

Le temps

En SystemC 2.x, comme en Verilog et VHDL, le modèle sous-jacent pour le temps est de type entier non signé sur 64 bits. La résolution par défaut est 1ps.

Une valeur temporelle est de type sc_time, et demande deux arguments lors de sa création :

sc_time_unit peut valoir :

sc_time est muni de méthodes de :

Exemple :

sc_time t1( 20, SC_NS );

 

Back to top

ExerciCES

Question 1

Question 2

Question 3

Pour les questions 1 et 2, vous justifierez vos choix des types de données. La question 3 est une question de culture générale, mais importante car beaucoup de mythes circulent à ce sujet !
Réponses à déposer sur votre dépôt Git.

Back to top

En résumé

En logique 2-valuée :

  • Utiliser les types natifs C++ dès que possible (les tailles indiquées ici sont valides sur Linux)
    • bool pour les valeurs sur 1 bit
    • unsigned char pour les valeurs sur 8 bits
    • unsigned short pour les valeurs sur 16 bits
    • unsigned int pour les valeurs sur 32 bits
    • unsigned long pour les valeurs sur 32 bits (i386) ou 64 bits (x86_64)
    • unsigned long long pour les valeurs sur 64 bits
  • Entre 1 et 64 bits, et taille non puissance de 2 :
    • sc_int, sc_uint
  • Plus de 64 bits, ou pas besoin d'opérations arithmétiques :
    • sc_bv

En logique 4-valuée :

  • sc_logic, sc_lv

Manipulation de flottants en virgule fixe :

  • mantisse de plus que 53 bits : sc_fixed, sc_ufixed, sc_fix, sc_ufix
  • mantisse de moins que 53 bits : sc_fixed_fast, sc_ufixed_fast, sc_fix_fast, sc_ufix_fast

 


Back to top