{ "cells": [ { "cell_type": "markdown", "id": "12dd8deb-ce5d-4118-b517-6671eaabeaa2", "metadata": {}, "source": [ "# Factory classes\n", "\n", "Some myHDL libraries provide classes to generate `@block` components. These are currently under scrutiny. \n", "\n" ] }, { "cell_type": "markdown", "id": "aff5ca49-b134-41be-854d-f619cf3fe94c", "metadata": {}, "source": [ "## MyHDL factory classes (emulation)\n", "\n", "For the time being, factory classes have be decorated using the `@factory` decorator in order to be translated to IRL.\n", "Not that the following class makes sense in the real world, but as an example:" ] }, { "cell_type": "markdown", "id": "b7cad36a-b609-4972-86e8-a6eda9fb2920", "metadata": {}, "source": [ "### `@block` factory" ] }, { "cell_type": "code", "execution_count": 1, "id": "25722f8e-af44-4fde-a247-88f9feb993c2", "metadata": {}, "outputs": [], "source": [ "from myirl.emulation.myhdl import *\n", "\n", "@factory\n", "class Bingo:\n", " def __init__(self, parameter = 8):\n", " self.n = parameter\n", " \n", " T = Signal.Type(intbv, parameter)\n", " \n", " @block\n", " def my_unit(clk : ClkSignal, a : T, b : T.Output):\n", " \n", " @always(clk.posedge)\n", " def worker():\n", " b.next = a\n", "\n", " return instances()\n", "\n", " self.my_unit = my_unit " ] }, { "cell_type": "code", "execution_count": 2, "id": "c9b32a4c-de2c-46c6-bf0d-3d3c118823d8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Creating process 'my_unit/worker' with sensitivity (clk'rising,)\n", " Writing 'my_unit' to file /tmp/myirl_top_my_unit_ey6bg8eu/my_unit.vhdl \n" ] } ], "source": [ "def test():\n", " b = Bingo(6)\n", " u, v = [Signal(intbv()[6:]) for _ in range(2)]\n", " c = ClkSignal()\n", " u = b.my_unit(c, u, v)\n", " \n", " f = u.elab(targets.VHDL)\n", " \n", "test()" ] }, { "cell_type": "code", "execution_count": 3, "id": "3fece99e-1108-4da9-9f58-a4cfca3ba6bd", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "cat: /tmp/my_unit.vhdl: No such file or directory\r\n" ] } ], "source": [ "!cat /tmp/my_unit.vhdl" ] }, { "cell_type": "markdown", "id": "5835fc0c-9eab-4a1c-9b4b-22cf00fd1ede", "metadata": {}, "source": [ "### Class with static `@block_component` member\n", "\n", "When specified as a static unit inside this class, the class will serve as its context and the unit requires a `@block_component` decoration (without arguments), plus the `self` argument, representing a *component method* describing hardware inference.\n", "In this case, the factory class is derived from the `DesignModule` (or minimum the `BareModule` class). This construct helps to encapsulate common blocks that depend on a complex configuration." ] }, { "cell_type": "code", "execution_count": 4, "id": "e613bb15-1234-42a6-9b80-25c6ad9c4bed", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "==============================\n", "Unparsing unit Bongo\n", "==============================\n", "\n", "\n", "class Bongo(LibraryModule):\n", "\n", " def __init__(self, parameter=8, name='Bongo'):\n", " self.n = parameter\n", " super().__init__(name)\n", " self.files = []\n", " self.inst = None\n", "\n", " @block_component\n", " def my_unit1(self, clk: ClkSignal, a: Signal, b: Signal.Output):\n", " 'A component somewhere in the hierarchy'\n", " ls = Signal(intbv()[self.n:])\n", "\n", " @always_(clk.posedge)\n", " def worker():\n", " (yield [ls.set(a), b.set(ls)])\n", " return instances()\n", "\n", " @block_component\n", " def my_tb(self):\n", " 'A built-in test bench'\n", " (u, v) = [Signal(intbv()[self.n:]) for _ in range(2)]\n", " c = ClkSignal()\n", "\n", " @always_(delay(4))\n", " def clkgen():\n", " (yield [c.set((~ c))])\n", "\n", " @sequential\n", " def stim(_sequence):\n", " _sequence += [u.set(2), wait(c.posedge), wait(c.posedge), wait(c.posedge), print_(v), assert_((v == 2), 'Failed in /tmp/ipykernel_41098/1829234184.py:Bongo():41'), raise_(StopSimulation)]\n", " uut = self.my_unit1(c, u, v)\n", " return instances()\n", "\n", " def build(self):\n", " t = self.my_tb()\n", " self.files = t.elab(targets.VHDL, elab_all=True)\n", " self.inst = t\n", " print('Resulting files', self.files)\n", "\n", " def simulate(self):\n", " common_test.run_ghdl(self.files, self.inst, debug=True)\n", "\n" ] } ], "source": [ "from myirl.test import common_test\n", "\n", "@factory\n", "class Bongo(LibraryModule):\n", " def __init__(self, parameter = 8, name = \"Bongo\"):\n", " self.n = parameter\n", " super().__init__(name)\n", " self.files = []\n", " self.inst = None\n", " \n", " # Here, we use `@block_component` without arguments, as the context is 'self'\n", " @block_component\n", " def my_unit1(self, clk : ClkSignal, a : Signal, b : Signal.Output):\n", " \"A component somewhere in the hierarchy\"\n", " ls = Signal(intbv()[self.n:])\n", " \n", " @always(clk.posedge)\n", " def worker():\n", " ls.next = a\n", " b.next = ls\n", "\n", " return instances()\n", " \n", " @block_component\n", " def my_tb(self):\n", " \"A built-in test bench\"\n", " u, v = [Signal(intbv()[self.n:]) for _ in range(2)]\n", " c = ClkSignal()\n", " \n", " @always(delay(4))\n", " def clkgen():\n", " c.next = ~c\n", " \n", " @instance\n", " def stim():\n", " u.next = 2\n", " yield c.posedge\n", " yield c.posedge\n", " yield c.posedge\n", " print(v)\n", " assert v == 2\n", " raise StopSimulation\n", " \n", " uut = self.my_unit1(c, u, v)\n", " return instances()\n", " \n", " def build(self):\n", " t = self.my_tb()\n", " self.files = t.elab(targets.VHDL, elab_all = True)\n", " self.inst = t\n", " print(\"Resulting files\", self.files)\n", " \n", " def simulate(self):\n", " common_test.run_ghdl(self.files, self.inst, debug = True)\n", " \n", "print(Bongo.unparse())" ] }, { "cell_type": "markdown", "id": "03a6ac37-d19e-4162-843e-a256a0ad433a", "metadata": {}, "source": [ "Running this design component, *OO* style:" ] }, { "cell_type": "code", "execution_count": 5, "id": "d795f0b1-be86-4425-9c43-0a5abdce7163", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Using default for name: Bongo\n", "\u001b[7;35m Declare obj 'my_tb' in context '(LIB: Bongo 'Bongo')' \u001b[0m\n", "Creating process 'my_tb/clkgen' with sensitivity ([ DeltaT 4 ns ],)\n", "Creating sequential 'my_tb/stim' \n", "\u001b[7;35m Declare obj 'my_unit1' in context '(LIB: Bongo 'Bongo')' \u001b[0m\n", "Creating process 'my_unit1/worker' with sensitivity (clk'rising,)\n", " Elaborating component my_unit1__Bongo_s1_s6_s6 \n", " Writing 'my_unit1' to file /tmp/myirl_Bongo_b8y8be_6/my_unit1.vhdl \n", " Elaborating component my_tb__Bongo \n", " Writing 'my_tb' to file /tmp/myirl_Bongo_b8y8be_6/my_tb.vhdl \n", " Creating library file /tmp/myirl_module_defs_rauris6_/module_defs.vhdl \n", "Resulting files ['/tmp/myirl_Bongo_b8y8be_6/my_unit1.vhdl', '/tmp/myirl_Bongo_b8y8be_6/my_tb.vhdl', '/tmp/myirl_module_defs_rauris6_/module_defs.vhdl']\n", "==== COSIM stdout ====\n", "\n", "==== COSIM stderr ====\n", "\n", "==== COSIM stdout ====\n", "analyze /home/testing/.local/lib/python3.9/site-packages/myirl-0.0.0-py3.9-linux-x86_64.egg/myirl/targets/../test/vhdl/txt_util.vhdl\n", "analyze /home/testing/.local/lib/python3.9/site-packages/myirl-0.0.0-py3.9-linux-x86_64.egg/myirl/targets/libmyirl.vhdl\n", "analyze /tmp/myirl_Bongo_b8y8be_6/my_unit1.vhdl\n", "analyze /tmp/myirl_Bongo_b8y8be_6/my_tb.vhdl\n", "elaborate my_tb\n", "\n", "==== COSIM stderr ====\n", "\n", "==== COSIM stdout ====\n", "0x02\n", "/tmp/myirl_Bongo_b8y8be_6/my_tb.vhdl:42:9:@20ns:(assertion failure): Stop Simulation\n", "/tmp/my_tb:error: assertion failed\n", "in process .my_tb(myirl).stim\n", "/tmp/my_tb:error: simulation failed\n", "\n", "==== COSIM stderr ====\n", "\n", "Using default for name: Bongo\n", "\u001b[7;35m Declare obj 'my_tb' in context '(LIB: Bongo 'Bongo')' \u001b[0m\n", "Creating process 'my_tb/clkgen' with sensitivity ([ DeltaT 4 ns ],)\n", "Creating sequential 'my_tb/stim' \n", "\u001b[7;35m Declare obj 'my_unit1' in context '(LIB: Bongo 'Bongo')' \u001b[0m\n", "Creating process 'my_unit1/worker' with sensitivity (clk'rising,)\n", " Elaborating component my_unit1__Bongo_s1_s7_s7 \n", " Writing 'my_unit1' to file /tmp/myirl_Bongo_jfhjnb75/my_unit1.vhdl \n", " Elaborating component my_tb__Bongo \n", " Writing 'my_tb' to file /tmp/myirl_Bongo_jfhjnb75/my_tb.vhdl \n", " Creating library file /tmp/myirl_module_defs_u116uelo/module_defs.vhdl \n", "Resulting files ['/tmp/myirl_Bongo_jfhjnb75/my_unit1.vhdl', '/tmp/myirl_Bongo_jfhjnb75/my_tb.vhdl', '/tmp/myirl_module_defs_u116uelo/module_defs.vhdl']\n" ] } ], "source": [ "def test():\n", " b = Bongo(6)\n", " b.build()\n", " b.simulate()\n", " \n", " b = Bongo(7)\n", " b.build()\n", "test()" ] }, { "cell_type": "markdown", "id": "b290abbe-4f99-4e39-a3d6-c1232024cef3", "metadata": {}, "source": [ "## Examples\n", "\n", "* DVI 10b8b encoder and decoder [library example](codec10b8b.ipynb)" ] } ], "metadata": { "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.9.2" } }, "nbformat": 4, "nbformat_minor": 5 }