Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
language:introduction [2019/04/18 10:54] rajit [Arrays] |
language:introduction [2024/11/18 08:16] (current) rajit [Variables and expressions] |
||
---|---|---|---|
Line 16: | Line 16: | ||
To get a feel for how a circuit is described in ACT, we begin with a simple example circuit. The purpose of this circuit is to create a dual rail channel (called '' | To get a feel for how a circuit is described in ACT, we begin with a simple example circuit. The purpose of this circuit is to create a dual rail channel (called '' | ||
- | < | + | < |
/* my first act program */ | /* my first act program */ | ||
defchan a1of2 <: chan(bool) (bool d0,d1,a) | defchan a1of2 <: chan(bool) (bool d0,d1,a) | ||
Line 72: | Line 72: | ||
legal: | legal: | ||
- | < | + | < |
bitbucket b; | bitbucket b; | ||
a1of2 x1; | a1of2 x1; | ||
Line 81: | Line 81: | ||
On the other hand, the following declaration is incorrect. | On the other hand, the following declaration is incorrect. | ||
- | < | + | < |
pbool 5; | pbool 5; | ||
+ | </ | ||
+ | < | ||
-[ERROR]-> | -[ERROR]-> | ||
</ | </ | ||
Line 90: | Line 92: | ||
parser was expecting. Error messages are accompanied by the file name, | parser was expecting. Error messages are accompanied by the file name, | ||
line number, and column number of the item that resulted in the error. | line number, and column number of the item that resulted in the error. | ||
+ | |||
+ | The variable names '' | ||
+ | ACT language features like functions and user-defined types. | ||
The names in the port list of a user-defined type are the only parts of | The names in the port list of a user-defined type are the only parts of | ||
Line 96: | Line 101: | ||
consider the following definition of '' | consider the following definition of '' | ||
- | < | + | < |
defproc bitbucket(a1of2 d) | defproc bitbucket(a1of2 d) | ||
{ | { | ||
Line 112: | Line 117: | ||
result in the following message: | result in the following message: | ||
- | < | + | < |
bitbucket b; | bitbucket b; | ||
a1of2 c; | a1of2 c; | ||
b.p = c.d0; | b.p = c.d0; | ||
+ | </ | ||
+ | < | ||
-[ERROR]-> | -[ERROR]-> | ||
</ | </ | ||
Line 137: | Line 144: | ||
Most circuits contain a set of components that are replicated a number | Most circuits contain a set of components that are replicated a number | ||
- | of times. This is especially common in datapath circuits. | + | of times. This is especially common in datapath circuits. |
very flexible array mechanism that can be used to construct complex | very flexible array mechanism that can be used to construct complex | ||
circuits. The simplest way to create an array is shown below. | circuits. The simplest way to create an array is shown below. | ||
- | < | + | < |
bool x[10]; | bool x[10]; | ||
a1of2 y[5][3]; | a1of2 y[5][3]; | ||
Line 153: | Line 160: | ||
be specified as shown below | be specified as shown below | ||
- | < | + | < |
bool w[4..7]; // create Booleans w[4], ..., w[7] | bool w[4..7]; // create Booleans w[4], ..., w[7] | ||
</ | </ | ||
Line 162: | Line 169: | ||
block. Consider the following instantiation: | block. Consider the following instantiation: | ||
- | < | + | < |
bool x[10]; | bool x[10]; | ||
bool x[12..14]; | bool x[12..14]; | ||
Line 172: | Line 179: | ||
following, on the other hand, is not valid. | following, on the other hand, is not valid. | ||
- | < | + | < |
bool x[10]; | bool x[10]; | ||
bool x[9..14]; | bool x[9..14]; | ||
-[ERROR]-> | -[ERROR]-> | ||
- | Oiginal: [10]; adding: [9..14] | + | Original: [10]; adding: [9..14] |
</ | </ | ||
Each index of an array can only be created once. | Each index of an array can only be created once. | ||
Line 189: | Line 196: | ||
below. | below. | ||
- | < | + | < |
bool x[10]; | bool x[10]; | ||
bool x[12..14]; | bool x[12..14]; | ||
Line 203: | Line 210: | ||
succeed, and their shapes also have to be compatible. | succeed, and their shapes also have to be compatible. | ||
- | < | + | < |
bool x[12]; | bool x[12]; | ||
bool w[4][3]; | bool w[4][3]; | ||
x=w; | x=w; | ||
+ | </ | ||
+ | < | ||
-[ERROR]-> | -[ERROR]-> | ||
Types `bool[12]' | Types `bool[12]' | ||
Line 213: | Line 222: | ||
The following are examples of valid connections: | The following are examples of valid connections: | ||
- | < | + | < |
bool x[10]; | bool x[10]; | ||
bool x[10..12]; | bool x[10..12]; | ||
Line 225: | Line 234: | ||
===== Loops and conditionals ===== | ===== Loops and conditionals ===== | ||
+ | |||
+ | Loops and conditionals can be used to describe complex circuit | ||
+ | structures in a compact manner. Loops are useful when creating array | ||
+ | structures, or connecting arrays in a regular manner. For example, | ||
+ | suppose '' | ||
+ | and '' | ||
+ | carry chain for a ten bit ripple-carry adder. | ||
+ | |||
+ | <code act> | ||
+ | fulladder fa[10]; | ||
+ | (i : 9 : fa[i].co=fa[i+1].ci; | ||
+ | </ | ||
+ | |||
+ | The parentheses are used to group the body of the loop. '' | ||
+ | the dummy variable, and it ranges from zero to eight in this | ||
+ | example. The '';'' | ||
+ | the body of the loop. In general if only one integer is specified for | ||
+ | the range, the variable ranges from zero to one less than the integer. | ||
+ | |||
+ | The conditional statement uses the guarded command notation. They are | ||
+ | used for describing the edge of repetitive structures, during | ||
+ | recursive constructions, | ||
+ | based on parameters. The following is an example where odd-numbered | ||
+ | indices of '' | ||
+ | indices are connected to '' | ||
+ | |||
+ | <code act> | ||
+ | bool x[10], y[10], z[10]; | ||
+ | |||
+ | ( i : 10 : | ||
+ | [ (i%2) = 0 -> x[i] = y[i]; | ||
+ | [] (i%2) = 1 -> x[i] = z[i]; | ||
+ | ] | ||
+ | ) | ||
+ | </ | ||
+ | |||
+ | ===== Scoping ===== | ||
+ | |||
+ | In the second definition of '' | ||
+ | defined within the body of the type definition. Therefore, this variable | ||
+ | is local to the type, and cannot be accessed by any construct outside | ||
+ | the body of the type. Different instances of '' | ||
+ | different copies of '' | ||
+ | created a dualrail channel '' | ||
+ | has no relation to the '' | ||
+ | |||
+ | The ACT language has two scopes: the global scope, and the scope | ||
+ | within the entity being defined. Ports of types have the same scope as | ||
+ | items defined within the body of the type. However, ports are special | ||
+ | in that they can also be accessed from outside the type using | ||
+ | dot-notation. | ||
+ | |||
+ | |||
+ | ACT does not have a special ' | ||
+ | be created by simply defining them in the outer-most scope. For | ||
+ | instance, ACT files will tend to begin with | ||
+ | |||
+ | <code act> | ||
+ | bool Reset, | ||
+ | </ | ||
+ | |||
+ | This permits the names '' | ||
+ | throughout the ACT file. | ||
+ | |||
+ | ===== Namespaces ===== | ||
+ | Complex projects involve a large number of ACT files, including | ||
+ | shared libraries and blocks designed by different people. One could | ||
+ | easily envision a situation where a particular identifier name is used by | ||
+ | multiple designers to describe different processes. | ||
+ | |||
+ | To keep names of processes, channels, and types separate for different | ||
+ | parts of a design, ACT provides the notion of a | ||
+ | // | ||
+ | specific namespace. In all our examples so far, this was the | ||
+ | (implicit) global namespace (named '' | ||
+ | |||
+ | The following example creates a namespace '' | ||
+ | within the namespace. | ||
+ | |||
+ | <code act> | ||
+ | namespace lib { | ||
+ | export defchan a1of2 <: chan(bool) (bool d0,d1,a) { ... } | ||
+ | } | ||
+ | |||
+ | lib::a1of2 d; | ||
+ | </ | ||
+ | |||
+ | We have created a channel definition of type '' | ||
+ | '' | ||
+ | First, the directive '' | ||
+ | type is in fact visible outside the namespace scope. This is why we | ||
+ | can use the notation '' | ||
+ | rationale for this is that one might have created a library, but might | ||
+ | only want a few types exposed (e.g. top-level cells). By default, a | ||
+ | type is not visible outside a namespace unless it is explicitly | ||
+ | '' | ||
+ | global instances of processes. This means that the only legal items | ||
+ | within a namespace are namespace directives, type definitions, | ||
+ | global data/ | ||
+ | |||
+ | Namespaces can be nested. For instance, we could have: | ||
+ | |||
+ | <code act> | ||
+ | namespace processor { | ||
+ | |||
+ | namespace lib { | ||
+ | | ||
+ | } | ||
+ | |||
+ | lib::a1of2 d; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | In this example, '' | ||
+ | within namespace '' | ||
+ | the '' | ||
+ | one level up in the namespace hierarchy. Hence, although the channel | ||
+ | '' | ||
+ | '' | ||
+ | |||
+ | <code act> | ||
+ | namespace processor { | ||
+ | |||
+ | namespace lib { | ||
+ | | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | processor:: | ||
+ | </ | ||
+ | < | ||
+ | -[ERROR]-> | ||
+ | | ||
+ | </ | ||
+ | |||
+ | If this channel needs to be visible | ||
+ | outside the '' | ||
+ | exporting the namespace itself. | ||
+ | |||
+ | <code act> | ||
+ | namespace processor { | ||
+ | |||
+ | export namespace lib { | ||
+ | | ||
+ | } | ||
+ | |||
+ | } | ||
+ | processor:: | ||
+ | </ | ||
+ | |||
+ | In this approach, every element that is exported from namespace | ||
+ | '' | ||
+ | |||
+ | Something that is a little unusual is that a type cannot be accessed | ||
+ | within a sub-namespace unless it is exported. For instance, in the | ||
+ | example above, if '' | ||
+ | '' | ||
+ | '' | ||
+ | '' | ||
+ | namespaces apart from the one in which the type was defined. | ||
+ | |||
+ | A namespace can have global variables. The global variables described | ||
+ | earlier were simply a special case corresponding to the namespace | ||
+ | '' | ||
+ | a namespace might have a reset signal that is global to the namespace | ||
+ | only, and which is generated using some logic defined within the | ||
+ | namespace. | ||
+ | |||
+ | ===== Importing ACT files ===== | ||
+ | |||
+ | The keyword '' | ||
+ | ACT file can begin with a sequence of '' | ||
+ | If the same file is imported twice within the same scope, chances are | ||
+ | that some types would be multiply defined. To avoid such problems, | ||
+ | imports of files which have already been imported within the same | ||
+ | scope or an outer scope are ignored. Therefore, always use | ||
+ | '' | ||
+ | |||
+ | <code act> | ||
+ | import " | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | '' | ||
+ | first, then in the colon-separated path specified by '' | ||
+ | and finally in '' | ||
+ | |||
+ | A typical project would contain multiple files, each possibly having | ||
+ | their own namespace. Namespaces can also have global variables, so | ||
+ | importing a namespace automatically creates an instance of the global | ||
+ | variables from that namespace, and from any sub-namespace that was also | ||
+ | imported. | ||
+ | |||
+ | There are a few things that might create issues in such a situation. | ||
+ | First, duplicate namespaces might exist, especially when re-using old | ||
+ | files. For instance, suppose we have two files: '' | ||
+ | '' | ||
+ | definitions that are useful. Importing both would result in the union of | ||
+ | the namespaces, and could create naming conflicts (e.g. multiple | ||
+ | definition of types having the same name---an error). To solve this | ||
+ | problem, one can do the following: | ||
+ | |||
+ | <code act> | ||
+ | import " | ||
+ | open lib -> lib1; | ||
+ | import " | ||
+ | open lib -> lib2; | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | has occured, there cannot be any naming conflicts. This version of | ||
+ | '' | ||
+ | eliminated. | ||
+ | |||
+ | A second issue is one that is more about convenience. Consider a | ||
+ | project that has many different people working on it, each in their | ||
+ | own namespace to avoid naming conflicts. This situation can result in | ||
+ | very long type names. Plus it would be more bookkeeping to have to | ||
+ | create a test environment for the types within, say, | ||
+ | '' | ||
+ | because not all types might be exported! In this case we can say: | ||
+ | |||
+ | <code act> | ||
+ | import " | ||
+ | open processor:: | ||
+ | |||
+ | a1of2 d; | ||
+ | </ | ||
+ | |||
+ | This version of the '' | ||
+ | functions: (i) it adds '' | ||
+ | types, and (ii) it allows one to access all types within the | ||
+ | namespace, not just the ones that are exported (including types within | ||
+ | nested namespaces). Note that this '' | ||
+ | all types cannot be uniquely resolved. | ||
+ | |||
+ | The sequence of '' | ||
+ | at the beginning of an ACT file. | ||
+ | |||
+ | A second version of import uses namespaces directly, but requires that | ||
+ | ACT files be placed in locations that match the namespace | ||
+ | hierarchy. The import statement | ||
+ | |||
+ | <code act> | ||
+ | import processor:: | ||
+ | </ | ||
+ | |||
+ | is equivalent to the following: | ||
+ | |||
+ | <code act> | ||
+ | import " | ||
+ | </ | ||
+ | |||
+ | It assumes that the file '' | ||
+ | '' | ||
+ | '' | ||
+ | |||