Learning SystemC: #001 Data Types

Learning SystemC: #001 Data Types

Posted by

In this post I will talk about the data types part of the SystemC library.
Here is a list of content if you want to jump to a particular subject:

1. Fixed-precision integer types
   1.1 sc_int
   1.2 sc_uint
   1.3 sc_bigint and sc_biguint
2. Logic and arbitrary width vector types
   2.1 sc_logic
   2.2 sc_lv<W>
3. Fixed-Point Types
   3.1 Fixed-Point Parameters
      3.1.1. World length (WL) and Integer Word Length (IWL)
      3.1.2. Quantization Mode (QUAT)
         3.1.2.1. Quantization for Signed Fixed-Point Numbers
         3.1.2.2. Quantization for Unsigned Fixed-Point Numbers
      3.1.3. Overflow Mode (OVFW) and Number of Saturation Bits (NBITS)
         3.1.3.1. Overflow for Signed Fixed-Point Numbers
         3.1.3.2. Overflow for Unsigned Fixed-Point Numbers
   3.2 Fixed-Point Classes



1. Fixed-precision integer types

In hardware world it is mandatory to use a precise number of bits when representing a number. This is because the HDL code will be synthesized to a physical implementation in silicon where every register bit takes up area and this costs money.
For example, one might declare in Verilog a 10 bit counter like this:

1
reg[9:0] counter

In the software world there is no requirement for such a fine granularity. In the best case we have usually a 8 bit granularity when it comes to data types widths in bits. For example some of the basic data types that we have natively in C language are:

  • char– width: >= 8
  • int– width: >= 16
  • long– width: >= 32
  • etc

SystemC comes with a solution for this problem with four parameterized classes.

Signed Unsigned
LENGTH ≤ 64 sc_int<LENGTH> sc_uint<LENGTH>
LENGTH > 64 sc_bigint<LENGTH> sc_biguint<LENGTH>

Let’s see some usage examples.

1.1. sc_int

First, we can take a look at an example for sc_int class:

1
2
3
4
5
6
7
8
9
//we can initialize the variable by direct assignment
sc_int<3> my_a = -1;
 
//we can initialize the variable via its constructor
sc_int<4> my_b(2);
 
sc_int<4> result = my_a + my_b;
 
cout << "sc_int: " << my_a << " + " << my_b << "  = " << result << endl;

We can use different styles for initializing our variables. For the code above we will get the following output:

1
sc_int: -1 + 2  = 1

1.2. sc_uint

In the example for sc_uint class we can easily see the overflow effect as we do not have enough bits in the result to store the correct result of the operation:

1
2
3
4
5
6
7
sc_uint<3> my_a = 3;
sc_uint<4> my_b(15);
 
//there is an overflow here as we do not have enough bits to store the correct result
sc_uint<4> result = my_a + my_b;
 
cout << "sc_uint: " << my_a << " + " << my_b << "  = " << result << endl;

The output:

1
sc_uint: 3 + 15  = 2

1.3. sc_bigint and sc_biguint

Of course, the other two classes, sc_bigint and sc_biguint are used in exactly the same manner. You can even combine them:

1
2
3
4
5
6
7
8
sc_biguint<128> my_a = 11;
sc_bigint<128> my_b = 3;
 
sc_bigint<128> result = my_a / my_b;
 
//even if the result is 3.666 we are dealing with integers
//so the result is truncated down to the closest integer value
cout << "sc_biguint & sc_bigint: " << my_a << " / " << my_b << "  = " << result << endl;

As in all integer operations, the result is rounded down to the closest integer:

1
sc_biguint & sc_bigint: 11 / 3  = 3

You can find all these examples on EDA Playground.

Choosing between native C++ types and these SystemC types must be done with care as SystemC types comes with a slower simulation comparing to native C++ types. Here are some guidelines for you to follow when deciding what types to use:

  • use these SystemC types if in the end you will use synthesis on your SystemC code
  • use these SystemC types to have the overflow effect out of the box
  • use the proper SystemC class based on length and signed/unsigned as in the table from the beginning of this chapter

