If you have previously used ACT (versions from 2006 to 2018), there are a few minor changes that clean up the language and make the syntax more consistent. There are also some new features that you might find helpful that simplify describing circuits in ACT.
Syntactic replication using loops now uses consistent syntax. This means that the following previous ACT syntax should be replaced by the alternative syntax
Purpose | Old ACT | Current ACT |
---|---|---|
Replicating ACT body constructs | (; i : range : items ) deprecated | (i : range : items ) |
Replicating ACT body or PRS | (: i : range : items ) | (i : range : items ) |
AND and OR PRS expressions | (: | i: range : items) or (:&i: range : items) | (| i: range : items ) or (&i:range: items) |
The old ACT had channel and data type bodies for send/recv/put/get methods, but they were ignored. So if you have old ACT that has those, you can simply delete them. Otherwise you can use the new method syntax.
The old ACT only had single-assignment parameters. So
pint x; x=1; x=2;
would result in an error. This was sometimes used to implement assertions. For example, if a parameter x
was supposed to be twice another parameter y
, then
x=2*y;
would silently pass if the the relationship was satisfied, assign a value to x
if it was not initialized, or report an error.
The new ACT supports mutable parameter variables in restricted contexts. To support the assertion feature, the new ACT supports explicit assertions. We use Hoare's syntax, and so the assertion specified earlier would be written
{x=2*y};
If a more meaningful message is required, the following syntax is also supported:
{x=2*y : "This assertion failed"};
which also reports the message specified.
In the previous version of ACT, one could do the following:
bool x[2][2]; bool y[2]; x[0] = y;
Here, x[0]
was treated as an array expression that corresponds to the one-dimensional slice x[0][0..1]
of the two-dimensional array x
. This is useful short-hand, but we found it led to ACT files that were harder for others to understand.
While this functionality is still useful, the new ACT will complain about the connection specified above by saying
Mismatch in array dimensions (1 v/s 2): x[0]
Instead, you can get the same effect by saying:
x[0][0..1] = y;
With this syntax, the fact that x
is a two-dimensional array is explicit, and it is visually obvious that the left hand side is a one-dimensional slice of x
.
When two signals are connected to each other, ACT picks one of them to be the canonical name for the signal and tracks the other names as aliases. In older versions, the canonical name was selected as the outer most, shortest name. Here, outer most means the name accessible with the fewest dots. So, for example, if you had an e1of2
channel with fields t
, f
, and e
, and a definition like this:
defproc test (e1of2 x) { bool y; x.t = y; }
then the canonical Booleans would be y
, x.f
, and x.e
. The rationale was that the name at the highest level of the hierarchy should be selected as the canonical name.
This could sometimes make port lists for processes hard to understand especially for tools that did not track all the aliases of a name. A much-requested feature was that names in the port list take precedence over internal signal names. In this particular example, that would mean that x.t
would get used as the canonical name rather than y
.
The new ACT library now implements a different way to select the canonical name for a signal. In a particular process, there are three signal categories: globals, ports, and local signals. These are given priority during canonical name selection: a global has the highest priority, followed by ports, followed by local signal names. Arrays have higher priority than non-arrays (in an attempt to keep array structures unfragmented), and if the global/port/local classification is the same, the outermost, shortest heuristic is still used to break ties.