Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
language:namespaces [2019/04/18 14:27]
rajit created
language:namespaces [2022/05/13 08:46] (current)
rajit
Line 10: Line 10:
 ===== Creating a namespace ===== ===== Creating a namespace =====
  
 +A namespace is created by using the ''namespace'' construct.
 +
 +<code act>
 +namespace lib {
 +...
 +export defproc buffer (a1of2? l; a1of2! r) { ... }
 +...
 +}
 +</code>
 +
 +The process ''buffer'' has been created in the namespace
 +''lib'', and it's fully qualified name is
 +''::lib::buffer''. This syntax is similar to the one used by
 +C++.
 +
 +An ACT type or instance is first evaluated in the current
 +namespace; if it doesn't exist in the current namespace, then the
 +global namespace is searched next.
 +
 +A namespace typically contains user-defined types. By default, these
 +types are only visible within the current namespace. To allow a type
 +to be visible in any other namespace, it must be prefaced by the
 +''export'' keyword (as above).
 +
 +A namespace can also contain another namespace. However, these
 +namespaces do not have special privileges. An example of nested
 +namespaces is shown below.
 +
 +<code act>
 +namespace datapath {
 +    export defproc bus_interface(...) { ... }
 +    namespace adder {
 +      export defproc alu(...) {
 +        bus_interface b;
 +      }
 +    }
 +    ...
 +}
 +</code>
 +
 +Nesting does not give a namespace special permissions; if the
 +''bus_interface'' definition was not ''export''ed, then the
 +namespace ''adder'' within it would not be able to reference
 +''bus_interface''. However, notice that the type
 +''bus_interface'' within ''alu'' did not require its fully
 +qualified name, due to the fact that the definition is in scope due to
 +nesting.
 +
 +''alu'' cannot be referenced from the global namespace using
 +''datapath::adder::alu''. Although ''alu'' is exported from the
 +namespace ''datapath::adder'', the ''export'' directive only
 +exports the definition one level up. To export this another level out,
 +the entire namespace ''adder'' can be exported as follows:
 +
 +<code act>
 +namespace datapath {
 +    export defproc bus_interface(...) { ... }
 +    export namespace adder {
 +      export defproc alu(...) {
 +        bus_interface b;
 +      }
 +    }
 +    ...
 +}
 +</code>
 +
 +Now ''datapath::adder::alu'' can be accessed from the global
 +namespace.
 +
 +//Namespace globals// are instances that are defined outside any type
 +definition. While the ''Global'' namespace can have any instances
 +or other constructs used to construct circuits, other namespaces can
 +only have global data types or channels---i.e. no circuits.
 +
 +===== Importing namespaces =====
 +
 +There are two mechanisms to import other files in ACT. These 
 +imports have to be at the beginning of an ACT file. If the same
 +file is imported twice within the same scope, ACT automatically
 +skips the second import.
 +
 +The basic form of import statement is shown below:
 +
 +<code act>
 +import "channel.act";
 +...
 +</code>
 +
 +This import searches for a file called ''channel.act'' to be read as
 +part of the ACT design. ACT has multiple mechanisms that can be used
 +to specify search paths for the files that an import statement can access:
 +
 +   * the current directory: if the file is located in the current working directory, then it is used.
 +   * the colon-separated path specified by ''$ACT_PATH'': The ACT_PATH environment variable can be used to specify a colon-separated list of directories. These are searched for the file specified in the import statement after the current working directory. This is typically used to specify project-specific configuration.
 +   * ''$ACT_HOME/act'': This path is used for system ACT files, shared across multiple projects.
 +
 +
 +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::lib;
 +</code>
 +
 +is equivalent to the following:
 +
 +<code act>
 +import "processor/lib/_all_.act";
 +</code>
 +
 +It assumes that the file ''_all_.act'' in the directory
 +''processor/lib'' contains all the definitions corresponding to the
 +''processor::lib'' namespace. More precisely, an import statement
 +
 +<code act>
 +import foo;
 +</code>
 +
 +would do the following:
 +  * Look for ''foo/_all_.act'' using the search paths specified earlier;
 +  * If unsuccessful, then look for ''foo.act''
 +  * If unsuccessful, report an error
 +
 +After the import, the specified namespace is checked to see if it exists. If not, an error will be reported.
 +
 +
 +===== Opening namespaces =====
 +
 +If there are two different files that define the same namespace (say defined in multiple projects), importing both the files may result in type conflicts. Consider a scenario where we have two ''lib'' namespaces defined for two different projects, but  both have useful circuits that we would like to re-use in a third project. If ''lib1.act'' and ''lib2.act'' both contain namespace ''lib'', importing both would take the union of the definitions in the two files, potentially resulting in errors.
 +
 +To resolve this issue, ACT provides a way to rename a namespace that has been imported.
 +
 +<code act>
 +import "lib1.act";
 +open lib -> lib1;
 +import "lib2.act";
 +open lib -> lib2;
 +</code>
 +
 +In this example, the ''open'' construct enables one to rename a namespace. Once this
 +has occured, there cannot be any naming conflicts. This version of ''open'' is a renaming construct; after the open statement, the old name for the namespace is 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,
 +''processor::lib''---not just because of the long type names, but
 +because not all types might be exported! In this case we can say:
 +
 +<code act>
 +import "lib.act";
 +open processor::lib;
 +
 +a1of2 d;
 +</code>
 +
 +This version of the ''open'' directive has two
 +functions: (i) it adds ''processor::lib'' to the search path for
 +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 ''open'' statement will fail if
 +all types cannot be uniquely resolved. Note that the sequence of ''open'' and ''import'' statements can only be
 +at the beginning of an ACT file.