2. Logic and arbitrary width vector types

In a HDL like Verilog or VHDL, despite the fact that they are used for describing digital logic, a modeled bit of information can have more than just two values: ‘0’ or ‘1’. Most commonly you will see that, for example in Verilog, a register might also take some other values like:

  • High Impedance – to model a physical wire left unconnected. This is represented as value ‘z’
  • Unknown – to model a physical wire which which has an unknown value due to several reasons – one reason being that is can have two driving sources, or that the wire was never assigned. This is represented as value ‘x’

Such multi-value logic is modeled in SystemC by two classes:

  • sc_logic – for modeling one bit of information with its four states: ‘0’, ‘1’, ‘x’ and ‘z’
  • sc_lv<W> – a parameterized class to model a logic vector

For modeling a purely boolean representation of a bit (two values) there are other two classes:

  • sc_bit (deprecated) – for modeling one bit of information with its two states: ‘0’ and ‘1’
  • sc_bv – a parameterized class to model a bit vector

Let’s see some usage examples of these classes.

2.1. sc_logic

There are a lot of ways to initialize a sc_logic class:

  • using predefined constants: SC_LOGIC_0, SC_LOGIC_1, SC_LOGIC_X, SC_LOGIC_Z
  • using boolean values: true, false
  • using special characters: ‘0’, ‘1’, ‘X’ or ‘Z’
  • using sc_logic_value_t type: Log_0, Log_1, Log_X or Log_Z

Here is an example that you can also try it for yourself on EDA Playground:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//one can use the values of constants SC_LOGIC_0, SC_LOGIC_1, SC_LOGIC_X, SC_LOGIC_Z
sc_logic val_0 = SC_LOGIC_0;
 
//once can use the boolean values 'true' or 'false' to initialize a sc_logic class
sc_logic val_1(true);
 
//one can use the values of the type sc_logic_value_t: Log_0, Log_1, Log_X or Log_Z
sc_logic val_x(Log_X);
 
//one can use even the characters '0', '1', 'X' or 'Z'
sc_logic val_z('Z');
 
sc_logic result_a = val_0 & val_1;
sc_logic result_b = val_0 | val_1;
sc_logic result_c = val_x ^ val_z;
 
cout << val_0 << " & " << val_1 << " = " << result_a << endl;
cout << val_0 << " | " << val_1 << " = " << result_b << endl;
cout << val_x << " ^ " << val_z << " = " << result_c << endl;

The output is:

1
2
3
0 & 1 = 0
0 | 1 = 1
X ^ Z = X

There are many operators overloaded for this class so you should be able to cover all your scenarios.
I extracted from the LRM some truth tables for most common operations:

‘0’ ‘1’ ‘Z’ ‘X’
‘0’ ‘0’ ‘0’ ‘0’ ‘0’
‘1’ ‘0’ ‘1’ ‘X’ ‘X’
‘Z’ ‘0’ ‘X’ ‘X’ ‘X’
‘X’ ‘0’ ‘X’ ‘X’ ‘X’
sc_logic AND truth table
‘0’ ‘1’ ‘Z’ ‘X’
‘0’ ‘0’ ‘1’ ‘X’ ‘X’
‘1’ ‘1’ ‘1’ ‘1’ ‘1’
‘Z’ ‘X’ ‘1’ ‘X’ ‘X’
‘X’ ‘X’ ‘1’ ‘X’ ‘X’
sc_logic OR truth table
‘0’ ‘1’ ‘Z’ ‘X’
‘0’ ‘0’ ‘1’ ‘X’ ‘X’
‘1’ ‘1’ ‘0’ ‘X’ ‘X’
‘Z’ ‘X’ ‘X’ ‘X’ ‘X’
‘X’ ‘X’ ‘X’ ‘X’ ‘X’
sc_logic exclusive or truth table
‘0’ ‘1’ ‘Z’ ‘X’
‘1’ ‘0’ ‘X’ ‘X’
sc_logic complement truth table

