The easiest way to get started with libLCS is to start building simple circuits using the off-the-shelf logic gates provided in libLCS. All circuit elements, which have an input and an output, will be called as modules when reffered to in the context of libLCS. Since logic gates also have a well defined input and output, they are called as modules in libLCS, unlike in Verilog where logic gates are reffered to as primitives. All logic gates, except the NOT gate, are provided as class templates in libLCS. Each class template takes one parameter which indicates the number of inputs to the gate. Since a NOT gate can have only one input, it is not provided as a class template.
The cable/wire connections between modules are done using busses. Busses are also provided as class templates taking one template parameter. The template parameter indicates the width (or number of lines) of the bus. In this section we will go over building a trivial example circuit. More complicated examples can be found in the Basic Examples section.
a
and b
be inputs to our circuit. Let s
be the output. Then, the boolean function for s
is:
s = ab' + a'b
Hence, to generate s
from a
and b
, we require two 2-input AND gates, one 2-input OR gate, and two NOT gates. The circuit diagram is as follows:
Each node in the above circuit translates to a bus in case of libLCS. As marked in the circuit, seven single-line busses are required to build the circuit. The class template to generate bus classes is defined in the header file lcs/bus.h
. All classes in libLCS are defined in the namespace lcs
, and so is the bus class template lcs::Bus
. The first step in our program is to declare 7 single-line bus objects. This is done as follows.
lcs::Bus<1> a, b, a_, b_, p1, p2, s; // The bus names are same as // that in the diagram above.
Note the use of a template parameter of 1 in the above declaration. After declaring the busses in the circuit, the next step is to initialise the modules in the circuit. The initialisation of the NOT gates is done as follows. (The NOT gates are defined in the header file lcs/not.h
.)
lcs::Not ng1(a_, a), ng2(b_, b);
Notice the order of arguments being passed to the NOT gate constructors. Constructors for all off-the-shelf gates provided in libLCS require two arguments: The output bus as the first argument, and the input bus as the second argument.
Next, we shall initialise the AND gates of our circuit. The AND gates are defined in the header file lcs/and.h
. A two input AND gate would require a two-line bus as input. However, we have defined only single-line busses. libLCS provides an overloaded operator*
with which one can concatenate two busses to form wider busses. We will make use of this concatenation operator to initialise the two AND gates required for our circuit.
lcs::And<2> ag1(p1, a*b_), ag2(p2, a_*b); // Notice the use of the template parameter 2. // Also, the * operator is used to concatenate // single-line busses into two-line busses.
The two input OR gate is initialised is a similar manner.
lcs::Or<2> og(s, p1*p2);
With the above OR gate initialisation, we have built our complete circuit. We now need a way to test it. For this, libLCS provides a class lcs::Tester
defined in the header file lcs/tester.h
. It is also a class template requiring two integer template parameters. A lcs::Tester
object will have to be initialised by passing two lcs::Bus
objects to the constructor. The first argument should be the input bus of our circuit, and the second argument the output bus of our circuit. When a lcs::Tester
object is run using the lcs::Tester::run
function, all possible line states are written on to the input bus and the corresponding output displayed on the std::stdout
device. Hence, for out circuit, we will make use of the lcs::Tester
class as follows.
lcs::Tester<2, 1> tester(a*b, s); // The first template parameter 2 indicates the bus width of // the input bus to our circuit. The second parameter 1 indicates // the bus width of the output bus of our circuit. tester.run();
The entire/complete program which simulates our circuit is as follows.
#include <lcs/bus.h> #include <lcs/not.h> #include <lcs/and.h> #include <lcs/or.h> #include <lcs/tester.h> int main() { lcs::Bus<1> a, b, a_, b_, p1, p2, s; lcs::Not ng1(a_, a), ng2(b_, b); lcs::And<2> ag1(p1, a*b_), ag2(p2, a_*b); lcs::Or<2> og(s, p1*p2); lcs::Tester<2, 1> tester(a*b, s); tester.run(); return 0; }
When the above program is compiled and run, the following output will be obtained. (See this page for information on compiling a program which uses libLCS.)
Test started... ------|----- 00 | 0 ------|----- 01 | 1 ------|----- 10 | 1 ------|----- 11 | 0 ------|----- Test performed successfully. The results should be verified!