{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Barrel shifter (cyhdl emulation library)\n", "\n", "This variant uses mixed myIRL and cythonized myhdl code segments. Note that the procedural generation is quite a bit faster, once the module is cythonized.\n", "\n", "This is using a `cyhdl` emulation and the `pyximport` mechanisms to ad-hoc cythonize Python code. The complation is taking place upon import." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We import the barrelshifter library:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "scrolled": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32m[cyhdl emulation]: COMPILE FOR CYTHON HDL : \u001b[0m BarrelShifterGenerator\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Compiling /tmp/_cython_inline_d4d0c88a151ed2920fb2029ff3e31d497bd207d2.pyx because it changed.\n", "[1/1] Cythonizing /tmp/_cython_inline_d4d0c88a151ed2920fb2029ff3e31d497bd207d2.pyx\n" ] } ], "source": [ "from library.barrelshifter import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Edit barrelshifter.py](library/barrelshifter.py)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then we create a barrel shifter generator with data width 32 (power 5):" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "W_POWER = 5\n", "\n", "TEST_VALUES = [\n", " (0xdead, 8, 0xdead << 8),\n", " (0x8f01, 15, 0x8f01 << 15),\n", "]\n", "\n", "b = BarrelShifterGenerator(W_POWER)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then we instance it first time in the test bench below. Note the instancing time on this first run." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[7;35m Declare obj 'barrel_shifter' in context '(LIB: BarrelShifterGenerator 'bs')'(.BarrelShifterGenerator'>) \u001b[0m\n", "\u001b[7;35m Declare obj 'shifter_stage' in context '(LIB: BarrelShifterGenerator 'bs')'(.BarrelShifterGenerator'>) \u001b[0m\n", "\u001b[7;35m Declare obj 'cshift' in context '(LIB: BarrelShifterGenerator 'bs')'(.BarrelShifterGenerator'>) \u001b[0m\n", "\u001b[32m Module bs: Existing instance cshift, rename to cshift_1 \u001b[0m\n", "\u001b[32m Module bs: Existing instance shifter_stage, rename to shifter_stage_1 \u001b[0m\n", "\u001b[32m Module bs: Existing instance shifter_stage, rename to shifter_stage_2 \u001b[0m\n", "\u001b[32m Module bs: Existing instance shifter_stage, rename to shifter_stage_3 \u001b[0m\n", "\u001b[32m Module bs: Existing instance shifter_stage, rename to shifter_stage_4 \u001b[0m\n", "Finished test in 0.2599 secs\n" ] } ], "source": [ "from myirl.test.common_test import gen_osc\n", "from cyhdl import *\n", "\n", "@block\n", "def top_bs(b):\n", " clk = ClkSignal()\n", " ce = Signal(bool())\n", " val, result = [ Signal(intbv(0xaa00)[2 ** W_POWER:]) for i in range(2) ]\n", " s = Signal(intbv()[W_POWER:])\n", " \n", " inst = [\n", " b.barrel_shifter(clk, ce, val, s, result, False),\n", " gen_osc(clk, 2)\n", " ]\n", "\n", " @instance\n", " def stim():\n", " for item in TEST_VALUES:\n", " ce.next = False\n", " s.next = item[1]\n", " val.next = item[0]\n", " yield(clk.posedge)\n", " ce.next = True\n", " yield(clk.posedge)\n", " yield(clk.posedge)\n", "\n", " print(result)\n", " assert result == item[2]\n", " \n", " raise StopSimulation\n", "\n", " inst += [ stim ]\n", " return inst\n", " \n", "@utils.timer\n", "def test(b): \n", " return top_bs(b)\n", "\n", "design = test(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Running the test bench again, the duration is a little less than on the first run, because this module was already compiled." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[32m Module top_bs: Existing instance top_bs, rename to top_bs_1 \u001b[0m\n", "Finished test in 0.0706 secs\n" ] } ], "source": [ "design = test(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, the quick & dirty verification:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Writing 'top_bs_1' to file /tmp/myirl_top_bs_90m_a89i/top_bs_1.vhdl \n", " Creating library file module_defs.vhdl \n", " Writing 'shifter_stage_4' to file ./shifter_stage_4.vhdl \n", " Writing 'shifter_stage_3' to file ./shifter_stage_3.vhdl \n", " Writing 'shifter_stage_2' to file ./shifter_stage_2.vhdl \n", " Writing 'shifter_stage_1' to file ./shifter_stage_1.vhdl \n", " Writing 'cshift_1' to file ./cshift_1.vhdl \n", " Writing 'cshift' to file ./cshift.vhdl \n", " Writing 'shifter_stage' to file ./shifter_stage.vhdl \n", " Writing 'barrel_shifter' to file ./barrel_shifter.vhdl \n", " Not emitting design types library \n", "WORK DIR of instance [Instance top_bs_1 I/F: [// ID: top_bs_0 ]] /tmp/myirl_top_bs_90m_a89i/\n", "==== COSIM stdout ====\n", "0x00DEAD00\n", "0x47808000\n", "simulation stopped @22ns\n", "\n" ] }, { "data": { "text/plain": [ "0" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from myirl import targets\n", "from myirl.test.common_test import run_ghdl\n", "\n", "f = design.elab(targets.VHDL, elab_all = True)\n", "f += b.elab(targets.VHDL)\n", "# print(f)\n", "run_ghdl(f, design, vcdfile = 'bs.vcd', debug = True)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# !cat -n /tmp/barrel_shifter.vhdl" ] } ], "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.10.0" } }, "nbformat": 4, "nbformat_minor": 4 }