2.2. sc_lv<W>

sc_lv<W> is a template class representing a finite logic vector – lv in the name of the class stands for “logic vector”. This class inherits from sc_lv_base so you might want to take a look at this one also to see what API is available for you.
Let’s see some examples on how to use this class:

1
2
3
4
5
6
7
8
9
sc_lv<4> a_vector = "1101";
sc_lv<4> b_vector(0b1110);
 
//normal bitwise operations can be performed in logic vectors
sc_lv<4> c_vector = a_vector & b_vector;
 
cout << "a_vector: " << a_vector << endl;
cout << "b_vector: " << b_vector << endl;
cout << "c_vector: " << c_vector << endl;

sc_lv<W> comes with lots of constructors so you can initialize it in the most intuitive way for you.
SystemC developers took fool advantage of the operator overload so normal bitwise operations can be performed on the logic vectors.
Here is the output of the example from above:

1
2
3
a_vector: 1101
b_vector: 1110
c_vector: 1100

You can run the example for yourself on EDA Playground.

One other interesting aspect to mention here is that the base class, sc_lv_base, has a lot of useful functions. Here is an example with most of the available functions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
sc_lv<4> a_vector = "1101";
 
cout << "a_vector:              " << a_vector << endl;
 
//Bitwise rotations
cout << "a_vector.lrotate(1):   " << a_vector.lrotate(1) << endl;
cout << "a_vector.rrotate(1):   " << a_vector.rrotate(1) << endl;
 
//Bitwise reverse
cout << "a_vector.reverse():    " << a_vector.reverse() << endl;
 
//Bit selection
cout << "a_vector[3]:           " << a_vector[3] << endl;
 
//Part selection
cout << "a_vector(3,1):         " << a_vector(3,1) << endl;
cout << "a_vector.range(3,1):   " << a_vector.range(3,1) << endl;
 
//Reduce functions
//<OPERATION>_reduce() – where <OPERATION> can be: and, nand, or, nor, xor, xnor
cout << "a_vector.and_reduce(): " << a_vector.and_reduce() << endl;

And the output:

1
2
3
4
5
6
7
8
a_vector:              1101
a_vector.lrotate(1):   1011
a_vector.rrotate(1):   1101
a_vector.reverse():    1011
a_vector[3]:           1
a_vector(3,1):         101
a_vector.range(3,1):   101
a_vector.and_reduce(): 0

You can run the example for yourself on EDA Playground.

3. Fixed-Point Types

Before you continue reading you must make sure you know how fixed-point numbers are represented in binary.
You can take a look at this short YouTube video explaining all you need to know about fixed-point number representation in binary.

IMPORTANT:
In order to have access to fixed point data type classes you must define SC_INCLUDE_FX before you include systemc.h file.
This can be achieved from command line by adding this argument to the compiler: -DSC_INCLUDE_FX

3.1 Fixed-Point Parameters

The SystemC classes used to model the fixed point types have five parameters:

  • Word Length (WL)
  • Integer Word Length (IWL)
  • Quantization Mode (QUAT)
  • Overflow Mode (OVFW)
  • Number of Saturation Bits (NBITS)

In the next sections of this chapter I will try to explain how these parameters are used.

3.1.1. Word Length (WL) and Integer Word Length (IWL)

World Length represents how many bits are used to represent the entire number – must be positive.
Integer Word Length represents how many bits, out of Word Length, are used to represent the integer part – it can have any integer value.

There are three scenarios for a fixed point representation based on the relationship between WL and IWL:

Scenario #1: 0 <= IWL <= WL

This is the easiest scenario to understand. A representation of a number where WL is 5 and IWL is 3 is this:

i i i f f
i = integer bit, f = fractional bit

Let’s try to understand the range.

If we have to represent an unsigned number the lowest number, represented in binary, is 000.00 and in decimal is 0.
The biggest number, represented in binary, is 111.11 and in decimal is 7.75

