====== Processes and cells ======
A process is a user-defined type that corresponds to a circuit
entity. Other hardware description languages sometimes call it a module
or a subcircuit. The basic syntax of a process definition is shown below.
defproc test (bool n, m; bool p, q)
{
...
}
The definition above creates a new process, called ''test'', that has
a port list consisting of four ''bool''s. This port list cannot
contain any parameter types (''pint'', etc).
If the body of the user-defined type is replaced by a single
semi-colon or is empty, the statement corresponds to a type
//declaration//. Declarations are typically used when defining
mutually recursive types. The declaration corresponding to type
''test'' is:
defproc test (bool n, m; bool p, q);
If the process is never defined, ACT assumes that it has an empty
body. If a process declaration is followed by a definition, the type
signature must match exactly.
defproc test (bool n, m; bool p, q);
defproc test (bool n, m; bool p) { }
-[ERROR]-> Name `test' previously defined as a different process
A type can only have one definition in a given scope.
defproc test (bool n) { ... }
defproc test (bool n) { ... }
-[ERROR]-> Process `test': duplicate definition with the same type signature
The body of a process specifies its implementation. This can use a
combination of instances of other processes, connections, and other
languages like production rules. Loops and conditional statements can
also be used to construct a process.
Port lists have a syntax similar to instantiations. A type
specifier can be followed by a list of identifiers rather than just a
single identifier, similar to an instantiation. Semicolons are used
to separate parameters of differing types, as shown in the example
below.
defproc test2(bool n,m; d1of2 p,q) { ... }
In this example we assumed that there was a user-defined type (or
channel) called ''d1of2'' that was used in the port list. Any
user-defined type in the port list must be either a data or channel
type. Processes are supposed to correspond to circuit blocks, and so
cannot be port parameters to other circuit blocks.
Square brackets can also be used following the identifier names to
specify array ports. The meaning of these square brackets is identical
to the ordinary array instantiation. However, the arrays in port lists
are restricted to be dense arrays indexed at zero. This restriction is
enforced by syntax, and will be reported as a parse error.
defproc test1 (bool a,b,c, d[10]) { } // success!
defproc test2 (bool a,b,c, d[0..9]) { }
-[ERROR]-> Expecting token `]', got `.'
The ports themselves cannot be converted to sparse arrays within the
body of a definition. This means that the following is illegal:
defproc test1 (bool a, b, c, d[10])
{
bool d[11..12];
...
}
-[ERROR]-> Array instance for `d': cannot extend a port array
Type names and variable names do not share the same name space.
Creating a type definition with the same name as an instance variable
or vice versa is allowed, but deprecated.
Cells follow the same rules for definition as processes, except the
keyword ''defcell'' is used in place of ''defproc''. The reason
for separating cells from processes is that processes are supposed to
correspond to logical entities that are meaningful semantic
objects. For example, a process ordinarily has its origins in a CHP
language description. Cells, on the other hand,
can be fragments of logical processes. Examples of cells are standard
gates like C-elements, NAND, or NOR gates, or commonly used circuit
structures like completion detection logic. Cells are distinguished
from processes to make it easier to write automation tools.