{ "cells": [ { "cell_type": "markdown", "id": "83d2dd56-f7d7-4f16-9c51-d3e1dd2441d1", "metadata": {}, "source": [ "# Simpler barrel shifter implementation\n", "\n", "\n", "A different, more compact variant, avoiding recursive fun. This one does not confuse CXXRTL with too much combinatorial logic." ] }, { "cell_type": "code", "execution_count": 1, "id": "e9efd303-8e79-46ac-b30d-c1a2e6c2bd8f", "metadata": {}, "outputs": [], "source": [ "import sys\n", "sys.path.insert(0, '../../')" ] }, { "cell_type": "code", "execution_count": 2, "id": "744c2505-f3f9-4d0c-b419-61396ba386e0", "metadata": {}, "outputs": [], "source": [ "from myirl.emulation.myhdl import *" ] }, { "cell_type": "code", "execution_count": 3, "id": "f6180ac6-cf3c-49a0-a831-db9b27efc249", "metadata": {}, "outputs": [], "source": [ "Bool = Signal.Type(bool)\n", "\n", "@block\n", "def bs_stage(wout : Signal.Output,\n", " win : Signal, sh_bit : Signal, stage : int,\n", " ROTATE : (Bool, bool),\n", " LEFT : (Bool, bool),\n", " ASR : (Bool, bool), BITS : int):\n", " \n", " j = 2 ** stage\n", " \n", " # When ASR is a constant, we optimize to constants as well:\n", " if isinstance(ASR, bool):\n", " if ASR:\n", " pad_msb = j * [ win[BITS-1] ]\n", " else:\n", " pad_msb = [ intbv(0)[j:] ]\n", " else:\n", " pad_msb = j * [ win[BITS-1] & ASR ]\n", " \n", " \n", " @always_comb\n", " def worker():\n", " if sh_bit == False:\n", " wout.next = win\n", " else:\n", " if ROTATE:\n", " if LEFT:\n", " wout.next = concat(win[BITS-j:0], win[BITS:BITS-j])\n", " else:\n", " wout.next = concat(win[j:0], win[BITS:j])\n", " else:\n", " if LEFT:\n", " wout.next = concat(win[BITS-j:0], *pad_msb)\n", " else:\n", " wout.next = concat(*pad_msb, win[BITS:j])\n", " \n", " return instances()\n", "\n", "BOOL = (bool, Signal.Type(bool))\n", "\n", "@block\n", "def barrel_shifter(clk : ClkSignal,\n", " ce : Signal,\n", " val : Signal,\n", " s : Signal,\n", " result : Signal.Output,\n", " left : BOOL = True,\n", " asr : BOOL = False,\n", " rotate : BOOL = False, W_POWER = 5):\n", " \n", " BITS = 2 ** W_POWER\n", " \n", " worker = [ Signal(intbv()[BITS:]) for _ in range(W_POWER + 1) ]\n", " \n", " inst = [\n", " worker[0].wireup(val),\n", " ]\n", " \n", " for i in range(W_POWER):\n", " inst += [\n", " bs_stage(worker[i+1], worker[i], s[i], i, rotate, left, asr, BITS)\n", " ]\n", " \n", " @always(clk.posedge)\n", " def ff():\n", " if ce:\n", " result.next = worker[W_POWER]\n", " \n", " return instances()\n", " " ] }, { "cell_type": "code", "execution_count": 4, "id": "a3646677-bc8a-4227-8b61-2f0ba90b5052", "metadata": {}, "outputs": [], "source": [ "from simulation import *\n", "\n", "from myirl.simulation import print_\n", "from myirl.emulation.factory_class import factory\n", "from myirl.targets import pyosys\n", "\n", "class example_design(factory.Module):\n", " def __init__(self, name, simclass, *args, **kwargs):\n", " super().__init__(name, simclass, *args, **kwargs)\n", " self.W_POWER = 4\n", " self.debug = False\n", "\n", " # Top level signal set\n", " self.clk = self.ClkSignal(name=\"clk\")\n", " self.ce = self.Signal(bool())\n", " self.val, self.result = [ self.Signal(intbv(0xaa00)[2 ** self.W_POWER:]) for i in range(2) ]\n", " self.result.rename(\"res\")\n", " self.s = self.Signal(intbv()[self.W_POWER:])\n", " self.left = self.Signal(bool())\n", " self.asr = self.Signal(bool())\n", " self.rotate = self.Signal(bool())\n", " \n", " def build(self):\n", " return barrel_shifter(\n", " clk = self.clk,\n", " ce = self.ce,\n", " val = self.val,\n", " s = self.s,\n", " result = self.result,\n", " rotate = self.rotate,\n", " left = self.left,\n", " asr = self.asr,\n", " W_POWER = self.W_POWER\n", " )\n", " \n", " def emit_rtlil(self, fileprefix):\n", " tgt = pyosys.RTLIL(\"barrel_shifter\")\n", " inst = self.build()\n", " d = inst.elab(tgt)\n", " d[0].write_rtlil(fileprefix)\n", "\n", " @factory.testbench('ns')\n", " def tb_rtl(self):\n", " \n", " inst = self.build()\n", "\n", " clk = self.clk\n", " ce = self.ce\n", " val = self.val\n", " result = self.result\n", " s = self.s\n", " rot, asr, left = self.rotate, self.asr, self.left\n", " \n", " @self.always(delay(2))\n", " def clkgen():\n", " clk.next = ~clk\n", "\n", " TEST_VALUES = [\n", " (0xdead, True, False, False, 8, 0xad00),\n", " (0x8f01, True, False, False, 15, 0x8000),\n", " (0xdead, False, False, False, 8, 0x00de),\n", " (0xdead, False, True, False, 12, 0xeadd),\n", " # With ASR bit set (only effective with right shift)\n", " (0x8f01, False, False, True, 14, 0xfffe),\n", " ]\n", "\n", " @self.sequence\n", " def stim():\n", " for item in TEST_VALUES:\n", " ce.next = False\n", " s.next = item[4]\n", " left.next = item[1]\n", " rot.next = item[2]\n", " asr.next = item[3]\n", " \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[5]\n", "\n", " raise StopSimulation\n", "\n", " return instances() " ] }, { "cell_type": "code", "execution_count": 5, "id": "9d861ac4-f000-40ec-a0d4-9612d80384ae", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[32m Module testbench: Existing instance bs_stage, rename to bs_stage_1 \u001b[0m\n", "\u001b[32m Module testbench: Existing instance bs_stage, rename to bs_stage_2 \u001b[0m\n", "\u001b[32m Module testbench: Existing instance bs_stage, rename to bs_stage_3 \u001b[0m\n", " Elaborating component bs_stage_s16_s16_s1_3_s1_s1_s1_16 \n", "\u001b[32m Adding module with name `bs_stage_3` \u001b[0m\n", " Elaborating component bs_stage_s16_s16_s1_2_s1_s1_s1_16 \n", "\u001b[32m Adding module with name `bs_stage_2` \u001b[0m\n", " Elaborating component bs_stage_s16_s16_s1_1_s1_s1_s1_16 \n", "\u001b[32m Adding module with name `bs_stage_1` \u001b[0m\n", " Elaborating component bs_stage_s16_s16_s1_0_s1_s1_s1_16 \n", "\u001b[32m Adding module with name `bs_stage` \u001b[0m\n", "\u001b[32m Adding module with name `barrel_shifter` \u001b[0m\n", "\u001b[7;34m FINALIZE implementation `barrel_shifter` of `barrel_shifter` \u001b[0m\n", "\n", "-- Running command `tee -q hierarchy -top \\barrel_shifter' --\n", "\n", "-- Running command `write_rtlil barrelshifter.il' --\n", "\n", "2. Executing RTLIL backend.\n", "DEBUG: Skip non-simulation type \n", "DEBUG: Skip non-simulation type \n", "============================================================================\n", " Elaborating component bs_stage_s16_s16_s1_3_s1_s1_s1_16 \n", "\u001b[32m Adding module with name `bs_stage_3` \u001b[0m\n", " Elaborating component bs_stage_s16_s16_s1_2_s1_s1_s1_16 \n", "\u001b[32m Adding module with name `bs_stage_2` \u001b[0m\n", " Elaborating component bs_stage_s16_s16_s1_1_s1_s1_s1_16 \n", "\u001b[32m Adding module with name `bs_stage_1` \u001b[0m\n", " Elaborating component bs_stage_s16_s16_s1_0_s1_s1_s1_16 \n", "\u001b[32m Adding module with name `bs_stage` \u001b[0m\n", "\u001b[32m Adding module with name `barrel_shifter` \u001b[0m\n", "\u001b[7;34m FINALIZE implementation `barrel_shifter` of `barrel_shifter` \u001b[0m\n", "Compiling /tmp/barrel_shifter_14d3.pyx because it changed.\n", "[1/1] Cythonizing /tmp/barrel_shifter_14d3.pyx\n", "running build_ext\n", "building 'barrel_shifter_14d3' extension\n", "x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -DCOSIM_NAMESPACE=barrel_shifter_14d3 -I../../myirl/../ -I/tmp/ -I/usr/share/yosys/include -I/usr/include/python3.9 -c /tmp/barrel_shifter_14d3.cpp -o build/temp.linux-x86_64-3.9/tmp/barrel_shifter_14d3.o\n", "x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -DCOSIM_NAMESPACE=barrel_shifter_14d3 -I../../myirl/../ -I/tmp/ -I/usr/share/yosys/include -I/usr/include/python3.9 -c /tmp/barrel_shifter_14d3_rtl.cpp -o build/temp.linux-x86_64-3.9/tmp/barrel_shifter_14d3_rtl.o\n", "x86_64-linux-gnu-g++ -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fwrapv -O2 -Wl,-z,relro -g -fwrapv -O2 -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.9/tmp/barrel_shifter_14d3.o build/temp.linux-x86_64-3.9/tmp/barrel_shifter_14d3_rtl.o -o build/lib.linux-x86_64-3.9/barrel_shifter_14d3.cpython-39-x86_64-linux-gnu.so\n", "copying build/lib.linux-x86_64-3.9/barrel_shifter_14d3.cpython-39-x86_64-linux-gnu.so -> \n", "Open for writing: tb_rtl.vcd\n", "\u001b[7;35m CXXRTL context: SKIP INTERFACE ITEM `W_POWER` \u001b[0m\n", " : 0xad00\n", " : 0x8000\n", " : 0x00de\n", " : 0xeadd\n", " : 0xfffe\n", "STOP SIMULATION @58 \n" ] } ], "source": [ "from myirl.test.ghdl import GHDL\n", "from yosys.simulator import CXXRTL\n", "\n", "d = example_design(\"testbench\", CXXRTL)\n", "d.emit_rtlil(\"barrelshifter\")\n", "tb = d.tb_rtl()\n", "print(76 * '=')\n", "tb.run(60)" ] }, { "cell_type": "code", "execution_count": null, "id": "287c87ef-0fea-4f51-bead-d910bffc84a6", "metadata": {}, "outputs": [], "source": [] } ], "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 }