If we have to represent a signed number, two’s complement representation is used, so the lowest number in binary is 100.00 and in decimal is -4.
The biggest number, represented in binary, is 011.11 and in decimal is 3.75

Scenario #2: WL < IWL

In this scenario we have more bits to represent the integer part than there are to represent the entire number. Strange right?
In the actual representation the remaining bits (IWLWL) are all zero.
A representation of a number where WL is 5 and IWL is 7 is this:

i i i i i 0 0
i = integer bit

Let’s try to understand the range.

If we have to represent an unsigned number the lowest number, represented in binary, is 0000000 and in decimal is 0.
The biggest number, represented in binary, is 1111100 and in decimal is 124

If we have to represent a signed number, two’s complement representation is used, so the lowest number in binary is 1000000 and in decimal is -64.
The biggest number, represented in binary, is 0111100 and in decimal is 60

Scenario #3: IWL < 0 < WL

This is the hardest scenario to understand.
In this scenario we have a negative number of bits to represent the integer part. These bits will actually be a copy of the sign bit, for signed representations and zero for unsigned representations.
A representation of a signed number where WL is 5 and IWL is -2 is this:

s s f f f f f
s = sign bit, f = fractional bit

A representation of an unsigned number where WL is 5 and IWL is -2 is this:

0 0 f f f f f
f = fractional bit

Let’s try to understand the range.

If we have to represent an signed number, two’s complement representation is used, so the lowest number, represented in binary, is .1110000 and in decimal is -0.125
The biggest number, represented in binary, is .0001111 and in decimal is 0.1171875

If we have to represent a unsigned number the lowest number in binary is .0000000 and in decimal is 0.
The biggest number, represented in binary, is .0011111 and in decimal is 0.2421875

3.1.2. Quantization Mode (QUAT)

Quantization Mode represents the way to handle the case when the precision of an assigned value exceeds the precision of a fixed-point variable.

For example, let’s say that we have a fixed point number with WL = 4 and IWL = 2 and it is equal to 0.75 (decimal) and in binary 0011.
If we want to assign it to a fixed point number with WL = 3 and IWL = 2, quantization mode dictates how the rounding shall be performed.

1
2
3
4
5
6
//this number has two fractional bits
sc_fixed<4,2> a = 0.75;

//this number has only one fractional bit
//quantization algorithm dictates what value b variable will have
sc_fixed<3, 2> b = a;

The quantization modes available in SystemC in the enum sc_q_mode and the possible values are listed in the table below.

Quantization mode Name
Rounding to plus infinity SC_RND
Rounding to zero SC_RND_ZERO
Rounding to minus infinity SC_RND_MIN_INF
Rounding to infinity SC_RND_INF
Convergent rounding SC_RND_CONV
Truncation SC_TRN
Truncation to zero SC_TRN_ZERO
Quantization modes

In the end the idea behind these quantization modes is this – put the most significant bits of the high precision number in the low precision number and use the quantization algorithm to determine a value to be added to the low precision number.

3.1.2.1. Quantization for Signed Fixed-Point Numbers

Each of the quantization modes available in sc_q_mode has a mathematical formula which is applied in order to do the quantization.
In order to understand those mathematical formulas you need to understand some terminology involved.

Higher precision number x x x x x x x x
Lower precision number x x x x x
Flags sR R R R lR mR D D
Flags at bit level applied for quantization algorithms

The flags in the table above have the following meaning:

  • x – a binary digit (0 or 1)
  • sR – a sign bit
  • R – the remaining bits
  • lR – the least significant remaining bit
  • mR – the most significant deleted bit
  • D – the deleted bits

In the mathematical formulas of the quantization algorithms it is used a symbol r – which is the logical OR between all the bits with flag D.
The table below list all the available quantization modes and how is computed the value to be added to the lower precision numer.

