{"cells":[{"cell_type":"markdown","metadata":{"id":"ASc0nYpw6D40"},"source":["# PyCircPL - Python Logic Circuit Programming Language \n","\n","\n","\n","* \n","Link to GITHUB repository\n","\n","* \n","Link to the the Google Colaboratory notebook\n","\n","\n"," * The Google Colaboratory notebook has the advantage\n"," that you can run PyCircPL code from it without having to\n"," install PyCircPl or even Python on your local system.\n"," * You first need to copy it to your google drive (or github repository)\n"," * You can also dowload it to your local device and open it as\n"," a Jupyter notebook (if you have it installed with your Python)."]},{"cell_type":"markdown","metadata":{"id":"re0JUU526D47"},"source":["## Installing the PyCircPL package\n","* The **PyCircPL** package can be installed on your local system by running the following command from the command line\n","```\n","pip install pycircpl\n","```\n","* Or you may try running one of the following commands from this notebook.\n","* If you are running it from a Jupyter notebook on your local system, then it will be installed on your device. "]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"elapsed":6035,"status":"ok","timestamp":1668773330003,"user":{"displayName":"Samy Zafrany","userId":"01281551573032788195"},"user_tz":-120},"id":"H8Trabf46D47","outputId":"fe0819bd-f061-4d97-945f-a07a9ddfde93"},"outputs":[{"output_type":"stream","name":"stdout","text":["Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n","Collecting pycircpl\n"," Downloading pycircpl-1.1.tar.gz (2.2 kB)\n","Building wheels for collected packages: pycircpl\n"," Building wheel for pycircpl (setup.py) ... \u001b[?25l\u001b[?25hdone\n"," Created wheel for pycircpl: filename=pycircpl-1.1-py3-none-any.whl size=1914 sha256=2b17b91d8b346628045b2fdb55ff13f846d76e9767c72369dca41d035feea87f\n"," Stored in directory: /root/.cache/pip/wheels/a3/2d/3b/c702335f765a1d7dfba13c8b049fbcc51bb63fabfe3a5c1938\n","Successfully built pycircpl\n","Installing collected packages: pycircpl\n","Successfully installed pycircpl-1.1\n"]}],"source":["# To install from this notebook, run this cell.\n","%pip install pycircpl\n","# This should also work:\n","# !pip install --upgrade pycircpl\n","\n","# After installation, you have to restart this notebook.\n","# Make sure to comment the %pip or !pip lines above to avoid reinstall each time you run this notebook.\n","\n","# To uninstall the package use:\n","#%pip uninstall pycircpl\n","# or\n","# !pip uninstall pycircpl"]},{"cell_type":"markdown","metadata":{"id":"5hIXG9SE6D48"},"source":["* **After installation, you may need to restart this notebook.**"]},{"cell_type":"markdown","metadata":{"id":"rlDvlU9I6D48"},"source":["## Loading the PyCircPL package\n","* After installing the **PyCircPL** package, you need to import\n"," it. \n","* The following command imports **PyCircPL** to your Python interpreter."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"ZaIr21bT6D49"},"outputs":[],"source":["from pycircpl import *"]},{"cell_type":"markdown","metadata":{"id":"kD35YCtJ6D4-"},"source":["## Introduction\n","\n","* **PyCircPL** is a simple Python package for simulating\n"," Logic Circuits specifically designed for educational\n"," use in introductory computation and\n"," digital logic college courses.\n","* As such, it was primarily tuned for simplicity, readability,\n"," convenience, and fast learning curve.\n"," * Less for speed or industrial production.\n","* It is a lightweight package especially designed for\n"," small to medium scale circuits, such as those that are studied\n"," in introductory academic courses on the theory of computation\n"," and electronic digital design.\n","* Its main characteristic is that a digital circuit or a boolean\n"," formula can be easily defined by a series of simple Python commands,\n"," rather than an external static language.\n","* So, the only requirement is basic knowledge of the\n"," Python programming language, with a little programming skill.\n","* Experienced Python programmers can probably benefit a lot\n"," more from this package.\n","* It can be a useful companion for theoretical courses on\n"," computation models and languages who wish also to engage\n"," the students with some programming experience and skills.\n"," * It is planned to be used in such a course by the author\n"," (Hebrew book at http://samyzaf.com/afl.pdf).\n"," * It enables students to easily model and experiment with\n"," * Typical logic circuit design\n"," * Logic Circuit or Boolean formula Validation\n"," * Logic Circuit Testing\n"," * Logic problem solving\n","* It does provide an opportunity for students to develop\n"," and practice some programming skills while covering\n"," the theoretical computation course.\n","* In this tutorial, we will cover:\n"," 1. Basic usage of PyCircPL for simulating\n"," Logic Circuits or Boolean formulas.\n"," 2. A short survey of the commands and tools of the **PyCircPL** package.\n"," 3. Advanced usage of PyCirc for experienced Python\n"," programmers (TODO)."]},{"cell_type":"markdown","metadata":{"id":"qSfarxQ-6D4_"},"source":["## Example 1: Simulating the circuit FOO\n","* We start with a very simple logic circuit which we call **\"FOO\"**\n"," whose **PyCirc Diagram** is given below\n"," * Inputs gates: $x_1$, $x_2$, $x_3$\n"," * Output gates: $y_1$, $y_2$\n"," * Logic formula: $(y_1, y_2) = (x_1 \\land x_2 , \\ \\neg x_3)$\n"," * See https://www.samyzaf.com/pycirc/pycirchdl.html for detailed\n"," information on PyCirc diagrams. \n","\n"," \n","\n","* Here is the **PyCircPL code** for modeling this circuit:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"TxVm9Pf-6D5B"},"outputs":[],"source":["def FOO(x1, x2, x3):\n"," g1 = AND(x1, x2)\n"," g2 = NOT(x3)\n"," y1 = g1\n"," y2 = g2\n"," return y1, y2"]},{"cell_type":"markdown","metadata":{"id":"kU-kvZpn6D5B"},"source":["* Notic that this is a **pure Python code**!\n"," * So you need to **run** its cell in order to execute it.\n","\n","* A circuit definition starts with the stabdard Python keyword `def`\n"," which is used to define a Python function.\n","* The function name is identical to the circuit name `FOO`.\n","* The function argument list is identical to the circuit boolean\n"," input list `x1`, `x2`, `x3`.\n","* The function output list (in the last `return` statement) is\n"," identical to the circuit output list.\n"," \n","* Note that we could make the definition shorter by removing the\n"," two intermediate variable `g1` and `g2`, but their presence\n"," keeps a resemblance with the circuit diagram.\n","\n","* We ephasize again: the above definition of **FOO** is\n"," a **pure Python function**!\n","* This means that you can use in any othe Python code and\n"," in other programs/scripts for building new circuit functions.\n","\n","* Here is a simple example which computes the circuit for the input\n","```Python\n","x1 = 1\n","x2 = 1\n","x3 = 0\n","```"]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"elapsed":53,"status":"ok","timestamp":1668773330004,"user":{"displayName":"Samy Zafrany","userId":"01281551573032788195"},"user_tz":-120},"id":"6KCfVXDzvGqj","outputId":"83f7172b-0726-42f4-a2f1-9907d2aeb214"},"outputs":[{"output_type":"stream","name":"stdout","text":["y1=1\n","y2=1\n"]}],"source":["y1,y2 = FOO(1,1,0)\n","print(f\"y1={y1}\")\n","print(f\"y2={y2}\")"]},{"cell_type":"markdown","metadata":{"id":"bWQWOaJ54g-o"},"source":["Here is a more sophisticated example for Pyhton programmers for\n","generating the **Truth Table** of `FOO`.\n","That is, all possible outputs."]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"elapsed":48,"status":"ok","timestamp":1668773330005,"user":{"displayName":"Samy Zafrany","userId":"01281551573032788195"},"user_tz":-120},"id":"MbA3AgKw4fb4","outputId":"b0ff81d0-b4ec-49df-bbbf-fd4324487e69"},"outputs":[{"output_type":"stream","name":"stdout","text":["FOO(0,0,0) = 0, 1\n","FOO(0,0,1) = 0, 0\n","FOO(0,1,0) = 0, 1\n","FOO(0,1,1) = 0, 0\n","FOO(1,0,0) = 0, 1\n","FOO(1,0,1) = 0, 0\n","FOO(1,1,0) = 1, 1\n","FOO(1,1,1) = 1, 0\n"]}],"source":["for x1 in [0,1]:\n"," for x2 in [0,1]:\n"," for x3 in [0,1]:\n"," y1,y2 = FOO(x1,x2,x3)\n"," print(f\"FOO({x1},{x2},{x3}) = {y1}, {y2}\")"]},{"cell_type":"markdown","metadata":{"id":"KPAdr0VY6D5C"},"source":["* After successful design of a circuit function such as **FOO**,\n"," it can be placed in a single python code file and loaded\n"," as usual with the Python `import` command.\n"," "]},{"cell_type":"markdown","metadata":{"id":"oHjloVC56D5C"},"source":["* You may want to copy the function library that we use in this\n"," notebook to your local pc.\n","* Here is a link to the Python file that contains all functions\n"," that we use in this notebook:\n"," * [Click to download functions.py](https://samyzaf.com/pycirc/functions.py)\n"]},{"cell_type":"markdown","metadata":{"id":"80ERuNF06D5D"},"source":["## Example 2: Simulating the circuit FRED\n","* Here is an example of cell called **FRED** which uses an instance of the cell **FOO** as one of its building blocks.\n","* Note that this cell is using a gate of type `FOO` whose function\n"," we defined in Example 1 above.\n"]},{"cell_type":"markdown","metadata":{"id":"B5eHBew46D5E"},"source":["\n","\n","\n"," \n","\n"]},{"cell_type":"markdown","metadata":{"id":"98xqznYqBT1B"},"source":["* It is easy to write its corresponding function.\n","* Note that the function `FOO` is used in the function `FRED`."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"Vb0U-NC-BTDq"},"outputs":[],"source":["def FRED(x1, x2):\n"," g0 = 0\n"," y1,y2 = FOO(x1,x2,g0)\n"," return y1,y2"]},{"cell_type":"markdown","metadata":{"id":"Ko9IcHhT6D5E"},"source":["## Example 3: The circuit HAM\n","* The follwing cell **HAM** contains two gates of type **FOO**\n"," and two gates of type **XOR3**.\n","* The **XOR3** cell is a typical **xor** cell with 3 input\n"," gates.\n","* It also contains one gate of type **NOT**.\n","\n"," "]},{"cell_type":"markdown","metadata":{"id":"TmMuARGzI9VV"},"source":["* Here is a **PyCircPL code** for modeling this cell.\n","* Notice lines 2 and 3 of the code that use the function `FOO`."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"gFwgNmlj6D5F"},"outputs":[],"source":["# CELL: HAM\n","# This cell is using the FOO cell which we defined earlier\n","# \"XOR\" is a basic function in PyCircPL\n","\n","def HAM(x1,x2,x3,x4):\n"," g1_y1, g1_y2 = FOO(x1,x3,x2)\n"," g2_y1, g2_y2 = FOO(x3,x4,x4)\n"," g3_y = XOR(g1_y2, g1_y1, g2_y2)\n"," g4_y = NOT(g1_y2)\n"," g5_y = XOR(g1_y2, g2_y1, g2_y2)\n"," y1 = g3_y\n"," y2 = g4_y\n"," y3 = g5_y\n"," return y1, y2, y3"]},{"cell_type":"markdown","metadata":{"id":"Kli6pX9TQPnu"},"source":["* Here is a simple code for generating the truth table of `HAM`.\n","* We use the `product` utility from the `itertools` module (which is\n"," automatically loaded by pycircpl) to generate all the possible\n"," combinations of 4 boolean values."]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"elapsed":43,"status":"ok","timestamp":1668773330006,"user":{"displayName":"Samy Zafrany","userId":"01281551573032788195"},"user_tz":-120},"id":"GNAOYA5rPprs","outputId":"2d310259-33a1-4e6a-e522-a36675818d10"},"outputs":[{"output_type":"stream","name":"stdout","text":["HAM(0, 0, 0, 0) = 0, 0, 0\n","HAM(0, 0, 0, 1) = 1, 0, 1\n","HAM(0, 0, 1, 0) = 0, 0, 0\n","HAM(0, 0, 1, 1) = 1, 0, 0\n","HAM(0, 1, 0, 0) = 1, 1, 1\n","HAM(0, 1, 0, 1) = 0, 1, 0\n","HAM(0, 1, 1, 0) = 1, 1, 1\n","HAM(0, 1, 1, 1) = 0, 1, 1\n","HAM(1, 0, 0, 0) = 0, 0, 0\n","HAM(1, 0, 0, 1) = 1, 0, 1\n","HAM(1, 0, 1, 0) = 0, 0, 0\n","HAM(1, 0, 1, 1) = 0, 0, 0\n","HAM(1, 1, 0, 0) = 1, 1, 1\n","HAM(1, 1, 0, 1) = 0, 1, 0\n","HAM(1, 1, 1, 0) = 0, 1, 1\n","HAM(1, 1, 1, 1) = 1, 1, 1\n"]}],"source":["for x1,x2,x3,x4 in product([0,1], repeat=4):\n"," y1,y2,y3 = HAM(x1,x2,x3,x4)\n"," print(f\"HAM({x1}, {x2}, {x3}, {x4}) = {y1}, {y2}, {y3}\")"]},{"cell_type":"markdown","metadata":{"id":"wx5alQ_geuZy"},"source":["## Example 4: Simulating 1-bits counter circuit\n","* The following circuit (given simple digraph represantation) counts\n"," the number of 1-bits of its input list.\n","\n",""]},{"cell_type":"markdown","metadata":{"id":"TpJk_TCJjI_t"},"source":["* This is the correponging Python function:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"S8oXfISFi2Q8"},"outputs":[],"source":["def COUNT3(x1, x2, x3):\n"," g1 = AND(x1, x2)\n"," g3 = XOR(x1, x2)\n"," g2 = AND(x3, g3)\n"," g4 = XOR(x3, g3)\n"," g5 = OR(g1, g2)\n"," y1 = g5\n"," y2 = g4\n"," return y1, y2\n"]},{"cell_type":"markdown","metadata":{"id":"m82iw5f6E5KK"},"source":["* Converting the graph diagram to the corresponding Python code\n"," is an easy task.\n","* Each non-input gate `g1`, `g3`, `g2`, `g4`, `g5`, `y1`, `y2`,\n"," is converted to its corresponding Python statement by simply\n"," applying its logical operator on its inputs.\n","* Note that gate order is critical! You have to go from low to high depth.\n","* For example, gate variable `g3` must be defined befor `g2` since\n"," it is an input to `g2`!"]},{"cell_type":"markdown","metadata":{"id":"b6Ck-hzEFsfa"},"source":["* For example, here is what happens we apply `COUNT3` on the input list\n","```\n","x1 = 1 ; x2=0 ; x3 = 1\n","```"]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"elapsed":40,"status":"ok","timestamp":1668773330008,"user":{"displayName":"Samy Zafrany","userId":"01281551573032788195"},"user_tz":-120},"id":"6ryKhBpOpr7n","outputId":"e3b0f26d-77c6-44a9-f0eb-1441cc2c6f5f"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["(1, 0)"]},"metadata":{},"execution_count":10}],"source":["COUNT3(1,0,1)"]},{"cell_type":"markdown","metadata":{"id":"NOvdF2bZqO05"},"source":["* The number of 1-bits in the input `(1,0,1)` is 2 which in binary\n"," form is `(1,0)` as the above calculation shows.\n","* It is easy to verify all possible outcomes of this circuit function\n"," with the following code:"]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"elapsed":36,"status":"ok","timestamp":1668773330008,"user":{"displayName":"Samy Zafrany","userId":"01281551573032788195"},"user_tz":-120},"id":"4Pw3Kb5qq1CD","outputId":"2e140b82-4d71-4c0e-8d14-46afba43129b"},"outputs":[{"output_type":"stream","name":"stdout","text":["COUNT3(0,0,0) = (0, 0)\n","COUNT3(0,0,1) = (0, 1)\n","COUNT3(0,1,0) = (0, 1)\n","COUNT3(0,1,1) = (1, 0)\n","COUNT3(1,0,0) = (0, 1)\n","COUNT3(1,0,1) = (1, 0)\n","COUNT3(1,1,0) = (1, 0)\n","COUNT3(1,1,1) = (1, 1)\n"]}],"source":["for x1,x2,x3 in product([0,1], repeat=3):\n"," y1,y2 = COUNT3(x1,x2,x3)\n"," print(f\"COUNT3({x1},{x2},{x3}) = ({y1}, {y2})\")"]},{"cell_type":"markdown","metadata":{"id":"qHmlHv6XjoV8"},"source":["* Note that the same applies if we are given a boolean formula of\n"," this logical circuit\n","$$\n","\\begin{array}{rcl}\n","y_1 &=& (x_1 \\wedge x_2) \\vee ((x_1 \\oplus x_2) \\wedge x_3)\n","\\\\\n","y_2 &=& (x_1 \\oplus x_2) \\oplus x_3\n","\\end{array}\n","$$\n","instead of its digraph representation.\n","* In most cases, the digraph diagram is more intuitive, and easier\n"," to work with than the algebraic formula."]},{"cell_type":"markdown","metadata":{"id":"kNi7FIqG6D5K"},"source":["## Example 5: Simulating a 4x1 Multiplexer\n","* Multiplxers are important circuit elements in electronic design.\n","* Here is a simple **PyCirc Diagram** for\n"," a 4x1 Multiplexer circuit (aka MUX2)\n"," \n"," "]},{"cell_type":"code","execution_count":null,"metadata":{"id":"yxBa2uco6D5K"},"outputs":[],"source":["# Function for MUX2\n","# input: x3, x2, x1, x0, s2, s1\n","# output: y\n","\n","def MUX2(x0,x1,x2,x3,s1,s2):\n"," g1_y = NOT(s1)\n"," g2_y = NOT(s2)\n"," g3_y = AND(g1_y, x0, g2_y)\n"," g4_y = AND(g1_y, x1, s2)\n"," g5_y = AND(s1, x2, g2_y)\n"," g6_y = AND(s1, x3, s2)\n"," y = OR(g3_y, g4_y, g5_y, g6_y)\n"," return y\n"]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"elapsed":31,"status":"ok","timestamp":1668773330009,"user":{"displayName":"Samy Zafrany","userId":"01281551573032788195"},"user_tz":-120},"id":"UhcuOpQ0qzz2","outputId":"1be146c2-0c95-4c04-ee7e-380b3e9743ac"},"outputs":[{"output_type":"stream","name":"stdout","text":["x0 x1 x2 x3 | s1 s2 | y\n","------------------------------\n","0 0 0 0 | 0 0 | 0\n","0 0 0 0 | 0 1 | 0\n","0 0 0 0 | 1 0 | 0\n","0 0 0 0 | 1 1 | 0\n","0 0 0 1 | 0 0 | 0\n","0 0 0 1 | 0 1 | 0\n","0 0 0 1 | 1 0 | 0\n","0 0 0 1 | 1 1 | 1\n","0 0 1 0 | 0 0 | 0\n","0 0 1 0 | 0 1 | 0\n","0 0 1 0 | 1 0 | 1\n","0 0 1 0 | 1 1 | 0\n","0 0 1 1 | 0 0 | 0\n","0 0 1 1 | 0 1 | 0\n","0 0 1 1 | 1 0 | 1\n","0 0 1 1 | 1 1 | 1\n","0 1 0 0 | 0 0 | 0\n","0 1 0 0 | 0 1 | 1\n","0 1 0 0 | 1 0 | 0\n","0 1 0 0 | 1 1 | 0\n","0 1 0 1 | 0 0 | 0\n","0 1 0 1 | 0 1 | 1\n","0 1 0 1 | 1 0 | 0\n","0 1 0 1 | 1 1 | 1\n","0 1 1 0 | 0 0 | 0\n","0 1 1 0 | 0 1 | 1\n","0 1 1 0 | 1 0 | 1\n","0 1 1 0 | 1 1 | 0\n","0 1 1 1 | 0 0 | 0\n","0 1 1 1 | 0 1 | 1\n","0 1 1 1 | 1 0 | 1\n","0 1 1 1 | 1 1 | 1\n","1 0 0 0 | 0 0 | 1\n","1 0 0 0 | 0 1 | 0\n","1 0 0 0 | 1 0 | 0\n","1 0 0 0 | 1 1 | 0\n","1 0 0 1 | 0 0 | 1\n","1 0 0 1 | 0 1 | 0\n","1 0 0 1 | 1 0 | 0\n","1 0 0 1 | 1 1 | 1\n","1 0 1 0 | 0 0 | 1\n","1 0 1 0 | 0 1 | 0\n","1 0 1 0 | 1 0 | 1\n","1 0 1 0 | 1 1 | 0\n","1 0 1 1 | 0 0 | 1\n","1 0 1 1 | 0 1 | 0\n","1 0 1 1 | 1 0 | 1\n","1 0 1 1 | 1 1 | 1\n","1 1 0 0 | 0 0 | 1\n","1 1 0 0 | 0 1 | 1\n","1 1 0 0 | 1 0 | 0\n","1 1 0 0 | 1 1 | 0\n","1 1 0 1 | 0 0 | 1\n","1 1 0 1 | 0 1 | 1\n","1 1 0 1 | 1 0 | 0\n","1 1 0 1 | 1 1 | 1\n","1 1 1 0 | 0 0 | 1\n","1 1 1 0 | 0 1 | 1\n","1 1 1 0 | 1 0 | 1\n","1 1 1 0 | 1 1 | 0\n","1 1 1 1 | 0 0 | 1\n","1 1 1 1 | 0 1 | 1\n","1 1 1 1 | 1 0 | 1\n","1 1 1 1 | 1 1 | 1\n"]}],"source":["print(\"x0 x1 x2 x3 | s1 s2 | y\")\n","print(30*'-')\n","for x0,x1,x2,x3,s1,s2 in product([0,1], repeat=6):\n"," y = MUX2(x0,x1,x2,x3,s1,s2)\n"," print(f\"{x0} {x1} {x2} {x3} | {s1} {s2} | {y}\")"]},{"cell_type":"markdown","metadata":{"id":"luXJPXBy6D5U"},"source":["## Example 6: Simulating a 8x1 Multiplexer circuit\n","* Now we build a function for a 8x1 Multiplexer circuit (aka **MUX3**)\n","* Note that the 8x1 Multiplexer diagram is using\n"," our **MUX2** circuit as one of its building blocks\n"," (two instance of MUX2 are needed).\n","* We also need one instance of 2x1 Multiplexer (aka **MUX1**),\n"," which we leave to the student as an easy exercise.\n","\n"," "]},{"cell_type":"markdown","metadata":{"id":"IMN7UrHa6D5U"},"source":["* As you can see from the diagram we now have 8 inputs bits:\n"," x0, x1, x2, x3, x4, x5, x6, x7, \n"," and one output bit: y.\n","* We only need 3 logic gates: g1, g2, and g3.\n"," * g1 and g2 are two instances of `MUX2`,\n"," * g3 is an instance of `MUX1`.\n","* Here is the code for creating a **PyCircPL** `MUX3` function.\n"," * We leave to the student to figure out the `MUX1` function\n"," as an easy exercise.\n"," * Using the already defined `MUX1` and `MUX2` functions,\n"," it took 5 lines to define the `MUX3` function!"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"KkIIjyn36D5U"},"outputs":[],"source":["def MUX1(x0,x1,s1):\n"," y1 = NOT(s1)\n"," y2 = AND(x0, y1)\n"," y3 = AND(x1, s1)\n"," y = OR(y2, y3)\n"," return y\n","\n","def MUX3(x0,x1,x2,x3,x4,x5,x6,x7,s1,s2,s3):\n"," g1_y = MUX2(x0,x1,x2,x3,s2,s3)\n"," g2_y = MUX2(x4,x5,x6,x7,s2,s3)\n"," g3_y = MUX1(g1_y,g2_y,s1)\n"," y = g3_y\n"," return y"]},{"cell_type":"markdown","metadata":{"id":"wVdWFVOpL8sZ"},"source":["* Here is a simple call of `MUX3` on a simple input."]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"elapsed":27,"status":"ok","timestamp":1668773330010,"user":{"displayName":"Samy Zafrany","userId":"01281551573032788195"},"user_tz":-120},"id":"rWU2a7T99LQI","outputId":"1c38b78b-0cd1-4730-af19-5767ad39fea7"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["1"]},"metadata":{},"execution_count":15}],"source":["#MUX3(0,0,0,0,0,1,0,0, 1,0,1)\n","MUX3(x0=0, x1=0, x2=0, x3=0, x4=0, x5=1, x6=0, x7=0, s1=1, s2=0, s3=1)\n"]},{"cell_type":"markdown","metadata":{"id":"FHnRKteeMI0y"},"source":["* In the next example we sample 3% of the truth assignments to the\n"," `MUX3` input and check the output."]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"elapsed":24,"status":"ok","timestamp":1668773330011,"user":{"displayName":"Samy Zafrany","userId":"01281551573032788195"},"user_tz":-120},"id":"iwsDqWX25NgO","outputId":"f419ea6a-f195-4227-87ae-fd8602c1362b"},"outputs":[{"output_type":"stream","name":"stdout","text":["x0 x1 x2 x3 x4 x5 x6 x7 | s1 s2 s3 | y\n","--------------------------------------------------\n","0 0 0 0 0 1 0 0 | 1 0 0 | 0\n","0 0 0 1 0 0 0 1 | 0 1 1 | 1\n","0 0 0 1 1 0 1 1 | 0 0 1 | 0\n","0 0 0 1 1 1 0 1 | 0 1 0 | 0\n","0 0 1 0 0 0 0 1 | 1 0 1 | 0\n","0 0 1 0 0 0 1 0 | 1 1 0 | 1\n","0 0 1 1 0 0 0 1 | 0 0 0 | 0\n","0 0 1 1 0 0 0 1 | 0 1 0 | 1\n","0 0 1 1 0 0 0 1 | 1 0 1 | 0\n","0 0 1 1 1 1 1 0 | 1 1 0 | 1\n","0 0 1 1 1 1 1 1 | 0 0 0 | 0\n","0 0 1 1 1 1 1 1 | 1 0 0 | 1\n","0 1 0 0 0 1 0 1 | 1 1 0 | 0\n","0 1 0 1 0 0 0 0 | 0 1 0 | 0\n","0 1 0 1 0 1 1 0 | 0 0 1 | 1\n","0 1 0 1 1 0 0 1 | 1 1 1 | 1\n","0 1 0 1 1 1 0 1 | 1 1 0 | 0\n","0 1 1 0 0 0 0 0 | 0 1 0 | 1\n","0 1 1 0 0 1 0 1 | 1 1 0 | 0\n","0 1 1 0 1 0 1 1 | 1 0 1 | 0\n","0 1 1 0 1 1 0 1 | 1 1 1 | 1\n","0 1 1 1 0 0 0 0 | 1 1 1 | 0\n","0 1 1 1 0 1 0 1 | 0 1 1 | 1\n","0 1 1 1 1 0 1 0 | 0 0 0 | 0\n","0 1 1 1 1 1 1 1 | 0 0 1 | 1\n","1 0 0 0 0 0 1 0 | 0 0 0 | 1\n","1 0 0 0 0 1 1 1 | 0 1 1 | 0\n","1 0 0 0 1 0 1 0 | 1 0 1 | 0\n","1 0 0 0 1 1 0 0 | 1 1 0 | 0\n","1 0 0 0 1 1 0 1 | 1 1 0 | 0\n","1 0 0 0 1 1 1 0 | 0 0 1 | 0\n","1 0 0 1 0 1 0 1 | 0 0 1 | 0\n","1 0 0 1 1 0 1 0 | 1 0 0 | 1\n","1 0 0 1 1 0 1 1 | 1 0 1 | 0\n","1 0 1 0 0 1 0 1 | 1 0 0 | 0\n","1 0 1 0 0 1 1 1 | 0 0 0 | 1\n","1 0 1 0 0 1 1 1 | 0 0 1 | 0\n","1 0 1 0 0 1 1 1 | 1 0 0 | 0\n","1 0 1 1 0 0 0 1 | 0 0 0 | 1\n","1 0 1 1 0 1 1 0 | 0 1 1 | 1\n","1 1 0 0 0 1 0 0 | 1 1 0 | 0\n","1 1 0 0 1 1 0 0 | 0 1 0 | 0\n","1 1 0 0 1 1 1 1 | 0 1 0 | 0\n","1 1 0 1 0 0 0 1 | 0 0 1 | 1\n","1 1 0 1 0 1 1 1 | 1 1 1 | 1\n","1 1 0 1 1 1 0 1 | 0 0 0 | 1\n","1 1 0 1 1 1 1 0 | 1 0 1 | 1\n","1 1 0 1 1 1 1 1 | 1 0 0 | 1\n","1 1 1 0 0 1 0 0 | 1 0 0 | 0\n","1 1 1 0 0 1 0 1 | 0 1 1 | 0\n","1 1 1 0 1 1 0 0 | 1 0 0 | 1\n","1 1 1 1 0 0 0 0 | 1 1 0 | 0\n","1 1 1 1 1 0 1 1 | 1 1 1 | 1\n"]}],"source":["print(\"x0 x1 x2 x3 x4 x5 x6 x7 | s1 s2 s3 | y\")\n","print(50*'-')\n","for x0,x1,x2,x3,x4,x5,x6,x7,s1,s2,s3 in product([0,1], repeat=11):\n"," if random()<0.97:\n"," continue\n"," y = MUX3(x0,x1,x2,x3,x4,x5,x6,x7,s1,s2,s3)\n"," print(f\"{x0} {x1} {x2} {x3} {x4} {x5} {x6} {x7} | {s1} {s2} {s3} | {y}\")"]},{"cell_type":"markdown","metadata":{"id":"ehGxPdiO6D5W"},"source":["## 3-bits Adder Design\n","* Here is a simple design for 3 bits adder with carry in (cin) and\n"," carry out (cout) bits\n"," \n"," \n"," "]},{"cell_type":"markdown","metadata":{"id":"6BuYU8rW6We2"},"source":["* This circuit acceps three types of input\n"," * two binary numbers: $(a_2,a_1,a_0)$, $(b_2,b_1,b_0)$\n"," * a carry in bit: `cin`.\n","* Its output $(y_2,y_1,y_0)$ is the binary sum of the two numbers\n"," (with the carry added).\n","* In case of addition overflow,\n"," we need a carry out (cout) output bit as well.\n","* The following **PyCircPL** code describes a model for the **ADDER3** cell."]},{"cell_type":"code","execution_count":null,"metadata":{"id":"01wD-vlgO2ds"},"outputs":[],"source":["def ADDER3(a2, a1, a0, b2, b1 ,b0, cin):\n"," g1_y = XOR(cin, a0)\n"," g2_y = XOR(b1, a1)\n"," g3_y = XOR(b2, a2)\n"," g4_y = MUX1(a0, b0, g1_y)\n"," g5_y = MUX1(b1, g4_y, g2_y)\n"," cout = MUX1(a2, g5_y, g3_y)\n"," y2 = XOR(g5_y, g3_y)\n"," y1 = XOR(g4_y, g2_y)\n"," y0 = XOR(g1_y, b0)\n"," return cout, y2, y1, y0"]},{"cell_type":"markdown","metadata":{"id":"qOdySII2StdG"},"source":["* For example, lets try to compute 001+001"]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"elapsed":21,"status":"ok","timestamp":1668773330011,"user":{"displayName":"Samy Zafrany","userId":"01281551573032788195"},"user_tz":-120},"id":"7gknyL73S4Kn","outputId":"1c979be7-0471-4cd0-ae1a-f9ac04b9a667"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["(0, 0, 1, 0)"]},"metadata":{},"execution_count":18}],"source":["ADDER3(a2=0, a1=0, a0=1, b2=0, b1=0 ,b0=1, cin=0)"]},{"cell_type":"markdown","metadata":{"id":"GB8vv_z4TZM9"},"source":["This result should be of course interpreted as follows\n","```python\n","cout=0, y2=0, y1=1, y=0\n","```\n","which is the correct result `10`."]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"elapsed":256,"status":"ok","timestamp":1668773330249,"user":{"displayName":"Samy Zafrany","userId":"01281551573032788195"},"user_tz":-120},"id":"jCyucO7wVz_-","outputId":"5fe1c46f-7d56-4cf5-8704-1d0e52b5b528"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["(0, 1, 1, 0)"]},"metadata":{},"execution_count":19}],"source":["ADDER3(a2=0, a1=1, a0=1, b2=0, b1=1 ,b0=1, cin=0)"]},{"cell_type":"markdown","metadata":{"id":"K78dzlbc6D5X"},"source":["## ADDER9 - 9-bits Adder Design\n","* Here is a simple **PyCirc Design Diagram** for the standard 9-bits adder with a carry in (cin) and carry out (cout) bits.\n","* It uses 3 gates g1, g2, g3, of type **ADDER3** which are chained by their cout/cin pins.\n","* **Input:** `a<8:0> + b<8:0> + cin`\n","* **Output:** `y<8:0> + cout`\n"," \n"," "]},{"cell_type":"markdown","metadata":{"id":"kSwpeV6Q6D5Y"},"source":["* Here is a **PyCircPL** code for **ADDER9**:"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"_An8AsmmWTov"},"outputs":[],"source":["def ADDER9(a8, a7, a6, a5, a4, a3, a2, a1, a0, b8, b7, b6, b5, b4, b3, b2, b1, b0, cin):\n"," g1_cout,y2,y1,y0 = ADDER3(a2, a1, a0, b2, b1, b0, cin)\n"," g2_cout,y5,y4,y3 = ADDER3(a5, a4, a3, b5, b4, b3, g1_cout)\n"," cout,y8,y7,y6 = ADDER3(a8, a7, a6, b8, b7, b6, g2_cout)\n"," return cout, y8, y7, y6, y5, y4, y3, y2, y1, y0"]},{"cell_type":"markdown","metadata":{"id":"K1fEvVHUXWuY"},"source":["* Lets test this function withe the following input"]},{"cell_type":"code","execution_count":null,"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"elapsed":14,"status":"ok","timestamp":1668773330252,"user":{"displayName":"Samy Zafrany","userId":"01281551573032788195"},"user_tz":-120},"id":"hnNFZW-KXjk_","outputId":"b58f5b2f-3caf-4aa4-840c-a0b7a7ae3d3c"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["(0, 0, 0, 0, 1, 0, 0, 0, 0, 0)"]},"metadata":{},"execution_count":21}],"source":["ADDER9(a8=0, a7=0, a6=0, a5=0, a4=0, a3=0, a2=0, a1=0, a0=1, b8=0, b7=0, b6=0, b5=0, b4=1, b3=1, b2=1, b1=1, b0=1, cin=0)"]},{"cell_type":"markdown","metadata":{"id":"0QI7OGTB6D5d"},"source":["## Advanced Topics -- To be Continued ...\n","* For the more experienced students we present here some more\n"," advanced features of the PyCircPL package will be added within the\n"," near future. To be contniued ..."]}],"metadata":{"anaconda-cloud":{},"colab":{"provenance":[{"file_id":"https://github.com/samyzaf/pycirc/blob/main/pycirc.ipynb","timestamp":1664202945581}]},"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.7.11"}},"nbformat":4,"nbformat_minor":0}