This is an old revision of the document!
Expressions
Expression syntax in ACT is similar to expressions in the C language.
- Integer expressions: operators that are supported include
+
,-
,*
,/
, and%
for integer arithmetic operations, and&
,|
, and~
for bit-wise logical operations between integers. - Boolean expressions can be constructed from Boolean variables, the constants
true
andfalse
, and the Boolean operators&
,|
, and~
denoting the and, or, and negation operations respectively. (This is a departure from C, where and/or operations between conditions use&&
and||
.) - Numerical expressions can be compared using
<
,< =
,>
,>=
,=
, and!=
for the operators less than, less than or equal to, greater than, greater than or equal to, equal to, and not equal to respectively. - The query expression
(e ? e1 : e2)
behaves like the C operator. The result ise1
ife
is true, ande2
otherwise. - Logical shift operators are
«
(left shift),»
(logical right shift), and the arithmetic right shift operator»>
. - Bit operations: For a variable
x
, the valuex{b..a}
extracts bitsb
througha
(both included, withb
at leasta
). Bothb
anda
must be constants (or computed by parameters, i.e. constants after expansion). The syntaxx{a}
is syntactic sugar forx{a..a}
, and extracts one bit fromx
. - Concatenation: Given a set of expressions,
{e1,e2,e3,…,eN}
concatenates the bits of the expressions to form a wide result.
Expressions can also include function calls, with the usual function call syntax. More details on how functions are defined is below. Expressions can also include type-conversion operators:
int(x)
:x
must be a Boolean expression.int(x)
will be 0 if the expression is false, or 1 otherwise.int(x,w)
:x
must be an integer expression, andw
must be evaluate to an integer constant after expansion (i.e. it can only be an integer expression that includes parameters). This changes the bit-width of the integer to bew
. If the width is reduced, the high order bits are truncated; if the bit-width is increased, the integer is zero extended.bool(x)
:x
must be an integer expression. This returns false if the integer is zero, and true otherwise.
Parameters and constant expressions
Parameter expressions are used to compute parameter values (pint
/pbool
) and are evaluated at expansion time. These expressions are signed integers, and use 64-bit integer arithmetic. All constants are simplified at expansion time using the same 64-bit integer arithmetic as parameters.
Expressions in CHP
The same expression syntax is also used in the chp
and dataflow
sub-languages. Once again, constant expressions are simplified as above. However, expressions can also include variables that are determined at run-time rather than expansion time (i.e. when the circuit is executing the specified computation.) In this case, we need rules to determine the bit-width of an expression. The rules are as follows:
- Each variable has the bit-width specified by its type.
- A constant uses the minimum number of bits needed to represent it. Note that a negative constant is assumed to be a two's complement value, an its bit-width is determined in the same way.
- For unary operators, the bit-width of the result is the same as the bit-width of the argument
- For binary operators and ternary operators where the result is an integer, let left be the bit-width of the left-hand side of the operator, and right be the bit-width of the right hand side. There are seven categories of result bit-widths:
- max(left,right) : for logical operators (bit-wise and, or, etc.). The smaller operand is zero-extended. For query expressions, left and right are the bit-widths of the two options, since the first part of the query expression is Boolean.
- 1+max(left,right) : for addition and subtraction
- left+right : for multiplication
- left : for division, and both arithmetic and logical right shifts.
- right : for mod
- left + 2^right - 1 : for left shift
- For concatenation, the bit-width is the sum of all the components
Functions
ACT provides support for user-defined functions. These functions can be used to make your design more understandable. The syntax of a function is illustrated by the following example:
function f (pint x) : pint { chp { self := x + 1 } }
The function
keyword is used to define a function. Here, function f
is defined, and it takes one parameter (x
of type pint
), and has a return type pint
(indicated by : pint
).
The CHP language is used to implement the body of a function. The special variable self
can be used in the body of the CHP language, and its value on termination of the CHP program indicates the return value.
Additional parameters that might be helpful as auxilliary variables can be defined within the body of the function in the usual way.
function sumint (pint x) : pint { pint i; chp { i := 0; self := 0; *[ i < x -> self := self + i; i := i + 1 ] } }
There are two flavors of functions:
- Functions where all the arguments and return type are parameter types
- Functions where all the arguments and return types are non-parameter data types
The first kind of function is typically used when constructing the circuit, and its value can be statically computed during the circuit construction phase. The second kind of function is viewed as CHP, and can be implemented either by inlining the function or through some other approach (e.g. shared, partially shared, etc).