Quantization mode Expression to be added Details
SC_RND mD Add the most significant deleted bit to the remaining bits.
SC_RND_ZERO mD & (sR | r) If the most significant deleted bit is 1, and either the sign bit or at least one other deleted bit is 1, add 1 to the remaining bits.
SC_RND_MIN_INF mD & r If the most significant deleted bit is 1 and at least one other deleted bit is 1, add 1 to the remaining bits.
SC_RND_INF mD & (! sR | r) If the most significant deleted bit is 1, and either the inverted value of the sign bit or at least one other deleted bit is 1, add 1 to the remaining bits.
SC_RND_CONV mD & (lR | r) If the most significant deleted bit is 1, and either the least significant of the remaining bits or at least one other deleted bit is 1, add 1 to the remaining bits.
SC_TRN 0 Copy the remaining bits.
SC_TRN_ZERO sR & (mD | r) If the sign bit is 1, and either the most significant deleted bit or at least one other deleted bit is 1, add 1 to the remaining bits.
Quantization handling for signed fixed-point numbers

Let’s see some examples for some of the quantization modes.

Rounding to plus infinity (SC_RND)

For this algorithm, the value to be added to the lower precision number is mD – most significant deleted bit.

1
2
3
4
5
6
7
8
9
//this number has 5 fractional bits
sc_fixed<8,3> a = -2.3125;
 
cout << "        a in dec: " << a << ", a in bin: "<< a.to_bin() << endl;
 
//this number has 2 fractional bits
sc_fixed<5,3, SC_RND> b_sc_rnd = a;
 
cout << "SC_RND - b in dec: " << b_sc_rnd << ",   b in bin: "<< b_sc_rnd.to_bin() << endl;

In this case mD is a[2] = 1 – bit index 2 counting from right to left.
So, b_sc_rnd before adding the value of the quantization algorithm is 0b101.10
Once we add quantization mode value we have b_sc_rnd = 0b101.11

1
2
         a in dec: -2.3125, a in bin: 0b101.10110
SC_RND - b in dec: -2.25,   b in bin: 0b101.11

You can run the full example on EDA Playground.

Truncation (SC_TRN)

For this algorithm, the value to be added to the lower precision number is 0 so things are much simpler – this is the default quantization mode.

1
2
3
4
5
6
7
8
9
//this number has 5 fractional bits
sc_fixed<8,3> a = -2.3125;
 
cout << "         a in dec: " << a << ", a in bin: "<< a.to_bin() << endl;
 
//this number has 2 fractional bits
sc_fixed<5,3, SC_TRN> b_sc_rnd = a;
 
cout << "SC_RND - b in dec: " << b_sc_rnd << ",    b in bin: "<< b_sc_rnd.to_bin() << endl;

And the output is:

1
2
         a in dec: -2.3125, a in bin: 0b101.10110
SC_TRN - b in dec: -2.5,    b in bin: 0b101.10

You can run the full example on EDA Playground.

3.1.2.1. Quantization for Unsigned Fixed-Point Numbers

For unsigned numbers the flags are quite similar with the signed numbers with the only difference that sR no longer exists.

Higher precision number x x x x x x x x
Lower precision number x x x x x
Flags R R R R lR mR D D
Flags at bit level applied for quantization algorithms

The table below list all the available quantization modes and how is computed the value to be added to the lower precision numer.

Quantization mode Expression to be added Details
SC_RND mD Add the most significant deleted bit to the left bits.
SC_RND_ZERO 0 Copy the remaining bits.
SC_RND_MIN_INF 0 Copy the remaining bits.
SC_RND_INF mD Add the most significant deleted bit to the left bits.
SC_RND_CONV mD & (lR | r) If the most significant deleted bit is 1, and either the least significant of the remaining bits or at least one other deleted bit is 1, add 1 to the remaining bits.
SC_TRN 0 Copy the remaining bits.
SC_TRN_ZERO 0 Copy the remaining bits.
Quantization handling for unsigned fixed-point numbers
3.1.3. Overflow Mode (OVFW) and Number of Saturation Bits (NBITS)

Overflow Mode represents the way to handle the case when the magnitude of an assigned value exceeds the magnitude of a fixed-point variable.

