In general, any valid operation that can be done on a native C/C++ integer data
type is supported (using operator overloading) for ap_[u]fixed
types. In addition to these overloaded operators,
some class specific operators and methods are included to ease bit-level
operations.
Binary Arithmetic Operators
Addition
ap_[u]fixed::RType ap_[u]fixed::operator + (ap_[u]fixed op)
Adds an arbitrary precision fixed-point with a given operand
op
.
The operands can be any of the following integer types:
- ap_[u]fixed
- ap_[u]int
- C/C++
The result type ap_[u]fixed::RType
depends on the type information of
the two operands.
ap_fixed<76, 63> Result;
ap_fixed<5, 2> Val1 = 1.125;
ap_fixed<75, 62> Val2 = 6721.35595703125;
Result = Val1 + Val2; //Yields 6722.480957
Because Val2
has the
larger bit-width on both integer part and fraction part, the result type
has the same bit-width and plus one to be able to store all possible
result values.
Specifying the data's width controls resources by using the power functions, as shown below. In similar cases, AMD recommends specifying the width of the stored result instead of specifying the width of fixed point operations.
ap_ufixed<16,6> x=5;
ap_ufixed<16,7>y=hl::rsqrt<16,6>(x+x);
Subtraction
ap_[u]fixed::RType ap_[u]fixed::operator - (ap_[u]fixed op)
Subtracts an arbitrary precision fixed-point with a given
operand op
.
The result type ap_[u]fixed::RType
depends on the
type information of the two operands.
ap_fixed<76, 63> Result;
ap_fixed<5, 2> Val1 = 1625.153;
ap_fixed<75, 62> Val2 = 6721.355992351;
Result = Val2 - Val1; // Yields 6720.23057
Because Val2
has the larger
bit-width on both integer part and fraction part, the result type has
the same bit-width and plus one to be able to store all possible result
values.
Multiplication
ap_[u]fixed::RType ap_[u]fixed::operator * (ap_[u]fixed op)
Multiplies an arbitrary precision fixed-point with a given
operand op
.
ap_fixed<80, 64> Result;
ap_fixed<5, 2> Val1 = 1625.153;
ap_fixed<75, 62> Val2 = 6721.355992351;
Result = Val1 * Val2; // Yields 7561.525452
This shows the multiplication of Val1
and Val2
. The
result type is the sum of their integer part bit-width and their
fraction part bit width.
Division
ap_[u]fixed::RType ap_[u]fixed::operator / (ap_[u]fixed op)
Divides an arbitrary precision fixed-point by a given operand
op
.
ap_fixed<84, 66> Result;
ap_fixed<5, 2> Val1 = 1625.153;
ap_fixed<75, 62> Val2 = 6721.355992351;
Val2 / Val1; // Yields 5974.538628
This shows the division of Val2
and Val1
. To
preserve enough precision:
- The integer bit-width of the result type is sum of the integer
bit-width of
Val2
and the fraction bit-width ofVal1
. - The fraction bit-width of the result type is equal to the fraction
bit-width of
Val2
.
Bitwise Logical Operators
Bitwise OR
ap_[u]fixed::RType ap_[u]fixed::operator | (ap_[u]fixed op)
Applies a bitwise operation on an arbitrary precision
fixed-point and a given operand op
.
ap_fixed<75, 62> Result;
ap_fixed<5, 2> Val1 = 1625.153;
ap_fixed<75, 62> Val2 = 6721.355992351;
Result = Val1 | Val2; // Yields 6271.480957
Bitwise AND
ap_[u]fixed::RType ap_[u]fixed::operator & (ap_[u]fixed op)
Applies a bitwise operation on an arbitrary precision fixed-point and a
given operand op
.
ap_fixed<75, 62> Result;
ap_fixed<5, 2> Val1 = 1625.153;
ap_fixed<75, 62> Val2 = 6721.355992351;
Result = Val1 & Val2; // Yields 1.00000
Bitwise XOR
ap_[u]fixed::RType ap_[u]fixed::operator ^ (ap_[u]fixed op)
Applies an xor
bitwise operation on an arbitrary
precision fixed-point and a given operand op
.
ap_fixed<75, 62> Result;
ap_fixed<5, 2> Val1 = 1625.153;
ap_fixed<75, 62> Val2 = 6721.355992351;
Result = Val1 ^ Val2; // Yields 6720.480957
Increment and Decrement Operators
Pre-Increment
ap_[u]fixed ap_[u]fixed::operator ++ ()
This operator function prefix increases an arbitrary
precision fixed-point variable by 1
.
ap_fixed<25, 8> Result;
ap_fixed<8, 5> Val1 = 5.125;
Result = ++Val1; // Yields 6.125000
Post-Increment
ap_[u]fixed ap_[u]fixed::operator ++ (int)
This operator function postfix:
- Increases an arbitrary precision fixed-point variable by
1
. - Returns the original val of this arbitrary
precision
fixed-point.
ap_fixed<25, 8> Result; ap_fixed<8, 5> Val1 = 5.125; Result = Val1++; // Yields 5.125000
Pre-Decrement
ap_[u]fixed ap_[u]fixed::operator -- ()
This operator function prefix decreases this arbitrary
precision fixed-point variable by 1
.
ap_fixed<25, 8> Result;
ap_fixed<8, 5> Val1 = 5.125;
Result = --Val1; // Yields 4.125000
Post-Decrement
ap_[u]fixed ap_[u]fixed::operator -- (int)
This operator function postfix:
- Decreases this arbitrary precision fixed-point variable by
1
. - Returns the original val of this arbitrary
precision
fixed-point.
ap_fixed<25, 8> Result; ap_fixed<8, 5> Val1 = 5.125; Result = Val1--; // Yields 5.125000
Unary Operators
Addition
ap_[u]fixed ap_[u]fixed::operator + ()
Returns a self copy of an arbitrary precision fixed-point variable.
ap_fixed<25, 8> Result;
ap_fixed<8, 5> Val1 = 5.125;
Result = +Val1; // Yields 5.125000
Subtraction
ap_[u]fixed::RType ap_[u]fixed::operator - ()
Returns a negative value of an arbitrary precision fixed-point variable.
ap_fixed<25, 8> Result;
ap_fixed<8, 5> Val1 = 5.125;
Result = -Val1; // Yields -5.125000
Equality Zero
bool ap_[u]fixed::operator ! ()
This operator function:
- Compares an arbitrary precision fixed-point variable with
0
, - Returns the
result.
bool Result; ap_fixed<8, 5> Val1 = 5.125; Result = !Val1; // Yields false
Bitwise Inverse
ap_[u]fixed::RType ap_[u]fixed::operator ~ ()
Returns a bitwise complement of an arbitrary precision fixed-point variable.
ap_fixed<25, 15> Result;
ap_fixed<8, 5> Val1 = 5.125;
Result = ~Val1; // Yields -5.25
Shift Operators
Unsigned Shift Left
ap_[u]fixed ap_[u]fixed::operator << (ap_uint<_W2> op)
This operator function:
- Shifts left by a given integer operand.
- Returns the result.
The operand can be a C/C++ integer type:
-
char
-
short
-
int
-
long
The return type of the shift left operation is the same width as the type being shifted.
ap_fixed<25, 15> Result;
ap_fixed<8, 5> Val = 5.375;
ap_uint<4> sh = 2;
Result = Val << sh; // Yields -10.5
The bit-width of the result is (W = 25
, I
= 15
). Because the shift left operation result type
is same as the type of Val
:
- The high order two bits of
Val
are shifted out. - The result is -10.5.
If a result of 21.5 is required, Val
must be cast to ap_fixed<10, 7>
first -- for example, ap_ufixed<10, 7>(Val)
.
Signed Shift Left
ap_[u]fixed ap_[u]fixed::operator << (ap_int<_W2> op)
This operator:
- Shifts left by a given integer operand.
- Returns the result.
The shift direction depends on whether the operand is positive or negative.
- If the operand is positive, a shift right is performed.
- If the operand is negative, a shift left (opposite direction) is performed.
The operand can be a C/C++ integer type:
-
char
-
short
-
int
-
long
The return type of the shift right operation is the same width as the type being shifted.
ap_fixed<25, 15, false> Result;
ap_uint<8, 5> Val = 5.375;
ap_int<4> Sh = 2;
Result = Val << sh; // Shift left, yields -10.25
Sh = -2;
Result = Val << sh; // Shift right, yields 1.25
Unsigned Shift Right
ap_[u]fixed ap_[u]fixed::operator >> (ap_uint<_W2> op)
This operator function:
- Shifts right by a given integer operand.
- Returns the result.
The operand can be a C/C++ integer type:
-
char
-
short
-
int
-
long
The return type of the shift right operation is the same width as the type being shifted.
ap_fixed<25, 15> Result;
ap_fixed<8, 5> Val = 5.375;
ap_uint<4> sh = 2;
Result = Val >> sh; // Yields 1.25
If it is necessary to preserve all significant bits, extend
fraction part bit-width of the Val
first, for example ap_fixed<10,
5>(Val)
.
Signed Shift Right
ap_[u]fixed ap_[u]fixed::operator >> (ap_int<_W2> op)
This operator:
- Shifts right by a given integer operand.
- Returns the result.
The shift direction depends on whether operand is positive or negative.
- If the operand is positive, a shift right performed.
- If operand is negative, a shift left (opposite direction) is performed.
The operand can be a C/C++ integer type (char
,
short
, int
, or
long
).
The return type of the shift right operation is the same width as type being shifted. For example:
ap_fixed<25, 15, false> Result;
ap_uint<8, 5> Val = 5.375;
ap_int<4> Sh = 2;
Result = Val >> sh; // Shift right, yields 1.25
Sh = -2;
Result = Val >> sh; // Shift left, yields -10.5
1.25
Relational Operators
Equality
bool ap_[u]fixed::operator == (ap_[u]fixed op)
This operator compares the arbitrary precision fixed-point variable with a given operand.
Returns true
if they are
equal and false
if they are not equal.
The type of operand op
can be ap_[u]fixed
, ap_int
or C/C++ integer types. For
example:
bool Result;
ap_ufixed<8, 5> Val1 = 1.25;
ap_fixed<9, 4> Val2 = 17.25;
ap_fixed<10, 5> Val3 = 3.25;
Result = Val1 == Val2; // Yields true
Result = Val1 == Val3; // Yields false
Inequality
bool ap_[u]fixed::operator != (ap_[u]fixed op)
This operator compares this arbitrary precision fixed-point variable with a given operand.
Returns true
if they are
not equal and false
if they are equal.
The type of operand op
can be:
- ap_[u]fixed
- ap_int
- C or C++ integer types
For example:
bool Result;
ap_ufixed<8, 5> Val1 = 1.25;
ap_fixed<9, 4> Val2 = 17.25;
ap_fixed<10, 5> Val3 = 3.25;
Result = Val1 != Val2; // Yields false
Result = Val1 != Val3; // Yields true
Greater than or equal to
bool ap_[u]fixed::operator >= (ap_[u]fixed op)
This operator compares a variable with a given operand.
Returns true
if they are
equal or if the variable is greater than the operator and false
otherwise.
The type of operand op
can be
ap_[u]fixed
, ap_int
or C/C++ integer types.
For example:
bool Result;
ap_ufixed<8, 5> Val1 = 1.25;
ap_fixed<9, 4> Val2 = 17.25;
ap_fixed<10, 5> Val3 = 3.25;
Result = Val1 >= Val2; // Yields true
Result = Val1 >= Val3; // Yields false
Less than or equal to
bool ap_[u]fixed::operator <= (ap_[u]fixed op)
This operator compares a variable with a given operand, and return
true
if it is equal to or less than the
operand and false
if not.
The type of operand op can be ap_[u]fixed
,
ap_int
or C/C++ integer types.
For example:
bool Result;
ap_ufixed<8, 5> Val1 = 1.25;
ap_fixed<9, 4> Val2 = 17.25;
ap_fixed<10, 5> Val3 = 3.25;
Result = Val1 <= Val2; // Yields true
Result = Val1 <= Val3; // Yields true
Greater than
bool ap_[u]fixed::operator > (ap_[u]fixed op)
This operator compares a variable with a given operand, and
return true
if it is greater than the
operand and false
if not.
The type of operand op
can be
ap_[u]fixed
,
ap_int
, or C/C++ integer types.
For example:
bool Result;
ap_ufixed<8, 5> Val1 = 1.25;
ap_fixed<9, 4> Val2 = 17.25;
ap_fixed<10, 5> Val3 = 3.25;
Result = Val1 > Val2; // Yields false
Result = Val1 > Val3; // Yields false
Less than
bool ap_[u]fixed::operator < (ap_[u]fixed op)
This operator compares a variable with a given operand, and
return true
if it is less than the
operand and false
if not.
The type of operand op can be ap_[u]fixed
, ap_int
,
or C/C++ integer types. For example:
bool Result;
ap_ufixed<8, 5> Val1 = 1.25;
ap_fixed<9, 4> Val2 = 17.25;
ap_fixed<10, 5> Val3 = 3.25;
Result = Val1 < Val2; // Yields false
Result = Val1 < Val3; // Yields true
Bit Operator
Bit-Select and Set
af_bit_ref ap_[u]fixed::operator [] (int bit)
This operator selects one bit from an arbitrary precision fixed-point value and returns it.
The returned value is a reference value that can set or
clear the corresponding bit in the ap_[u]fixed
variable. The bit argument must be an
integer value and it specifies the index of the bit to select. The least
significant bit has index 0
. The
highest permissible index is one less than the bit-width of this ap_[u]fixed
variable.
The result type is af_bit_ref
with a value of either 0
or 1
. For example:
ap_int<8, 5> Value = 1.375;
Value[3]; // Yields 1
Value[4]; // Yields 0
Value[2] = 1; // Yields 1.875
Value[3] = 0; // Yields 0.875
Bit Range
af_range_ref af_(u)fixed::range (unsigned Hi, unsigned Lo)
af_range_ref af_(u)fixed::operator [] (unsigned Hi, unsigned Lo)
This operation is similar to bit-select operator [] except that it operates on a range of bits instead of a single bit.
It selects a group of bits from the arbitrary precision fixed-point
variable. The Hi
argument provides the upper
range of bits to be selected. The Lo
argument
provides the lowest bit to be selected. If Lo
is
larger than Hi
the bits selected are returned in
the reverse order.
The return type af_range_ref
represents a reference
in the range of the ap_[u]fixed
variable
specified by Hi
and Lo
.
For example:
ap_uint<4> Result = 0;
ap_ufixed<4, 2> Value = 1.25;
ap_uint<8> Repl = 0xAA;
Result = Value.range(3, 0); // Yields: 0x5
Value(3, 0) = Repl(3, 0); // Yields: -1.5
// when Lo > Hi, return the reverse bits string
Result = Value.range(0, 3); // Yields: 0xA
Range Select
af_range_ref af_(u)fixed::range ()
af_range_ref af_(u)fixed::operator []
This operation is the special case of the range select
operator []
. It selects all bits from
this arbitrary precision fixed-point value in the normal order.
The return type af_range_ref
represents a
reference to the range specified by Hi = W - 1 and Lo = 0. For
example:
ap_uint<4> Result = 0;
ap_ufixed<4, 2> Value = 1.25;
ap_uint<8> Repl = 0xAA;
Result = Value.range(); // Yields: 0x5
Value() = Repl(3, 0); // Yields: -1.5
Length
int ap_[u]fixed::length ()
This function returns an integer value that provides the number of bits in an arbitrary precision fixed-point value. It can be used with a type or a value. For example:
ap_ufixed<128, 64> My128APFixed;
int bitwidth = My128APFixed.length(); // Yields 128
Explicit Conversion Methods
Fixed to Double
double ap_[u]fixed::to_double ()
This member function returns this fixed-point value in form of IEEE double precision format. For example:
ap_ufixed<256, 77> MyAPFixed = 333.789;
double Result;
Result = MyAPFixed.to_double(); // Yields 333.789
Fixed to Float
float ap_[u]fixed::to_float()
This member function returns this fixed-point value in form of IEEE float precision format. For example:
ap_ufixed<256, 77> MyAPFixed = 333.789;
float Result;
Result = MyAPFixed.to_float(); // Yields 333.789
Fixed to Half-Precision Floating Point
half ap_[u]fixed::to_half()
This member function return this fixed-point value in form of HLS half-precision (16-bit) float precision format. For example:
ap_ufixed<256, 77> MyAPFixed = 333.789;
half Result;
Result = MyAPFixed.to_half(); // Yields 333.789
Fixed to ap_int
ap_int ap_[u]fixed::to_ap_int ()
This member function explicitly converts this fixed-point
value to ap_int
that captures all
integer bits (fraction bits are truncated). For example:
ap_ufixed<256, 77> MyAPFixed = 333.789;
ap_uint<77> Result;
Result = MyAPFixed.to_ap_int(); //Yields 333
Fixed to Integer
int ap_[u]fixed::to_int ()
unsigned ap_[u]fixed::to_uint ()
ap_slong ap_[u]fixed::to_int64 ()
ap_ulong ap_[u]fixed::to_uint64 ()
This member function explicitly converts this fixed-point value to C built-in integer types. For example:
ap_ufixed<256, 77> MyAPFixed = 333.789;
unsigned int Result;
Result = MyAPFixed.to_uint(); //Yields 333
unsigned long long Result;
Result = MyAPFixed.to_uint64(); //Yields 333
ap_[u]fixed
to other data types.Compile Time Access to Data Type Attributes
The ap_[u]fixed<>
types are provided with several static members that allow the size and
configuration of data types to be determined at compile time. The data
type is provided with the static const
members: width
, iwidth
, qmode
and omode
:
static const int width = _AP_W;
static const int iwidth = _AP_I;
static const ap_q_mode qmode = _AP_Q;
static const ap_o_mode omode = _AP_O;
You can use these data members to extract the following information from any
existing ap_[u]fixed<>
data type:
-
width
- The width of the data type.
-
iwidth
- The width of the integer part of the data type.
-
qmode
- The quantization mode of the data type.
-
omode
- The overflow mode of the data type.
For example, you can use these data members to extract the
data width of an existing ap_[u]fixed<>
data type to create another ap_[u]fixed<>
data type at
compile time.
The following example shows how the size of variable
Res
is automatically defined as 1-bit greater
than variables Val1
and Val2
with the same quantization
modes:
// Definition of basic data type
#define INPUT_DATA_WIDTH 12
#define IN_INTG_WIDTH 6
#define IN_QMODE AP_RND_ZERO
#define IN_OMODE AP_WRAP
typedef ap_fixed<INPUT_DATA_WIDTH, IN_INTG_WIDTH, IN_QMODE, IN_OMODE> data_t;
// Definition of variables
data_t Val1, Val2;
// Res is automatically sized at run-time to be 1-bit greater than INPUT_DATA_WIDTH
// The bit growth in Res will be in the integer bits
ap_int<data_t::width+1, data_t::iwidth+1, data_t::qmode, data_t::omode> Res = Val1 +
Val2;
This ensures that Vitis HLS correctly
models the bit-growth caused by the addition even if you update the
value of INPUT_DATA_WIDTH, IN_INTG_WIDTH, or the quantization modes for
data_t
.