Ac Datatypes Reference
Ac Datatypes Reference
The software described herein is copyright 2002-2011 Calypto Design Systems, Inc. All rights
reserved. The software described herein, which contains confidential information and trade secrets, is
property of Calypto Design Systems, Inc.
This manual is copyright 2005-2011 Calypto Design Systems, Inc. Printed in U.S.A. All rights reserved.
This document may not, in whole or in part, be copied, photocopied, reproduced, translated, transmitted,
or reduced to any electronic medium or machine-readable form without prior written consent from
Calypto Design Systems, Inc.
This manual and its contents are confidential information of Calypto Design Systems, Inc., and should be
treated as confidential information by the user under the terms of the nondisclosure agreement and
software license agreement, as applicable, between Calypto Design Systems, Inc. and user.
Table of Contents
Chapter 1
Overview of Algorithmic C Datatypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Definition and Implementation Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
7
8
8
Chapter 2
Arbitrary-Length Bit-Accurate Integer and Fixed-Point Datatypes . . . . . . . . . . . . . . . . .
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Quantization and Overflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Operators and Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Binary Arithmetic and Logical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Relational Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Shift Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Unary Operators: +, -, ~ and !. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Increment and Decrement Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Conversion Operators to C Integer Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Explicit Conversion Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Bit Select Operator: []. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Slice Read Method: slc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Slice Write Method: set_slc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
The set_val Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
IO Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Methods to performing IO have not been defined/implemented for the current release. . .
Mixing ac_int and ac_fixed with Other Datatypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Advanced Utility Functions, Typedefs, etc. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Accessing Parameter Information. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Using ac::init_array for Initializing Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Static Computation of log2 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Return Type for Unary and Binary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
11
15
17
18
19
22
22
24
24
25
26
27
28
28
29
29
30
30
30
30
30
31
32
33
Chapter 3
Complex Datatype. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Recommendations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Advanced utility functions, typedefs, etc. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Accessing the Underlying (Element) Type. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Using ac::init_array for Initializing Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Return Type for Unary and Binary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
37
39
39
39
40
40
40
Table of Contents
Chapter 4
Datatype Migration Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
General Compilation Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
SystemC Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
SystemC to AC Differences in Methods/Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Support for SystemC sc_trace Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Simulation Differences with SystemC types and with C integers . . . . . . . . . . . . . . . . . . . . .
Limited Precision vs. Arbitrary Precision. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Implementation Deficiencies of sc_int/sc_uint. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Differences Due to Definition. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Mixing Datatypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
41
41
41
41
43
44
44
45
45
46
49
Chapter 5
Frequently Asked Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Operators ~, &, |, ^, -, ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why does ~ and - for an unsigned return signed? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why are operators &, |, ^ arithmetically defined?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why does operator ! return different results for ac_fixed and sc_fixed? . . . . . . . . . . . . . .
Conversions to double and Operators with double . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why is the implicit conversion from ac_fixed to double not defined?. . . . . . . . . . . . . . . .
Why are most binary operations not defined for mixed ac_fixed and double arguments?.
Constructors from strings. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why are constructors from strings not defined? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Shifting Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why does shifting gives me unexpected results? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Division Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why does division return different results for ac_fixed and sc_fixed? . . . . . . . . . . . . . . .
Compilation Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why arent older compilers supported? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why doesnt the slc method compile in some cases? . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why do I get compiler errors related to template parameters?. . . . . . . . . . . . . . . . . . . . . .
Platform Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
What platforms are supported? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Purify Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why do I get UMRs for ac_int/ac_fixed in purify? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
User Defined Asserts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Can I control what happens when an assert is triggered? . . . . . . . . . . . . . . . . . . . . . . . . . .
51
51
51
51
52
52
52
52
53
53
53
53
53
53
53
53
54
54
54
54
54
54
55
55
List of Tables
Table 2-1. Numerical Ranges of ac_int and ac_fixed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Table 2-2. Examples for ac_int and ac_fixed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Table 2-3. Operators defined for ac_int and ac_fixed. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Table 2-4. Methods defined for ac_int and ac_fixed. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Table 2-5. Constructors defined for ac_int and ac_fixed. . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Table 2-6. Quantization modes for ac_fixed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Table 2-7. Overflow modes for ac_fixed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Table 2-8. Return Types for ac_int Binary Arithmetic and Bitwise Logical Operations . . . 20
Table 2-9. Return Types for ac_fixed Binary Arithmetic and Bitwise Logical Operations . 21
Table 2-10. Mixed Expressions: i_s7 is ac_int<7,true>, fx_s20_4 is ac_fixed<20,4,false> and
c_s8 is signed char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Table 2-11. Unary Operators for ac_int<W,S> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Table 2-12. Unary Operators for ac_fixed<W,I,S,Q,O> . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Table 2-13. Pre- and Post-Increment/Decrement Operators for ac_int . . . . . . . . . . . . . . . . 24
Table 2-14. Pre- and Post-Increment/Decrement Operators for ac_fixed<W,I,S,Q,O> where .
25
Table 2-15. Conversion to C Integer Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Table 2-16. Explicit Conversion Methods for ac_int/ac_fixed . . . . . . . . . . . . . . . . . . . . . . . 27
Table 2-17. Special values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Table 2-18. Basic Parameters. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Table 2-19. Required Include Files for ac::init_array Function . . . . . . . . . . . . . . . . . . . . . . 31
Table 2-20. Syntax for log2 functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Table 2-21. Return types for operator on T. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Table 2-22. Return type for (T1(op1) op T2(op2)) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Table 3-1. Operators defined for ac_complex. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Table 3-2. Methods defined for ac_complex<T>. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Table 4-1. Relation Between SystemC Datatypes and AC Datatypes . . . . . . . . . . . . . . . . . 42
Table 4-2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Table 4-3. Quantization Modes for ac_int and Their Relation to sc_fixed/sc_ufixed . . . . . 42
Table 4-4. Overflow Modes for ac_fixed and Their Relation to sc_fixed/sc_ufixed . . . . . . 43
Table 4-5. Migration of SystemC Methods to ac_int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
List of Tables
Chapter 1
Overview of Algorithmic C Datatypes
Introduction
The arbitrary-length bit-accurate integer and fixed-point datatypes provide an easy way to
model static bit-precision with minimal runtime overhead. The datatypes were developed in
order to provide a basis for writing bit-accurate algorithms to be synthesized into hardware. The
Algorithmic C data types are used in Catapult C Synthesis, a tool that generates optimized RTL
from algorithms written as sequential ANSI-standard C/C++ specifications. Operators and
methods on both the integer and fixed-point types are clearly and consistently defined so that
they have well defined simulation and synthesis semantics.
The precision of the integer type ac_int<W,S> is determined by template parameters W (integer
that gives bit-width) and S (a boolean that determines whether the integer is signed or
unsigned). The fixed-point type ac_fixed<W,I,S,Q,O> has five template parameters which
determine its bit-width, the location of the fixed-point, whether it is signed or unsigned and the
quantization and overflow modes (see Quantization and Overflow on page 15) that are
applied when constructing or assigning to object of its type.
The advantages of the Algorithmic C datatypes over the existing integer and fixed-point
datatypes are the following:
Arbitrary-Length: This allows a clean definition of the semantics for all operators that is
not tied to an implementation limit. It is also important for writing general IP algorithms
that dont have artificial (and often hard to quantify and document) limits for precision.
Precise Definition of Semantics: Special attention has been paid to define and verify the
simulation semantics and to make sure that the semantics are appropriate for synthesis.
No simulation behavior has been left to compiler dependent behavior. Also, asserts have
been introduced to catch invalid code during simulation. See also User Defined
Asserts on page 55.
Correctness: The simulation and synthesis semantics have been verified for many size
combinations using a combination of simulation and equivalence checking.
Compilation Speed and Smaller Executable: Code written using ac_int datatypes
compiles 5x faster even with the compiler optimizations turned on (required to get fast
simulation). It also produces smaller binary executables.
Static Bit Widths: all operations and methods return an object with a bit width that is
statically determinable from the bit widths of the inputs and signedness (signed vs.
unsigned) of the inputs. Keeping bit-widths static is essential for fast simulation, as it
means that memory allocation is completely avoided. It is also essential for synthesis.
For example the left shift operation of an ac_int returns an ac_int of the same type
(width and signedness) as the type of first operand. In contrast, the left shift for sc_bigint
or sc_biguint returns an object with precision that depends on the shift value and has no
practical bound on its bit width.
Mixed ac_int, ac_fixed and C integer type Binary Functions: all binary operators are
defined for mixed ac_int, ac_fixed and native C integers for consistency. For example
the expression 1 + a where a is an ac_int<36,true> will compute ac_int<32,true> 1 +
a rather than 1 + (int) a. This is done to ensure that expressions are carried out
without unintentional loss of precision and to make sure that compiler errors due to
ambiguities are avoided.
The types have a public interface. The base class implementation of these types are private.
They are part of the implementation and may be changed. Also any function or class under
namespace ac_private should not be used as it may be subject to change.
Usage
In order to use the Algorithmic C data types, either the header file ac_int.h or ac_fixed.h needs
to be included in the source. All the definitions are in these files and there are no object files that
need to be linked in. Enabling compiler optimizations (for example -O3 in GCC) is critical to
8
the fastest runtime. Explicit conversion functions to SystemC integer and fixed-point datatypes
are provided in the header file ac_sc.h. Chapter 4, Datatype Migration Guide, presents
information about how to convert algorithms written with SystemC datatypes to Algorithmic C
datatypes.
10
Chapter 2
Arbitrary-Length Bit-Accurate Integer and
Fixed-Point Datatypes
Introduction
The arbitrary-length bit-accurate integer and fixed-point datatypes provide an easy way to
model static bit-precision with minimal runtime overhead. Operators and methods on both the
integer and fixed-point types are clearly and consistently defined so that they have well defined
simulation and synthesis semantics.
The types are named ac_int and ac_fixed and their numerical ranges are given by their template
parameters as shown in Table 2-1. For both types, the boolean template parameter determines
whether the type is constrained to be unsigned or signed. The template parameter W specifies
the number of bits for the integer or fixed point number and must be a positive integer. For
ac_int the value of the integer number bW-1...b1b0 is interpreted as an unsigned integer or a
signed (twos complement) number.The advantage of having the signedness specified by a
template parameter rather than having two distinct types is that it makes it possible to write
generic functions where signedness is just a parameter.
Table 2-1. Numerical Ranges of ac_int and ac_fixed
Type
ac_int<W, false>
ac_int<W, true>
Description
unsigned integer
signed integer
ac_fixed<W, I, false>
unsigned fixed-point
ac_fixed<W, I, true>
signed fixed-point
Numerical Range
0 to
-2W-1
2W-
to
2W-1-
Quantum
1
0 to (1 - 2
1
-W) 2I
2I-W
2I-W
For ac_fixed, the second parameter I of an ac_fixed is an integer that determines the location of
the fixed-point relative to the MSB. The value of the fixed-point number bW-1...b1b0 is given by
(.bW-1...b1b0) 2I or equivalently (bW-1...b1b0) 2I-W where bW-1...b1b0 is interpreted as an
unsigned integer or a signed (twos complement) number.
Table 2-2 shows examples for various integer and fixed-point types with their respective
numerical ranges and quantum values. The quantum is the smallest difference between two
numbers that are represented. Note that an ac_fixed<W,W,S> (that is I==W) has the same
numerical range as an ac_int<W,S> where S is a boolean value that determines whether the
11
Numerical Range
Quantum
ac_int<1, false>
0 to1
ac_int<1, true>
-1 to 0
ac_int<4, false>
0 to 15
ac_int<4, true>
-8 to 7
ac_fixed<4, 4, false>
0 to 15
ac_fixed<4, 4, true>
-8 to 7
ac_fixed<4, 6, false>
0 to 60
ac_fixed<4, 6, true>
-32 to 28
ac_fixed<4, 0, false>
0 to 15/16
1/16
ac_fixed<4, 0, true>
-0.5 to 7/16
1/16
ac_fixed<4,-1, false>
0 to 15/32
1/32
ac_fixed<4,-1, true>
-0.25 to 7/32
1/32
It is important to remember when dealing with either an ac_fixed or an ac_int that in order for
both +1 and -1 to be in the numerical range, I and W have to be at least 2. For example,
ac_fixed<6,1,true> has a range from -1 to +0.96875 (it does not include +1) while
ac_fixed<6,2,true> has a range -2 to +1.9375 (includes +1).
The fixed-point datatype ac_fixed has two additional template parameters that are optional that
define the overflow mode (e.g. saturation) and the quantization mode (e.g. rounding):
ac_fixed<int W, int I, bool S, ac_q_mode Q, ac_o_mode O>
Quantization and overflow occur when assigning (=, +=, etc.) or constructing (including
casting) where the target does not represent the source value without loss of precision (this will
be covered more precisely in Quantization and Overflow on page 15). In all the examples of
Table 2-2 the default quantization and overflow modes AC_TRN and AC_WRAP are implied.
The default modes simply throw away bits to the right of LSB and to the left of the MSB which
is also the behavior of ac_int:
ac_fixed<1,1,true>
ac_int<1,true> x
ac_fixed<4,4,true>
ac_int<4,true>
ac_fixed<4,4,true>
ac_int<4,true>
ac_fixed<4,4,true>
12
x =
=
x =
x =
x =
x =
x =
Table 2-3 shows the operators defined for both ac_int and ac_fixed
Table 2-3. Operators defined for ac_int and ac_fixed.
Operators
ac_int
ac_fixed
Arithmetic result. First or second
arg may be ac_int or C INT
/ truncates towards 0.
% NOT DEFINED
>>, <<
bidirectional
bidirectional
return type is type of first operand return type is type of first operand
Second arg is ac_int or C INT
Second arg is ac_int or C INT
assignment
Unary +, -, ~
Arithmetic
Arithmetic
Pre/post incr/dec by 1
!x
Equiv to x == 0
Equiv to x == 0
(long long)
NOT DEFINED
x[i]
returns ac_int::ac_bitref
index: ac_int, unsigned, int
asserts for index out of bound
returns ac_fixed::ac_bitref
index: ac_int, unsigned, int
asserts for index out of bounds
Note that for convenience the conversion operators to (long long) and signed ac_int and
(unsigned long long) for unsigned ac_int are defined for W <= 64. Among other things, this
allows for the use of an ac_int as an index to a C array without any explicit conversion call.
Table 2-4 shows the methods defined for ac_int and ac_fixed types. The slc and set_slc methods
are templatized to get or set a slice respectively. For slc, the width needs to be explicitly
provided as a template argument. When using the slc method in a templatized function place the
keyword template before it as some compilers may error out during parsing. For example:
template<int N> // not important whether or not N is used
int f(int x) {
ac_int<32,true> t = x;
ac_int<6,true> r = t.template slc<6>(4); // t.slc<6>(4) could error out
13
The set_slc method does not need to have a width specified as a template argument since the
width is inferred from the width of the argument x. Many of the other methods are conversion
functions. The length method returns the width of the type. The set_val method sets the ac_int
or ac_fixed to a value that depends on the template parameter.
Table 2-4. Methods defined for ac_int and ac_fixed.
Methods
ac_int<W,S>
ac_fixed<W,I,S,Q,O>
slc<W2>(int_type i)
set_slc(
int_type i,
ac_int<W2,S2> x
)
Bits of x are copied at slice with LSB index i. That is, bits (W2-1+i
downto i) are set with bits of x.
Parameter i needs to be non-negative and could of any of the
following types: ac_int, unsigned, int
to_ac_int()
NOT DEFINED
to_int(), to_uint(),
to_long(), to_ulong(),
to_int64(), to_uint64()
to_double()
Conversion to double
Conversion to double
to_string(
convert to std::string depending on parameters base_rep
ac_base_mode base_rep, {AC_HEX, AC_DEC, AC_OCT, AC_BIN} and sign_mag
bool sign_mag = false
)
length()
14
Table 2-5 shows the constructors that are defined for ac_int and ac_fixed. When constructing an
ac_fixed, its quantization/overflow mode is taken into account. Initializing an ac_int or ac_fixed
from floating-point (float or double) is not as runtime efficient as initializing from integers.
Table 2-5. Constructors defined for ac_int and ac_fixed.
Constructor argument
ac_int
ac_fixed
None: Default
quantization/overflow
quantization/overflow
signed/unsigned char
(8-bit signed/unsigned)
quantization/overflow
signed/unsigned short
(16-bit signed/unsigned)
quantization/overflow
quantization/overflow
quantization/overflow
double
Not as efficient
ac_int
quantization/overflow
Not as efficient
quantization/overflow
ac_fixed
NOT DEFINED
Use to_ac_int() instead
quantization/overflow
Quantization: bits to the right of the LSB of the target type are being lost. The value may
be adjusted by the following two strategies:
Rounding: choose the closest quantization level. When the value is exactly half way
two quantization levels, which one is chosen depends on the specific rounding mode
as shown in Table 2-6.
Truncation: choose the closest quantization level such that result (quantized value) is
less than or equal the source value (truncation toward minus infinity) or such that the
absolute value of the result is less than or equal the source value (truncation towards
zero).
15
Note that quantization may trigger an overflow so it is always applied before overflow
handling.
Overflow: value after quantization is outside the range of the target as defined in
Table 2-1 on page 11, except when the overflow mode is AC_SAT_SYM where the
range is symmetric: [-2W-1+1, 2W-1-1] in which case the most negative number -2W-1
triggers an overflow.
The modes are specified by the 4th and 5th template argument to ac_fixed:
ac_fixed<int W, int I, bool S, ac_q_mode Q, ac_o_mode O>
that are of enumeration type ac_q_mode and ac_o_mode respectively. The enumeration values
for ac_q_mode are shown in Table 2-6. The enumeration values for ac_o_modes are shown in
Table 2-7 on page 17. The quantization and overflow mode default to AC_TRN and
AC_WRAP:
ac_fixed<8,4,true> x; // equiv to ac_fixed<8,4,true,AC_TRN,AC_WRAP)
Behavior
n is integer, q is 2I-W
AC_TRN (default)
(trunc towards )
AC_TRN_ZERO
(trunc towards 0)
nq
n0
)
(n+1)q
)(
nq
(n+1)q
n<0
n0
)(
)(
nq
(n+1)q
n<0
(n+1)q
n0
)(
)(
nq
nq
(n+1)q
AC_RND_MIN_INF
(round towards )
16
nq
(n+1)q
nq
AC_RND_CONV
(round towards even
q multiples)
(n+1)q
n<0
AC_RND
(round towards + )
AC_RND_INF
(rounds towards )
nq
AC_RND_ZERO
(round towards 0)
Simulation/Synthesis cost
(n+1)q
)(
(2n-1)q
nq
(n+1)q
)(
)(
2nq
(2n+1)q
For unsigned ac_fixed types, AC_TRN and AC_TRN_ZERO are equivalent, AC_RND and
AC_RND_INF are equivalent, and AC_RND_ZERO and AC_RND_MIN_INF are equivalent.
The AC_RND_CONV is a convergent rounding that rounds towards even multiples of the
quantization. The quantization modes that have two columns (different directions for negative
and positive numbers) are symmetric around 0 and are more costly as ac_fixed is represented in
twos complement arithmetic. On the other hand signed-magnitude representations (for example
floating point numbers) are more costly for asymmetric cases.
Quantization and overflow occur when assigning or constructing.
ac_fixed<8,1,true,Q,O> x = -0.1; // quantization, no overflow
ac_fixed<8,1,false,Q,O> y = x; // overflow (underflow) as y is unsigned
ac_fixed<4,1,true,Q,O> z= x; // quantization (dropping bits on the right)
(ac_fixed<4,1,true,Q,O>) x; // casting: same as above
ac_fixed<8,4,true,Q,O> a = ...;
ac_fixed<8,4,true,Q,O> b =
The behavior of the overflow modes are shown in Table 2-7. The default is AC_WRAP and
requires no special handling (same behavior as with an ac_int). The AC_SAT mode saturates to
the MIN or MAX limits of the range (as specified in Table 2-1 on page 11) of the target type
(different for signed or unsigned targets). The AC_SAT_ZERO sets the value to zero when an
overflow is detected. The AC_SAT_SYM makes only sense for signed targets. It saturates to
+MAX or -MAX (note that -MAX = MIN+q). It not only saturates on overflow, but also when
the value is MIN (it excludes the most negative number that would make the range asymmetric).
Note however, that declaring an ac_fixed with AC_SAT_SYM does not guarantee that it stays
symmetric as changing individual bits or slices in an ac_fixed does not trigger quantization or
overflow handling.
Table 2-7. Overflow modes for ac_fixed
Mode
Behavior
all references are to target type
MIN, MAX are limits as in Table 2-1
Simulation/Synthesis
cost
AC_WRAP (default)
No cost
AC_SAT
AC_SAT_ZERO
Set to 0 on overflow
AC_SAT_SYM
Usage
In order to use the ac_int datatype the following file include should be used:
17
The ac_int type is implemented with two template parameters to define its bitwidth and to
indicate whether it is signed or unsigned:
ac_int<7, true> x;
// x is 7 bits signed
ac_int<19, false> y; // y is 19 bits unsigned
In order to use the ac_fixed datatype the following file include should be used:
#include <ac_fixed.h>
The ac_fixed.h includes ac_int.h so it is not necessary to include both ac_int.h and ac_fixed.h.
The ac_fixed type is implemented with 5 template parameters that control the behavior of the
fixed point type:
ac_fixed<int W, int I, bool S, ac_q_mode Q, ac_q_mode O>
where W is the width of the fixed point type, I is the number of integer bits, S is a boolean flag
that determines whether the fixed-point is signed or unsigned, and Q and O are the quantization
and overflow modes respectively (as shown in Table 2-4 on page 14 and Table 2-5 on page 15).
The value of the fixed point is given by:
( 0.b W 1 b 1 b 0 )2
For example:
ac_fixed<4,4,true> x; // bbbb signed, AC_TRN, AC_WRAP
ac_fixed<4,0,false> x; // .bbbb unsigned AC_TRN, AC_WRAP
ac_fixed<4,7,false> x; // bbbb000, unsigned, AC_TRN, AC_WRAP
ac_fixed<4,-3,false> x; // .bbbb * pow(2, -3), unsigned, AC_TRN, AC_WRAP
18
Relational: the result is a boolean value (true/false): >, <, >=, <=, ==, !=. Mixing of
ac_int, ac_fixed, native C integers and double is allowed.
Shift operator and shift assign operators: <<, >>, =<<, =>>. The second argument is
an ac_int or a native C integer.
Slicing Method slc<W>(int i) and set_slc(int i, const ac_int<W,S> &s) to read and
modify a slice in an ac_int or ac_fixed. A slice of an ac_fixed is an ac_int.
I/O methods.
The concatenation operator is not defined for ac_int. Bit reversal may be defined in future
releases.
19
returns the same value (and in this case the same type) as
a | (b | c)
Table 2-8 shows the list of binary (two operand) arithmetic and logical operators for ac_int and
the return type based on the signedness and bit width of the two input operands. All operators
shown in the table are defined arithmetically. The operator & could have been defined to return
a more constrained type, SR = S1 & S2 and WR = abs(min(S1 ? -W1:W1, S2 ? -W2:W2)). For
instance, the bitwise AND of a uin1 and an int5 would return a uint1. However, for simplicity it
has been defined to be consistent with the other two logical operators. Regardless of how the
operators are defined, synthesis will reduce it to the smallest size that preserves the arithmetic
value of the result.
Table 2-8. Return Types for ac_int Binary Arithmetic and Bitwise Logical
Operations
Operator
Bit Width: WR
S1 | S2
max(W1+!S1&S2,W2+!S2&S1)+1
true
max(W1+!S1&S2,W2+!S2&S1)+1
S1 | S2
W1+W2
S1 | S2
W1+S2
S1
min(W1, W2+!S2&S1)
&
S1 | S2
max(W1+!S1&S2,W2+!S2&S1)
S1 | S2
max(W1+!S1&S2,W2+!S2&S1)
S1 | S2
max(W1+!S1&S2,W2+!S2&S1)
Table 2-9 shows the binary (two operand) arithmetic and logical operators for ac_fixed and the
return type based on the signedness, bit width and integer bit width of the operands. All
operands are defined consistently with ac_int: if both ac_fixed operands are pure integers (W
and I are the same) then the result is an ac_fixed that is also a pure integer with the same
bitwidth and value as the result of the equivalent ac_int operation. For example: a/b where a is
20
Bit Width: WR
S1 | S2
IR+max(W1-I1,W2-I2)
max(I1+!S1&S2,I2+!S2&S1)+1
true
IR+max(W1-I1,W2-I2)
max(I1+!S1&S2,I2+!S2&S1)+1
S1 | S2
W1+W2
I1+I2
S1 | S2
W1+max(W2-I2,0)+S2
I1+(W2-I2)+S2
&
S1 | S2
IR+max(W1-I1,W2-I2)
max(I1+!S1&S2,I2+!S2&S1)
S1 | S2
IR+max(W1-I1,W2-I2)
max(I1+!S1&S2,I2+!S2&S1)
S1 | S2
IR+max(W1-I1,W2-I2)
max(I1+!S1&S2,I2+!S2&S1)
The assignment operators +=, -=, *=, /=, %=, &=, |= and ^= have the usual semantics:
A1 @= A2
From a simulation speed point of view, the assignment version (for instance *=) is more
efficient since the target precision can be taken into account to reduce the computation required.
Otherwise, if one of the operands is an ac_int in a binary operation or the first operand is
an ac_int in an assign operation, the other operand (native c integer) gets represented as
ac_int<width(c_int), signedness(c_int)>
21
The rules above guarantee that precision is not lost. Note that floating point types are not
supported for the operators in this section as the output precision can not be determined by the C
compiler. Table 2-10 shows a few examples of mixed operations.
Table 2-10. Mixed Expressions: i_s7 is ac_int<7,true>, fx_s20_4 is
ac_fixed<20,4,false> and c_s8 is signed char
Expression
Equivalent Expression
1 + i_s7
(ac_int<32,true>) 1 + i_s7
(bool) 1 + i_s7
(ac_int<1,false>) 1 + i_s7
i_7s + fx_u20_4
fx_u20_4 += c_s8
c_s8 += fx_u20_4
Relational Operators
Relational operators !=, ==, >, >=, < and <= are also binary operations and have some of the
same characteristics described for arithmetic and logical operations: the operations are done
arithmetically and mixed ac_int, ac_fixed and native C integer operators are defined. The return
type is bool.
The relational operator for ac_int and ac_fixed with the C floating type double is also defined
for convenience, though for simulation performance reasons it is best to store the double
constant in an appropriate ac_int or ac_fixed variable outside computation loops so that the
overhead of converting the double to ac_fixed or ac_int is minimized.
Shift Operators
Left shift << and right shift >> operators return a value of type of the first operand. The left
shift operator shifts in zeros. The right shift operator shifts in the MSB bit for ac_int/ac_fixed of
type signed, 0 for ac_int/ac_fixed integers of type unsigned.
If the shift value is negative the first operand is shifted in the opposite direction by the absolute
value of the shift value (this is also the semantic of sc_fixed/sc_ufixed shifts). Shift values that
are greater than W (bitwidth of first operand) are equivalent to shifting by W.
The second operand is an ac_int integer of bit width less or equal to 32 bits or a signed or
unsigned int.
22
The shift assign operators <<= and >>= have the usual semantics:
A1 <<= A2; // equiv to A1 = A1 << A2
A1 >>= A2; // equiv to A1 = A1 >> A2
Because the return type is the type of the first operand, the shift assign operators do not carry
out any quantization or overflow.
The shift assign operators <<= and >>= are also defined for mixed ac_int (first or second
operand), ac_fixed (first operand) and native C integer (second operand).
The return type of the left shift for sc_bigint/sc_biguint or sc_fixed/sc_ufixed does not
lose bits making the return type of the left shift data dependent (dependent on the shift
value). Shift assigns for sc_fixed/sc_ufixed may result in quantization or overflow
(depending on the mode of the first operand).
Shifting occurs on either 32-bit (int, unsigned int) or 64-bit (long long, unsigned long
long) integrals. If the first operand is an integral type that has less than 32 bits (bool,
(un)signed char, short) it is first promoted to int. The return type is the type of the first
argument after integer promotion (if applicable).
Shift values are constrained according to the length of the type of the promoted first
operand.
The behavior for shift values outside the allowed ranges is not specified by the C++ ISO
standard.
23
Return Type
ac_int<W, S>
ac_int<W+1, true>
ac_int<W+!S, true>
bool
Table 2-12 lists the unary operators for ac_fixed and their return types.
Table 2-12. Unary Operators for ac_fixed<W,I,S,Q,O>
Operator
Return Type
ac_fixed<W, I, S>
bool
24
Operator
Equivalent Behavior
x++
T_x t = x; x += 1; return t;
++x
x += 1; return reference to x;
Equivalent Behavior
x--
T_x t = x; x -= 1; return t;
--x
x -= 1; return reference to x;
Pre/Post increment/decrement for ac_fixed have the semantics as shown in Table 2-14 (T_x is
the type of variable x) where q is the quantum value of the representation (the smallest
difference between two values for T_x). This definition is consistent with the definition of
ac_int where q is 1.
Table 2-14. Pre- and Post-Increment/Decrement Operators for
IW
ac_fixed<W,I,S,Q,O> where q = 2
.
Operator
Equivalent Behavior
x++
T_x t = x; x += q; return t;
++x
x += q; return reference to x;
x--
T_x t = x; x -= q; return t;
--x
x -= q; return reference to x;
Some coding styles may encounter compilation problems due to the lack of conversion
operators. The most common problem is the absence of the conversion to bool for bit widths
beyond 64 for ac_int and for all bit widths for ac_fixed. Table 25 shows some typical scenarios:
Table 2-15. Conversion to C Integer Types
ac_int<33,true> k = ...;
if( k )
if( (bool) k )
switch( k )
25
switch( 2*(int)k )
a[k]
a[2*k]
a[2*(int)k]
if( (bool) k )
if( !! k )
if( k != 0 )
if( k.to_bool() )
switch( k )
a[k]
if( !! x )
if( x != 0 )
if( k.to_bool() )
When writing parameterized IP where the bit-widths of some ac_int is parameterized, code that
may compile for some parameters, may not compile for a different set of parameters. In such
cases, it is important to not rely on the conversion operator.
26
are also defined for sc_bigint/sc_biguint). The method to_double() is also defined for both
ac_int and ac_fixed. The method to_ac_int() is defined for ac_fixed.
Table 2-16. Explicit Conversion Methods for ac_int/ac_fixed
Method
Types
Return Type
to_int()
ac_int/ac_fixed
int
to_uint()
ac_int/ac_fixed
unsigned int
to_long()
ac_int/ac_fixed
long
to_ulong()
ac_int/ac_fixed
unsigned long
to_int64()
ac_int/ac_fixed
Slong
to_uint64()
ac_int/ac_fixed
Ulong
to_double()
ac_int/ac_fixed
double
to_ac_int()
ac_fixed only
ac_int<max(I,1), S>
The [] operator does not return an ac_int, but rather it returns an object of class
ac_int::ac_bitref that stores the index and a reference to the ac_int object that is being indexed.
The conversion function to bool (operator bool) is defined so that a bit reference may be used
where a bool type is required:
while( y[k] && z[m] )
z = y[k] ? a : b;
{}
A bit reference may be assigned an integer. The behavior is that the least significant bit of the
integer is assigned to the bit reference. For example if n is type int and x is type ac_int then the
following three assignments have the same behavior:
x[k] = n;
x[k] = (ac_int<1,false>) n;
x[k] = 1 & n;
The conversion to any ac_int is provided and it equivalent to first converting to a bool or to a
ac_int<1,false>:
ac_int<5,false> x = y[0]; // equivalent to x = (bool) y[0]
The ac_bitref::operator=(int val) returns the bit reference so that assignment chains work as
expected:
27
The bit length of slice W: this is template argument (the length of the slice is constrained
to be static so that the length of the slice is known at compile time. The length of the
slice must be greater or equal to 1.
The slc method returns an ac_int of length W and signedness of the ac_int being sliced.
28
where lsb is the index of the LSB of the slice been written and slc is ac_int slice that is assigned
to the ac_int:
x.set_slc(7, y);
AC_VAL_DC
AC_VAL_0
AC_VAL_MIN
AC_VAL_MAX
AC_VAL_QUANTUM
enumeration values should not be used since it will assign the integer value of the enumeration
to the ac_int or ac_fixed.
Constructors
Constructors from all C-types are provided. Constructors from ac_int are also provided. The
default constructor does nothing, so non-static variables of type ac_int or ac_fixed will not be
initialized by default.
Algorithmic C Datatypes, v2.6
July 2011
29
Constructors from char *, have not been defined/implemented in the current release.
IO Methods
Methods to performing IO have not been
defined/implemented for the current release.
Mixing ac_int and ac_fixed with Other Datatypes
Refer to Mixing Datatypes on page 49 for information on how to interface ac_int and
ac_fixed to other data types.
30
Static member
width
i_width
sign
q_mode
AC_TRN
o_mode
AC_WRAP
Note that for generality all the static members are defined for ac_int even in the cases where
there is no corresponding template parameter involved as they do capture the numerical
behavior of ac_int.
The variable b_dummy is declared static so that the initialization of array b to dont_care occurs
only once rather than every time the function foo is invoked. The return value of ac::init_array is
always true, but in reality only the side effect to array b is of interest. A similar example to
initialize an array to zero that is not declared static would look like:
void foo( ... ) {
int b[200];
ac::init_array<AC_VAL_0>(b, 200);
...
}
The function ac::init_array does not check for array bound violations. The template argument to
ac::init_array is an enumeration that can be any of the following values: AC_VAL_0,
AC_VAL_DC, AC_VAL_MIN, AC_VAL_MAX or AC_VAL_QUANTUM (see Table 2-17
for details). The function is defined for the integer and fixed point datatypes shown in
Table 2-19:
Table 2-19. Required Include Files for ac::init_array Function
Type
C integer types
ac_int.h
ac_int, ac_fixed
No additional include
ac_int.h, ac_sc.h
The first argument is of type pointer to one of the types in Table 2-19. Arrays of any dimension
may be initialized using ac::init_array by casting it or taking the address of the first element:
static int b[200][200];
static bool b_dummy = ac::init_array<AC_VAL_DC>((int*) b, 200*200);
31
ac::init_array<AC_VAL_0>(b+50, 100);
32
for a circular buffer. The minimum bitwidth of the index variable into the buffer is
ceil(log2(Size)) where Size is the size of the buffer.
The computation of the log2 functions is accomplished using a recursive template class. For the
user it suffices to know the syntax on how to retrieve the desired value as shown in Table 2-20.
Table 2-20. Syntax for log2 functions
Function
Syntax
ceil(log2(x))
ac::log2_ceil<x>::val
floor(log2(x))
ac::log2_floor<x>::val
nbits(x)
ac::nbits<x>::val
Return type
neg
T::rt_unary::neg
mag
T::rt_unary::mag
mag_sqr
T::rt_unary::mag_sqr
33
Return type
summation of N elements
T::rt_unary::set<N>::sum
Return Type
op1 * op2
T1::rt_T<T2>::mult
op1 + op2
T1::rt_T<T2>::plus
op1 - op2
T1::rt_T<T2>::minus
op1 / op2
T1::rt_T<T2>::div
T1::rt_T<T2::logic
op2 - op1
T1::rt_T<T2>::minus2
op2 - op1
T1::rt_T<T2>::div2
The last two rows in Table 2-22 are mostly there as helper functions to build up the
infrastructure and are not in general needed. For example if both T1 and T2 are AC datatypes
then instead of using T1::rt_T<T2>::minus2, T2::rt_T<T1>::minus could be used. These
versions are only there for non-commutative operators.
Returning to the mult_add example, the type T would be expressed as:
where the keywords typename and template are used when Ta, Tb and Tc are template
arguments (dependent-name lookup). In this case getting to the type was done in two steps by
first defining the type a_mult_b. In the following version, the it is done in one step so that it can
be used directly as the return type of the templatized function mult_add:
template<typename Ta, typename Tb, typename Tc>
typename Ta::template rt_T<Tb>::mult::template rt_T<Tc>::plus mult_add(Ta
a, Tb b, Tc c) {
typename Ta::template rt_T<Tb>::mult::template rt_T<Tc>::plus res = a *
b + c;
return res;
}
Note that additional template keywords are used because the lookup of rt_T is a dependentname lookup, that is the parser does not know that Ta::rt_T is a templatized class until it knows
the type Ta (this happens only once the function mult_add is instantiated).
34
35
36
Chapter 3
Complex Datatype
Introduction
The algorithmic datatype ac_complex is a templatized class for representing complex numbers.
The template argument defines the type of the real and imaginary numbers and can be any of the
following:
37
Complex Datatype
Introduction
i
s
i
i
f
f
Operators for multiplying a variable of type ac_complex by a real number also are defined with
the same restrictions as outlined above. For example:
ac_complex<ac_int<5,true> > i(2, 1);
ac_complex<ac_fixed<8,3,false> f(1, 5);
ac_fixed<8,3,false> f_r = 3;
unsigned short s_r = 5;
double d_r = 3.5
i * f_r; // OK: ac_int and ac_fixed can be mixed
s_r * i; // OK: native int type can be mixed with ac_int
i * d_r; // ERROR: ac_int/double + and * operators are not defined
i * 0.1; // ERROR: ac_int/float + and * operators are not defined
i == d_r; // ERROR: ac_int/double comparison operator is not defined
f == d_r; // OK: ac_fixed/double comparison operator is defined
i == 0.1; // ERROR: ac_int/float comparison operators is not defined
f == 0.1; // OK: ac_fxed/double comparison operator is defined
ac_complex
Two operand +, -, *, /,
assignment
==, !=
Unary +, -
Arithmetic
!x
Equiv to x == 0
Table 3-2 shows the methods defined for the ac_complex type.
Table 3-2. Methods defined for ac_complex<T>.
38
Methods
ac_complex
r(), real()
i(), imag()
Complex Datatype
Usage
ac_complex
set_r(const T2 &r)
set_i(const T2 &i)
conj()
complex conjugate
sign_conj()
mag_sqr()
to_string
type_name()
Usage
In order to use the ac_int datatype the following header file must be included in the C++ source:
#include <ac_complex.h>
Recommendations
1. Do not use native C type unsigned (unsigned int) as the return type (and the arithmetic)
is defined according to the promotion/arithmetic rules of the C language. That is the
resulting complex type will based on the type unsigned. For example:
ac_complex<unsigned> x(0,1);
cout << x*x; // result is (232 - 1, 0)
2. Pay special attention on the return type when performing division. For example, if two
ac_complex based on native C type int are divided, the result will be an ac_complex
based on int and truncation will take place.
39
Complex Datatype
Advanced utility functions, typedefs, etc
40
Chapter 4
Datatype Migration Guide
Introduction
This Chapter provides detailed explanations on differences between the Algorithmic datatypes
and the built-in C integer types and the SystemC integer and fixed-point types.
works when x is a C integer or a SystemC data type but will error out when x is an ac_int or
ac_fixed because x and -x dont have the same type (their bitwidths are different). Explicit
casting may be needed for the question mark operator so that both choices have the exact same
type. For example, in the examples below the expressions in the left (using sc_int) are re-coded
with ac_int as follows:
where variable a_5s is a 5-bit wide signed sc_int or ac_int and so on.
The SystemC datatypes dont require casting because they share the same base class that
contains the actual value of the variable. Note that an integer constant such as 1 is of type int
and will be represented as an ac_int<32, true>, so an expression such as a_4s + 1 will have type
ac_int<33,true> instead of ac_int<5,true>.
SystemC Syntax
Table 4-1 shows the SystemC bit-accurate datatypes that ac_int and ac_fixed can replace. Using
ac_int and ac_fixed it is possible to write generic algorithms that work for any bitwidth and that
simulate faster than the fast (but limited) SystemC types sc_int, sc_uint, sc_fixed_fast,
sc_ufixed_fast.
41
New Datatype
Comments
sc_int<W>
ac_int<W,true>
sc_uint<W>
ac_int<W,false>
sc_bigint<W>
ac_int<W,true>
sc_biguint<W>
ac_int<W,false>
sc_fixed_fast<W,I,Q,O>
ac_fixed<W,I,true,Q,O>
sc_fixed_fast limited to
mantissa of double
sc_ufixed_fast<W,I,Q,O>
ac_fixed<W,I,false,Q,O>
sc_ufixed_fast limited to
mantissa of double
sc_fixed<W,I,Q,O>
ac_fixed<W,I,true,Q,O>
sc_ufixed<W,I,Q,O>
ac_fixed<W,I,false,Q,O>
The ac_int and ac_fixed types have the same parameters with the same interpretation as the
corresponding SystemC type. The difference is an extra boolean parameter S that defines
whether the type is signed (S==true) or unsigned (S==false). Using a template parameter
instead of different type names makes it easier to write generic algorithms (templatized) that can
handle both signed and unsigned types. The other difference is that ac_fixed does not use the
nbits parameter that is used for the SystemC fixed-point datatypes.
The template parameters Q and O are enumerations of type ac_q_mode and ac_o_mode
respectively. All quantization modes are supported as shown in Table 4-3. Most commonly
used overflow modes are supported as shown in Table 4-4.
Table 4-3. Quantization Modes for ac_int and Their Relation to
sc_fixed/sc_ufixed
42
ac_fixed
sc_fixed/sc_ufixed
AC_TRN (default)
SC_TRN (default)
AC_RND
SC_RND
AC_TRN_ZERO
SC_TRN_ZERO
AC_RND_ZERO
SC_RND_ZERO
AC_RND_INF
SC_RND_INF
AC_RND_MIN_INF
SC_RND_MIN_INF
AC_RND_CONV
SC_RND_CONV
sc_fixed/sc_ufixed
AC_WRAP (default)
AC_SAT
SC_SAT
AC_SAT_ZERO
SC_SAT_ZERO
AC_SAT_SYM
SC_SAT_SYM
All operands are defined consistently with ac_int: if both ac_fixed operands are pure integers
(W and I are the same) then the result is an ac_fixed that is also a pure integer with the same
bitwidth and value as the result of the equivalent ac_int operation. For example: a/b where a is
an ac_fixed<8,8> and b is an ac_fixed<5,5> returns an ac_fixed<8,8>. In SystemC, on the other
hand, the result of a/b returns 64 bits of precision (or SC_FXDIV_WL if defined).
where x.slc<W>(i) returns an ac_int<W, SX> where SX is the signedness of variable x. The
slice method returns an ac_int for both ac_int and ac_fixed. Also note that W must be a
constant. For instance x.range(i, j) would translate into x.slc<i-j+1>(j) provided both i and j are
constants.
For assigning a range:
x.range(i+W-1,i) = y (or x.(i+W-1,i) = y) becomes x.set_slc(i, y)
this assumes that y is of type either ac_int<W, false> or ac_int<W, true>, otherwise it needs to
be cast to either type.
Concatenation
The concatenation operator (the , operator in sc_int/sc_uint and sc_bigint/sc_biguint) is not
defined in ac_int or ac_fixed. The solution is to rewrite it using set_slc:
43
Other Methods
Table 4-5 shows other less frequently used methods in SystemC datatypes that would require
rewriting in ac_int.
Table 4-5. Migration of SystemC Methods to ac_int
SystemC
ac_int
iszero
operator !
sign
x<0
bit
x[i]
reverse
no equivalent
test
x[i]
set
x[i] = 1
clear
x[i] = 0
invert
x[i] = !x[i]
Constructors from char *, are not defined/implemented for ac_int and ac_fixed.
Failing to include them in the above order will result in compile errors. In addition to proper
include file ordering, you can only trace using VCD format files (i.e. using the
sc_create_vcd_trace_file() function in SystemC). Using any other trace file format may result in
a crash during simulation.
integer of bitwidth bw respectively. Also Slong and Ulong will be used to denote the C 64-bit
integer types long long and unsigned long long respectively.
The differences between limited and arbitrary length integer datatypes can be group in several
categories as follows:
Mixing signed and unsigned can lead to unexpected results. Many operators are not
defined so they fall back to the underlying C types Slong and Ulong. Conversion rules in
C change the signed operand to unsigned when a binary operation has mixed Slong and
Ulong operands. This leads to the following non intuitive results:
o
Note however, that operations such as +, -, and *, |, &, ^ provided the result is assigned
to an integer type of length 64 or less, or is used in expressions that are not sensitive to
the signedness of the result:
o
sc_bigint<67> i = a_u8 * b_s9 + x_u13 & y_s4; // Bad, assigning Ulong to 67 signed
w_u20 = (a_u8 * b_s9) / c_s6; // Bad, s/s div should be ok, but numerator is Ulong
45
Shifting has the same limitations as in C. The C language only defines the behavior of
integer shifts on a Slong or Ulong when the shift value is in the range [0, 63]. The
behavior outside that range is compiler dependent. Also some compilers (Visual C 6.0
for example) incorrectly convert the shift value from Slong to Ulong if the first operand
is Ulong.
Initialization
The SystemC integer datatypes are initialized by default to 0 by the default constructor, whereas
ac_int is not initialized by the default constructor. If the algorithm relies on this behavior, the
initialization needs to be done explicitly when migrating from SystemC integer datatypes to
ac_int. This issue is not there for fixed-point datatypes as neither the sc_fixed/sc_ufixed nor
ac_fixed initializes by default.
Note that non local variables (that is global, namespace, and static variables) dont have this
issue as they are initialized by virtue of how C/C++ is defined.
Shift Operators
The ac_int and ac_fixed shift operators are described in the section Shift Operators on
page 22. Shift operations present the most important differences between the Algorithmic C
types and the SystemC types.
SystemC Types
The return type of the left shift for sc_bigint/sc_biguint or sc_fixed/sc_ufixed does not
lose bits making the return type of the left shift data dependent (dependent on the shift
value). Shift assigns for sc_fixed/sc_ufixed may result in quantization or overflow
(depending on the mode of the first operand).
46
Shifting occurs on either 32-bit (int, unsigned int) or 64-bit (long long, unsigned long
long) integrals. If the first operand is an integral type that has less than 32 bits (bool,
(un)signed char, short) it is first promoted to int. The return type is the type of the first
argument after integer promotion (if applicable).
Shift values are constrained according to the length of the type of the promoted first
operand.
o
The behavior for shift values outside the allowed ranges is not specified by the C++ ISO
standard.
The shift left operator of ac_int returns an ac_int of the same type (width and signedness) of the
first argument and it is not equivalent to the left shift of sc_int/sc_uint or sc_bigint/sc_biguint.
To get the equivalent behavior using ac_int, the first argument must be of wide enough so that is
does not overflow. For example
(ac_int<1,false>) 1 << 1 = 0
(ac_int<2,false>) 1 << 1 = 2
Both the right and left shift operators of ac_int return an ac_fixed of the same type (width,
integer width and signedness) of the first argument and is not equivalent to the corresponding
operator in sc_fixed/sc_ufixed. Despite the fact that there might be loss of precision when
shifting an ac_fixed, no quantization or overflow is performed. The first argument must be large
enough width and integer width to guarantee that there is no loss of precision.
The behavior for indices outside the 0 to W-1 range for SystemC datatypes is not consistent. For
example sc_int/sc_uint and sc_fixed/sc_ufixed dont allow it (runtime error) while
sc_bigint/sc_biguint allow even negative indices (changed to a 0 index).
Conversion Methods
The conversion methods to_int(), to_long(), to_int64(), to_uint(), to_uint64() and to_ulong()
for sc_fixed/sc_ufixed are implemented by first converting to double. For instance:
47
The difference in most cases will be subtle (double has a signed-magnitude representation so it
truncates towards zero instead of truncating towards minus infinity) but could be very different
if the number would overflow the int or long long C types.
Neither ac_int nor ac_fixed provide a conversion operator to double (an explicit to_double
method is provided). SystemC datatypes do provide that conversion. There are a number of
cases where that can lead to non intuitive semantics:
sc_fixed<7,4> x = ...;
int t = (int) x; // equiv to (int)(double) x
bool b = !x;
// equiv to ! (double) x
The reason for this discrepancy is that for C integers the return type for the unary operators ~
and - is the type of the promoted type for the operand. If the argument is signed/unsigned int,
long or long long, integer promotion does not change the type. For example, when the operand
is unsigned int, then the return type of either ~ or - will be unsigned int. Note however that
unsigned char and unsigned short get promoted to int which makes the behavior consistent with
ac_int:
unsigned short x = 0;
unsigned short mask = ~x >> 8; // mask is 0xFFFF, not 0xFF
ac_int<16,false> x = 0;
ac_int<16,false> mask = ~x >> 8; // mask is 0xFFFF
The arithmetic definition of the operator ~ makes the value result independent of the bit-width
of the operand:
if x == y, then ~x == ~y // x and y may be different bitwidths
48
Also the arithmetic definition is consistent with the arithmetic definition of the binary (two
operand) logical operators &, |, and ^. For instance:
~(a | b) == ~a & ~b
The arithmetic definition of the logical operators &, |, ^ is necessary since signed and unsigned
operands of various bit-widths may be combined.
Mixing Datatypes
This section describes the conversion functions that are used interface between the bit-accurate
integer datatypes.
Explicit conversion functions are provided between the datatypes sc_bigint/sc_biguint and
ac_int and between sc_fixed/sc_ufixed and ac_fixed. They are provided in a different include
file:
$MGC_HOME/shared/include/ac_sc.h
49
For example:
sc_bigint<123> x = to_sc(y); // y is ac_int<123, true>
50
Chapter 5
Frequently Asked Questions
Operators ~, &, |, ^, -, ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why does ~ and - for an unsigned return signed? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why are operators &, |, ^ arithmetically defined?. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why does operator ! return different results for ac_fixed and sc_fixed? . . . . . . . . . . . . . .
Conversions to double and Operators with double . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why is the implicit conversion from ac_fixed to double not defined?. . . . . . . . . . . . . . . .
Why are most binary operations not defined for mixed ac_fixed and double arguments?.
Constructors from strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why are constructors from strings not defined? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Shifting Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why does shifting gives me unexpected results? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Division Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why does division return different results for ac_fixed and sc_fixed? . . . . . . . . . . . . . . .
Compilation Problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why arent older compilers supported? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why doesnt the slc method compile in some cases? . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why do I get compiler errors related to template parameters?. . . . . . . . . . . . . . . . . . . . . .
Platform Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
What platforms are supported? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Purify Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Why do I get UMRs for ac_int/ac_fixed in purify? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
User Defined Asserts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Can I control what happens when an assert is triggered? . . . . . . . . . . . . . . . . . . . . . . . . . .
51
51
51
52
52
52
52
53
53
53
53
53
53
53
53
54
54
54
54
54
54
55
55
Operators ~, &, |, ^, -, !
Why does ~ and - for an unsigned return signed?
See Unary Operators ~, - and Binary Operators &, |, ^ on page 48.
51
could be made more efficient by storing the constant in an ac_fixed so that the overhead of
converting from double to ac_fixed is incurred once (outside the loop):
ac_fixed<1,0,false> c0_5 = 0.5;
while( ... ) {
if( x > c0_5 ) // more efficient
...
}
52
Shifting Operators
Why does shifting gives me unexpected results?
The shift operation for ac_int/ac_fixed differs from the shift operations in SystemC and native
(built-in) C integers. See Section - Shift Operators. The main difference is that the shift
operation for ac_int/ac_fixed returns the type of the first operand.
ac_int<2,false> x = 1;
x << 1; // returns ac_int<2,false> (2), value is 2
x << 2; // returns ac_int<2,false> (4), value is 0
(ac_int<3,false>) x << 2; // returns ac_int<3,false> (4), value is 4
The main reason for this semantic is that for an arbitrary-length type, a definition that returns a
fully arithmetic value requires a floating return type which violates the condition that the return
type should an ac_int or an ac_fixed type. Supporting a floating return type creates a problem
both for simulation speed and synthesis. For example the type of the expression
a * ( (x << k) + y)
Division Operators
Why does division return different results for ac_fixed
and sc_fixed?
Division for sc_fixed/sc_ufixed returns 64 bits of precision (or whatever SC_FXDIV_WL is
defined as). The return type for ac_fixed is defined depending on the parameters of both the
dividend and divisor (see Table 2-9 on page 21).
Compilation Problems
Why arent older compilers supported?
The support of templates is not adequate in older compilers.
53
Without the keyword template the t.slc<N>(4) is parsed as t.slc < N since it does not know
whether slc is a data member or a method (this is known once template function f and therefore
ac_int<N,true> is instantiated).
Platform Dependencies
What platforms are supported?
The current implementation assumes that an int is 32 bits and that a long long is 64-bits, both in
2s complement representation. These assumptions need to be met for correct simulation of the
data types. In addition a long is assumed to be 32 bits wide, a short is assume to be 16 bits and a
char is assumed to be 8 bits wide. A plain char (neither signed or unsigned) is assumed to be
signed. These assumptions are only relevant if the types are used to initialize/construct an ac_int
or ac_fixed or they are used in expressions with ac_int or ac_fixed.
Purify Reports
Why do I get UMRs for ac_int/ac_fixed in purify?
The following code will report a UMR in purify:
ac_int<2,false> x;
x[0] = 0;
// UMR
x[1] = 1;
54
The UMR occurs because x is not initialized, but setting a bit (or a slice) requires accessing the
original (un-initialized) value of x.
A second source of UMRs is explicit calls to un-initialize an ac_int/ac_fixed that were declared
static (see Section - Using ac::init_array for Initializing Arrays). This is used mostly for
algorithms written for hardware design.
55
56