15.3  Registers

The language includes the integer and fixed-point register class templates of Algorithmic C [algc], which may be instantiated as follows:

By convention, we use the names ui$ n$, si$ n$, uf$ n$i$ m$, and sf$ n$i$ m$ for the types ac_int<n, false> and ac_int<n, true>, ac_fixed<n, m, false>, and ac_fixed<n, m, true>, respectively. These types are expected to be declared as needed at the beginning of a program, as in the following examples:
  typedef ac_int<96,false> ui96;
  typedef ac_int<48,true> si48;
  typedef ac_fixed<64,4,false> uf64i4;
  typedef ac_fixed<32,16,false> uf32i16;

A register is associated with two values, a raw value, which is a bit vector of the same width as the register, and an integer or rational interpreted value. The interpreted value is derived from the raw value according to the register's type as follows:

The interpretation of register values is formalized by the following functions:

Definition 15.3.1   (ui, si, uf, sf) Let $ n \in \mathbb{Z}$ and $ m \in \mathbb{Z}$ with $ n > 0$ and let $ r$ be a bit vector of width $ n$.

(a) $ \mathit{ui}(r) = r$;

(b) $ \mathit{si}(r, n) = \left\{\begin{array}{ll}
r & \mbox{if $r < 2^{n-1}$} \\
r-2^n & \mbox{if $r \geq2^{n-1}$.}\end{array}\right.$;

(c) $ \mathit{uf}(r, n, m) = 2^{m-n}\mathit{ui}(r) = 2^{m-n}r$;

(d) $ \mathit{sf}(r, n, m) = 2^{m-n}\mathit{si}(r, n) = \left\{\begin{array}{ll}
2^...
...r < 2^{n-1}$} \\
2^{m-n}r-2^m & \mbox{if $r \geq 2^{n-1}$,}\end{array}\right.$.

Note that while the width $ n$ of a register must be positive, there is no restriction on the number $ m$ of integer bits of a fixed-point register. If $ m>n$, then the interpreted value is an integer with $ m-n$ trailing zeroes; if $ m<0$, then the interpreted value is a fraction with $ -m$ leading zeroes.

The Algorithmic C register types include a "bit select" operator and "bit slice" methods. Bit selection is independent of the register type (signed vs. unsigned, integer vsfixed-point) and uses the familiar syntax. Thus, a bit $ x[i]$ of a register $ x$ may be extracted or assigned in the natural way. The syntax of bit slices is less straightforward. The slice extraction method slc requires a constant template parameter indicating the width of the slice and a variable argument that represents the base index. Thus,

x.slc<4>(n)
determines the slice of x of width 4 based at bit n, which the pretty-printer renders as
x[n+3,n].
The value of this method is an integer register (independent of whether the register is integer or fixed-point) with ther same width parameter as the method and the same sign parameter as the operand. Thus, the numerical value of a slice is a signed or unsigned integer according to the type of the register from which it is extracted.

A bit slice is modified by a method of two arguments, the base index and an integer register containing the value to be written. The width of the slice is not specified explicitly, but rather is inferred from the type of the second argument. For example, the assignment

x.set_slc(n, ui4(6))
replaces the slice of x of width 4 based at index n with the value 6 (binary 0110), and is pretty-printed as
x[n+3:n] = 6.

David Russinoff 2017-08-01