For example, let’s say that we have a fixed point number with WL = 4 and IWL = 3 and it is equal to 5.5 (decimal) and in binary 0b1011.
If we want to assign it to a fixed point number with WL = 3 and IWL = 2 (maximum integer value is only 3), overflow mode dictates how the assignment shall be performed.

1
2
3
4
5
6
//this number has three integer bits
sc_fixed<4,3> a = 5.5;

//this number has two integer bits
//overflow algorithm dictates what value b variable will have
sc_fixed<3, 2> b = a;

The overflow modes available in SystemC in the enum sc_o_mode and the possible values are listed in the table below.

Overflow Mode Name
Saturation SC_SAT
Rounding to zero SC_SAT_ZERO
Symmetrical saturation SC_SAT_SYM
Wrap-around SC_WRAP
Sign magnitude wrap-around SC_WRAP_SM
Overflow modes

3.1.2.1. Overflow for Signed Fixed-Point Numbers

Each of the overflow modes available in sc_o_mode has a mathematical formula which is applied in order to do the overflow.
In order to understand those mathematical formulas you need to understand some terminology involved.

Higher precision number x x x x x x x x x x
Lower precision number x x x x x x
Flags sD D D lD sR R(N) R(lN) R R lR
Flags at bit level applied for overflow algorithms

The flags in the table above have the following meaning:

  • x – a binary digit (0 or 1)
  • sD – a sign bit before overflow handling
  • D – deleted bits
  • lD – the least significant deleted bit
  • sR – the bit on the MSB position of the result number. For the SC_WRAP_SM, 0 and SC_WRAP_SM, 1 modes, a distinction is made between the original value (sRo) and the new value (sRn) of this bit
  • N – the saturated bits. Their number is equal to the n_bits argument minus 1
  • lN – the least significant saturated bit
  • R – the remaining bits
  • lR – the least significant remaining bit

The table below list all the available overflow modes and how the result is computed.

Overflow mode sR N, lN R, lR Details
SC_SAT sD !sD The result number gets the sign bit of the original number. The remaining bits shall get the inverse value of the sign bit.
SC_SAT_ZERO 0 0 All bits shall be set to zero.
SC_SAT_SYM sD !sD The result number shall get the sign bit of the original number. The remaining bits shall get the inverse value of the sign bit, except the least significant remaining bit, which shall be set to one.
SC_WRAP, n_bits = 0 sR x All bits except for the deleted bits shall be copied to the result.
SC_WRAP, n_bits = 1 sD x The result number shall get the sign bit of the original number. The remaining bits shall be copied from the original number.
SC_WRAP, n_bits > 1 sD !sD x The result number shall get the sign bit of the original number. The saturated bits shall get the inverse value of the sign bit of the original number. The remaining bits shall be copied from the original number.
SC_WRAP_SM, n_bits = 0 lD x ^ sRo ^ sRn The sign bit of the result number shall get the value of the least significant deleted bit. The remaining bits shall be XOR-ed with the original and the new value of the sign bit of the result.
SC_WRAP_SM, n_bits = 1 sD x ^ sRo ^ sRn The result number shall get the sign bit of the original number. The remaining bits shall be XOR-ed with the original and the new value of the sign bit of the result.
SC_WRAP_SM, n_bits > 1 sD !sD x ^ lNo ^ !sD The result number shall get the sign bit of the original number. The saturated bits shall get the inverse value of the sign bit of the original number. The remaining bits shall be XOR-ed with the original value of the least significant saturated bit and the inverse value of the original sign bit.
Overflow handling for signed fixed-point numbers

Let’s see an example.

Saturation (SC_SAT)
1
2
3
4
5
6
7
8
9
  //this number has 4 integer bits
  sc_fixed<6,4> a = -7;
 
  cout << "         a in dec: " << a << ", a in bin: "<< a.to_bin() << endl;
 
  //this number has 2 integer bits
  sc_fixed<4,2, SC_RND, SC_SAT> b_sc_sat = a;
 
  cout << "SC_SAT - b in dec: " << b_sc_sat << ", b in bin:   "<< b_sc_sat.to_bin() << endl;

