diff --git a/Cortex-M0/nanosoc/systems/mcu/fpga_imp/pynq_export/pz104/jupyter_notebooks/soclabs/nanosoc-iotest.ipynb b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/pynq_export/pz104/jupyter_notebooks/soclabs/nanosoc-iotest.ipynb new file mode 100755 index 0000000000000000000000000000000000000000..15a9d8985625cada4d7dfb655cf4cd17ba07fc2b --- /dev/null +++ b/Cortex-M0/nanosoc/systems/mcu/fpga_imp/pynq_export/pz104/jupyter_notebooks/soclabs/nanosoc-iotest.ipynb @@ -0,0 +1,708 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Downloading Overlays\n", + "\n", + "This notebook demonstrates how to download an FPGA overlay and examine programmable logic state. \n", + "\n", + "## 1. Instantiating an overlay\n", + "With the following overlay bundle present in the `overlays` folder, users can instantiate the overlay easily.\n", + "\n", + "* A bitstream file (\\*.bit).\n", + "* An hwh file (\\*.hwh).\n", + "* A python class (\\*.py).\n", + "\n", + "For example, an overlay called `base` can be loaded by:\n", + "```python\n", + "from pynq.overlays.base import BaseOverlay\n", + "overlay = BaseOverlay(\"base.bit\")\n", + "```\n", + "Users can also use the absolute file path of the bitstream to instantiate the overlay.\n", + "\n", + "In this notebook, we get the current bitstream loaded on PL, and try to download it multiple times." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "\n", + "try {\n", + "require(['notebook/js/codecell'], function(codecell) {\n", + " codecell.CodeCell.options_default.highlight_modes[\n", + " 'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n", + " Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n", + " Jupyter.notebook.get_cells().map(function(cell){\n", + " if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n", + " });\n", + "});\n", + "} catch (e) {};\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "\n", + "try {\n", + "require(['notebook/js/codecell'], function(codecell) {\n", + " codecell.CodeCell.options_default.highlight_modes[\n", + " 'magic_text/x-csrc'] = {'reg':[/^%%pybind11/]};\n", + " Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n", + " Jupyter.notebook.get_cells().map(function(cell){\n", + " if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n", + " });\n", + "});\n", + "} catch (e) {};\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import os, warnings\n", + "from pynq import PL\n", + "from pynq import Overlay\n", + "\n", + "ol = Overlay(\"/home/xilinx/pynq/overlays/soclabs/design_1.bit\")\n", + "\n", + "if not os.path.exists(PL.bitfile_name):\n", + " warnings.warn('There is no overlay loaded after boot.', UserWarning)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Note**: If you see a warning message in the above cell, it means that no overlay\n", + "has been loaded after boot, hence the PL server is not aware of the \n", + "current status of the PL. In that case you won't be able to run this notebook\n", + "until you manually load an overlay at least once using:\n", + "\n", + "```python\n", + "from pynq import Overlay\n", + "ol = Overlay('your_overlay.bit')\n", + "```\n", + "\n", + "If you do not see any warning message, you can safely proceed." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "ol = Overlay(PL.bitfile_name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can check the download timestamp for this overlay." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'2023/2/20 17:44:40 +479858'" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ol.download()\n", + "ol.timestamp" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "from pynq import Overlay\n", + "from pynq import MMIO\n", + "import time\n", + "from time import sleep, time\n", + "\n", + "#ADP_address = 0x80020000 # nanosoc FT1248 com channel\n", + "#ADP_address = 0x80030000 # streamio TX/RX loopback (unbuffered)\n", + "#ADP_address = 0x80040000 # streamio TX/RX loopback (FIFO buffered)\n", + "ADP_address = 0x80050000 # local test ADP controller COM channel\n", + "UART2_address = 0x80060000 # nanosoc UART2 com serial (9600 baud?)\n", + "#ADP_address = 0x80070000 # uart TX/RX loopback\n", + "\n", + "# HARDWARE CONSTANTS\n", + "RX_FIFO = 0x00\n", + "TX_FIFO = 0x04\n", + "# Status Reg\n", + "STAT_REG = 0x08\n", + "RX_VALID = 0\n", + "RX_FULL = 1\n", + "TX_EMPTY = 2\n", + "TX_FULL = 3\n", + "IS_INTR = 4\n", + "\n", + "# Ctrl Reg\n", + "CTRL_REG = 0x0C\n", + "RST_TX = 0\n", + "RST_RX = 1\n", + "INTR_EN = 4\n", + "\n", + "class ADPIO:\n", + " def __init__(self, address):\n", + " # Setup axi core\n", + " self.uart = MMIO(address, 0x10000, debug=False)\n", + " self.address = address\n", + "\n", + " def setupCtrlReg(self):\n", + "# # Reset FIFOs, disable interrupts\n", + "# self.uart.write(CTRL_REG, 1 << RST_TX | 1 << RST_RX)\n", + "# sleep(1)\n", + " self.uart.write(CTRL_REG, 0)\n", + " sleep(1)\n", + " self.uart.write(TX_FIFO, 0x1b)\n", + " sleep(1)\n", + "\n", + " def read(self, count, timeout=1):\n", + " # status = currentStatus(uart) bad idea\n", + " buf = \"\"\n", + " stop_time = time() + timeout\n", + " for i in range(count):\n", + " # Wait till RX fifo has valid data, stop waiting if timeoutpasses\n", + " while (not (self.uart.read(STAT_REG) & 1 << RX_VALID)) and (time() < stop_time):\n", + " pass\n", + " if time() >= stop_time:\n", + " break\n", + " buf += chr(self.uart.read(RX_FIFO))\n", + " return buf\n", + " \n", + " def write(self, buf, timeout=1):\n", + " # Write bytes via UART\n", + " stop_time = time() + timeout\n", + " wr_count = 0\n", + " for i in buf:\n", + " # Wait while TX FIFO is Full, stop waiting if timeout passes\n", + " while (self.uart.read(STAT_REG) & 1 << TX_FULL) and (time() < stop_time):\n", + " pass\n", + " # Check timeout\n", + " if time() > stop_time:\n", + " wr_count = -1\n", + " break\n", + " self.uart.write(TX_FIFO, ord(i))\n", + " wr_count += 1\n", + " return wr_count\n", + "\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Inspect the ADP banner after reset (0x50CLAB02 expected)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "' 0x50c1ab02\\n\\r\\n\\r]'" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adp = ADPIO(ADP_address)\n", + "# Setup AXI UART register\n", + "adp.setupCtrlReg()\n", + "adp.read(20)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Also check the UART2 RX channel for any boot message" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "''" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "uart = ADPIO(UART2_address)\n", + "# Setup AXI UART register\n", + "uart.setupCtrlReg()\n", + "uart.read(50)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now check adp Address pointer reets to zero" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'A 0x00000000\\n\\r]'" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adp.write('A\\n')\n", + "adp.read(20)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And do a couple of 32-bit reads" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'R 0x00000000\\n\\r]'" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adp.write('R\\n')\n", + "adp.read(15)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'R 0x00000000\\n\\r]'" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adp.write('R\\n')\n", + "adp.read(15)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Verify the address pointer has auto-incremented two words" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'A 0x00000008\\n\\r]'" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adp.write('A\\n')\n", + "adp.read(15)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now set adp address to high memory and write a couple of patterns" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'A 0xc0000000\\n\\r]'" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adp.write('A c0000000\\n')\n", + "adp.read(20)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'W 0x11111111\\n\\r]'" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adp.write('W 111111111\\n')\n", + "adp.read(15)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'W 0x22222222\\n\\r]'" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adp.write('W 22222222\\n')\n", + "adp.read(15)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Reset the address pointer and verify same patterns read back" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'A 0xc0000000\\n\\r]'" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adp.write('A c0000000\\n')\n", + "adp.read(20)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'R 0x11111111\\n\\r]'" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adp.write('R\\n')\n", + "adp.read(15)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'R 0x22222222\\n\\r]'" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "adp.write('R\\n')\n", + "adp.read(15)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## ol.download()\n", + "ol.timestamp\n", + "ol.reset()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ip_info = {'trace_cntrl':\"ft1248tb_i/ila_0\"}\n", + "class pynq.logictools.trace_analyzer.TraceAnalyzer(ip_info)\n", + "\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#PL.ip_dict" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gpio_0.register_map\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Examining the PL state\n", + "\n", + "While there can be multiple overlay instances in Python, there is only one bitstream that is currently loaded onto the programmable logic (PL). \n", + "\n", + "This bitstream state is held in the singleton class, PL, and is available for user queries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "PL.bitfile_name" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "PL.timestamp\n", + "\n", + "PL.ip_dict\n", + "\n", + "leds_address = PL.ip_dict['led_4bits']['phys_addr']\n", + " \n", + "from pynq import MMIO\n", + "mmio_buttons = MMIO(0xa0000000, 16)\n", + "help (mmio_buttons)\n", + "\n", + "#print(hex(mmio_buttons))\n", + "#print(hex(mmio_buttons.read(0)))\n", + "\n", + "hex(pl.ip_dict[\"axi_gpio_1\"][\"phys_addr\"])\n", + "\n", + "\n", + "#buttons_address = ssc_dpram.ip_dict['push_button_4bits']['phys_addr']\n", + "#switches_address = ssc_dpram.ip_dict['dip_switch_4bits']['phys_addr']\n", + "#leds_address = ssc_dpram.ip_dict['led_4bitss']['phys_addr']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Users can verify whether an overlay instance is currently loaded using the Overlay is_loaded() method" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ol.is_loaded()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Overlay downloading overhead\n", + "\n", + "Finally, using Python, we can see the bitstream download time over 50 downloads. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "import matplotlib.pyplot as plt\n", + "\n", + "length = 50\n", + "time_log = []\n", + "for i in range(length):\n", + " start = time.time()\n", + " ol.download()\n", + " end = time.time()\n", + " time_log.append((end-start)*1000)\n", + "\n", + "%matplotlib inline\n", + "plt.plot(range(length), time_log, 'ro')\n", + "plt.title('Bitstream loading time (ms)')\n", + "plt.axis([0, length, 0, 1000])\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +}