Step 7: Inverters ################# .. include:: /header.inc .. vim:filetype=rst spell: Our first real part is the Inverter. Formally, this device is a hardware implementation of George Boole's "not" operation. This device has a single input pin, and a single output pin. All it does inside is read the input signal, flip it (complement) and write that new signal back out on the output pin. How hard can this be to implement? For our first real device, the input will be a single bit (a zero or a one). The output will also be a single bit. Formally, we could handle more bits, and compliment each bit individually, producing an output result. We will do that later. For now, we will stick with this single bit version. C++ Inheritance *************** To implement this device we need to set up a class that "inherits" everything we defined in the generic component class. Essentially, this new class will have all the capabilities of the component class plus new features we add in in this derived (child) class. Inheritance is a complex topic in C++, but in our case all we really need to do is provide a new constructor that sets up our new part, and a new version of the ``tick`` routine that does the real work we need. We will set up the required input and output pins in the constructor for this class, so objects we create later will be ready to run! Inverter Class Specification **************************** Here is our new part header file: .. literalinclude:: code/cpu-factory5/include/Inverter.h :linenos: :caption: include/Inverter.h The "inheritance" we are doing here can be seen on line 5. The normal ``class`` declaration line has new stuff after the class name. We place a colon, an access specifier (``public`` in this case), then the name of the class we are extending. Of course, we need to include the header file for that generic class so this name will be recognized by the compiler. Essentially, that first line in the constructor will pass on the Inverter name to the constructor from the Component class, where that name will be registered. Inheritance lets you add new attributes or methods, or override methods in the base class with new methods in the derived class. We cannot delete things from the base class. Testing the Inverter ******************** Testing the inverter simply involves checking that it does the work needed when that ``tick`` routine is called. All we need to do is set the input pin to some value (remember that this is a single bit input, so the only legal values are zero and one). Then we call the ``tick`` routine and make sure the output changes to the opposite of the set value. Here is the code: .. literalinclude:: code/cpu-factory5/tests/test_inverter.cpp :linenos: :caption: tests/test_inverter.cpp Inverter Implementation *********************** I suspect you can figure out the implementation code for this device. Since the hard work has already been taken care of in the generic ``Component`` class, all we need here is a new constructor that sets up the required pins, and the new ``tick`` method: .. literalinclude:: code/cpu-factory5/lib/Inverter.cpp :linenos: :caption: lib/Inverter.cpp .. note:: Look closely at that single line that "flips" the input bit. This is called a "C++ Conditional Expression". Basically is has this form: .. code-block:: text expr1 ? expr2 : expr3; the statement returns the result of evaluating expr2 if evaluating expr1 results in ``true``, otherwise it returns the result on evaluating expr3. It is just a shortened up if-then-else piece of code. Running the tests now shows that we have a real, admittedly simple, digital part to play with. Let's set up a simple circuit and see if we can make something work!