In this case sR = sD so it is a[5] = 1.
R = !sD so it is 0.

1
2
         a in dec: -7, a in bin: 0b1001.00
SC_SAT - b in dec: -2, b in bin:   0b10.00

You can run the full example on EDA Playground.

3.1.2.2. Overflow for Unsigned Fixed-Point Numbers

For unsigned numbers the flags are quite similar with the signed numbers with the only difference that sD, sR and lR no longer exists

Higher precision number x x x x x x x x x x
Lower precision number x x x x x x
Flags D D D lD R(N) R R R R R
Flags at bit level applied for overflow algorithms

The table below list all the available overflow modes and how the result is computed.

Overflow mode N R Details
SC_SAT 1 (overflow) 0 (underflow) The remaining bits shall be set to 1 (overflow) or 0 (underflow).
SC_SAT_ZERO 0 The remaining bits shall be set to 0.
SC_SAT_SYM 1 (overflow) 0 (underflow) The remaining bits shall be set to 1 (overflow) or 0 (underflow).
SC_WRAP, n_bits = 0 x All bits except for the deleted bits shall be copied to the result number.
SC_WRAP, n_bits > 0 1 x The saturated bits of the result number shall be set to 1. The remaining bits shall be copied to the result.
SC_WRAP_SM Not defined for unsigned numbers.
Overflow handling for unsigned fixed-point numbers

3.2 Fixed-Point Classes

Now that we have a clear understanding on how these fixed-point numbers are represented we can take a look at the classes used for modeling fixed-point numbers:

Let’s look over the differences between these classes.

The ones with “fast” are called limited-precision fixed-point types. They are faster than the other ones due to the fact that internal implementation takes use of the double primitive. These types can not be bigger than 53 bits.

The ones with “u” are unsigned.

The ones with “fixed” (past tense) are template classes and you can set all the parameters via variable declaration.
The other ones, with “fix” are regular C++ classes for which you can set the parameters via their constructors or via parameters context.
Let’s see an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//first argument is WL and second argument is IWL
sc_fixed<5,3> a_fixed = 1.75;
 
cout << "a_fixed: " << a_fixed << endl;
 
//for "fix" class you can specify via its constructor WL and IWL
sc_fix a_fix(5, 3);
a_fix = 1.75;
 
cout << "a_fix: " << a_fix << endl;
 
//however for "fix" classes the parameters can be set via a context
sc_fxtype_params params(5,4);
sc_fxtype_context context(params);
 
//because we do not specify in b_fix constructor anything
//the parameters are taken from the latest created context
sc_fix b_fix;
b_fix = 1.75;
 
//b_fix is 1.5 because we configured the context with WL = 5 and IWL = 4
//leaving only one bit for fractional value
cout << "b_fix: " << b_fix << endl;
 
//even if we set the context earlier we can use the constructor to
//hard code the arguments
sc_fix c_fix(5,3);
c_fix = 1.75;
 
cout << "c_fix: " << c_fix << endl;

This produce the following output:

1
2
3
4
a_fixed: 1.75
a_fix: 1.75
b_fix: 1.5
c_fix: 1.75

Pay attention to the comments in the example as I tried to explain there how WL and IWL are attributed to each variable.
You can run the example on your own on EDAPlayground.

Next Lesson: Learning SystemC: #002 Module – sc_module
Previous Lesson: Learning SystemC: #000 Learning Materials and Initial Setup



Summary
SystemC Tutorial: Data Types
Article Name
SystemC Tutorial: Data Types
Description
SystemC tutorial about the data types introduced by the SystemC library. You can learn about how and when to use classes for fixed-precision integer types, logic and arbitrary width vector types and fixed-point types. The lesson is full of code examples which you can run on your own on EDA Playground.
Author
Publisher Name
cfs-vision.com
Publisher Logo

Cristian Slav

3 Comments

Leave a Reply

Your email address will not be published.