====== Creating a library of building blocks ====== A library can be created using pre-designed building blocks and use them in hierarchical designs. This can be achieved using keyword ''import''. In this case, ACT file begins with a sequence of "import" statements. The "import" looks for file in the current directory first, then in the colon-separated path specified by ''$ACT_PATH'', and finally in ''$ACT_HOME/act''. ACT files can be imported in two ways: (a) For simple projects, design files containing building blocks can be imported using keyword ''import''. For example, the ''gates.act'' file contains basic logic gates. defproc nand2 (bool? a,b; bool! y) { prs { a & b => y- } } defproc and2 (bool? a,b; bool! y) { bool _y; prs { a & b => _y- _y => y- } } defproc or2 (bool? a,b; bool! y) { bool _y; prs { a | b => _y- _y => y- } } This file can be imported in a new ACT file ''xor2.act'' for creating XOR gate using basic logic gates. import "gates.act"; defproc xor2 (bool? a,b; bool! y) { bool y1, y2; nand2 N1 (a,b,y1); or2 O1 (a,b,y2); and2 A1 (y1,y2,y); } xor2 x; (b) For complex projects involving a large number of ACT files, importing libraries can become complicated. For example, a project can have multiple ACT files containing different implementation of a design with same process name or different channels with same name. To keep names of process, channel, and types separate in such cases, ACT provides the option of namespace ([[language:introduction#namespaces|ACT namespaces]]). The following example creates a namespace gates in file ''gates.act'' and defines process for basic logic gates within the namespace. namespace gates { export defproc xor2 (bool? a,b; bool! y) { bool _a, _b; prs{ a => _a- b => _b- (a & b) | (_a & _b) => y- } } export defproc and2 (bool? a,b; bool! y) { bool _y; prs { a & b => _y- _y => y- } } export defproc or2 (bool? a,b; bool! y) { bool _y; prs { a | b => _y- _y => y- } } } As shown below, this library is imported in a new ACT file ''adder.act'' to design full adder using logic gates defined in the library. import "gates.act"; defproc adder (bool? a,b,ci; bool! s,co) { bool y1,y2,y3; gates::xor2 X1(a, b, y1); gates::and2 A1(a,b,y2); gates::xor2 X2 (y1,ci,s); gates::and2 A2(y1,ci,y3); gates::or2 O1(y2,y3,co); } adder FA; Finally, ACT supports another import format that is similar to those provided by object-oriented languages like Python and Java. Since ''gates.act'' defines the namespace ''gates'', it can be imported as follows: import gates; defproc adder (bool? a,b,ci; bool! s,co) { bool y1,y2,y3; gates::xor2 X1(a, b, y1); gates::and2 A1(a,b,y2); gates::xor2 X2 (y1,ci,s); gates::and2 A2(y1,ci,y3); gates::or2 O1(y2,y3,co); } adder FA; The ''import'' statement looks for ''gates.act'' (details are in [[language:namespaces|Namespaces]]), and imports it if it is found. It also checks that the namespace ''gates'' exists after the import. Finally, if you are going to be using the ''gates'' namespace a lot, it can be added to the search path used to find type definitions as follows. import gates; open gates; defproc adder (bool? a,b,ci; bool! s,co) { bool y1,y2,y3; xor2 X1(a, b, y1); and2 A1(a,b,y2); xor2 X2 (y1,ci,s); and2 A2(y1,ci,y3); or2 O1(y2,y3,co); } adder FA; ===== Simulating with prsim script ===== Run simulation in prsim with script as: prsim adder.act < adder.scr You could also run ''prsim'' and then source script as: prsim adder.act (Prsim) source adder.scr where ''adder.scr'' file contains the following commands: initialize set fa.a 0 set fa.b 0 set fa.ci 0 cycle get fa.a get fa.b get fa.ci get fa.s get fa.co set fa.a 0 set fa.b 0 set fa.ci 1 cycle get fa.a get fa.b get fa.ci get fa.s get fa.co