{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "scrolled": false
   },
   "source": [
    "<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\">\n",
    "<link href=\"https://fonts.googleapis.com/css2?family=Fira+Code&display=swap\" rel=\"stylesheet\">\n",
    "\n",
    "### License\n",
    "\n",
    "<p style=\"font-family: 'Fira Code', monospace; font-size: 1.2rem\">\n",
    "Copyright 2021 Xilinx, Inc.<br><br>\n",
    "Licensed under the Apache License, Version 2.0 (the \"License\");<br>\n",
    "you may not use this file except in compliance with the License.<br><br>\n",
    "You may obtain a copy of the License at <a href=\"http://www.apache.org/licenses/LICENSE-2.0\"?>http://www.apache.org/licenses/LICENSE-2.0</a><br><br>\n",
    "Unless required by applicable law or agreed to in writing, software<br>\n",
    "distributed under the License is distributed on an \"AS IS\" BASIS,<br>\n",
    "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.<br>\n",
    "See the License for the specific language governing permissions and<br>\n",
    "limitations under the License.<br>\n",
    "</p>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# IBERT link and eye scan example\n",
    "\n",
    "\n",
    "<img src=\"../../img/api_overview.png\" width=\"500\" align=\"left\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Description\n",
    "This example shows how to interact with the IBERT (Integrated Bit Error Ratio Tester) debug core service via ChipScoPy APIs.\n",
    "- Program the ChipScoPy CED design onto the XCVC1902 device on a VCK190 board\n",
    "- Verify that the expected IBERT quads are instantiated by the design\n",
    "- Create links and change link settings to get link lock\n",
    "- Run and plot eye scans for the links\n",
    "\n",
    "\n",
    "## Requirements\n",
    "- Local or remote Xilinx Versal board, such as a VCK190\n",
    "- Xilinx hw_server 2022.1 installed and running\n",
    "- Xilinx cs_server 2022.1 installed and running\n",
    "- Python 3.8 or greater installed\n",
    "- ChipScoPy 2022.1 installed\n",
    "- Jupyter notebook support installed - Please do so, using the command `pip install chipscopy[jupyter]`\n",
    "- Plotting support installed - Please do so, using the command `pip install chipscopy[core-addons]`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1 - Initialization: Imports and File Paths\n",
    "\n",
    "After this step,\n",
    "- Required functions and classes are imported\n",
    "- Paths to server(s) and files are set correctly"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "lines_to_next_cell": 2,
    "pycharm": {
     "name": "#%%\n"
    },
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "import os\n",
    "from more_itertools import one\n",
    "\n",
    "from chipscopy import create_session, report_versions, report_hierarchy, get_design_files\n",
    "from chipscopy.api.ibert.aliases import (\n",
    "    EYE_SCAN_HORZ_RANGE,\n",
    "    EYE_SCAN_VERT_RANGE,\n",
    "    EYE_SCAN_VERT_STEP,\n",
    "    EYE_SCAN_HORZ_STEP,\n",
    "    EYE_SCAN_TARGET_BER,\n",
    "    PATTERN,\n",
    "    RX_LOOPBACK,\n",
    ")\n",
    "from chipscopy.api.ibert import create_eye_scans, create_links"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PROGRAMMING_FILE: C:\\wrk\\chipscopy\\chipscopy-venv\\Lib\\site-packages\\chipscopy\\examples\\designs\\vck190\\production\\chipscopy_ced\\chipscopy_wrapper.pdi\n"
     ]
    }
   ],
   "source": [
    "# Make sure to start the hw_server and cs_server prior to running.\n",
    "# Specify locations of the running hw_server and cs_server below.\n",
    "# The default is localhost - but can be other locations on the network.\n",
    "CS_URL = os.getenv(\"CS_SERVER_URL\", \"TCP:localhost:3042\")\n",
    "HW_URL = os.getenv(\"HW_SERVER_URL\", \"TCP:localhost:3121\")\n",
    "\n",
    "# The get_design_files() function tries to find the PDI and LTX files. In non-standard\n",
    "# configurations, you can put the path for PROGRAMMING_FILE and PROBES_FILE below.\n",
    "design_files = get_design_files(\"vck190/production/chipscopy_ced\")\n",
    "\n",
    "PDI_FILE = design_files.programming_file\n",
    "\n",
    "print(f\"PROGRAMMING_FILE: {PDI_FILE}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2 - Create a session and connect to the hw_server and cs_server\n",
    "\n",
    "The session is a container that keeps track of devices and debug cores.\n",
    "After this step,\n",
    "- Session is initialized and connected to server(s)\n",
    "- Versions are detected and reported to stdout"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "<span style=\"color: #808000; text-decoration-color: #808000; font-weight: bold\">--&gt; WARNING: </span><span style=\"color: #808000; text-decoration-color: #808000; font-style: italic\">A client/server version mismatch was detected while connecting!</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000; font-style: italic\">       ChipScoPy client version - 2022.2.0</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000; font-style: italic\">       hw_server version        - 2022.1.0</span>\n",
       "<span style=\"color: #808000; text-decoration-color: #808000; font-style: italic\">       cs_server version        - 2022.1.0</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x15a4e2db940>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x15a4e2dbbb0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-style: italic\">                         ChipScoPy Version Information                          </span>\n",
       "┌────────────────────────────┬─────────────────────────────────────────────────┐\n",
       "│<span style=\"font-weight: bold\">                     Entity </span>│<span style=\"font-weight: bold\"> Version                                         </span>│\n",
       "├────────────────────────────┼─────────────────────────────────────────────────┤\n",
       "│                  ChipScoPy │ ┌───────────┬──────────────────────┐            │\n",
       "│                            │ │<span style=\"font-weight: bold\"> Attribute </span>│<span style=\"font-weight: bold\"> Value                </span>│            │\n",
       "│                            │ ├───────────┼──────────────────────┤            │\n",
       "│                            │ │     Build │ 2022.2.1654226650    │            │\n",
       "│                            │ │ Timestamp │ Jun 02 2022-21:24:10 │            │\n",
       "│                            │ └───────────┴──────────────────────┘            │\n",
       "│                            │                                                 │\n",
       "│ hw_server @ localhost:3121 │ ┌───────────┬─────────────────────────────────┐ │\n",
       "│                            │ │<span style=\"font-weight: bold\"> Attribute </span>│<span style=\"font-weight: bold\"> Value                           </span>│ │\n",
       "│                            │ ├───────────┼─────────────────────────────────┤ │\n",
       "│                            │ │    Status │ Connected                       │ │\n",
       "│                            │ │     Build │ 1641456835                      │ │\n",
       "│                            │ │   Version │ 2022.1                          │ │\n",
       "│                            │ │ Timestamp │ Thu 06 Jan 2022 08:13:55 AM UTC │ │\n",
       "│                            │ └───────────┴─────────────────────────────────┘ │\n",
       "│                            │                                                 │\n",
       "│ cs_server @ localhost:3042 │ ┌───────────────┬──────────────────────┐        │\n",
       "│                            │ │<span style=\"font-weight: bold\">     Attribute </span>│<span style=\"font-weight: bold\"> Value                </span>│        │\n",
       "│                            │ ├───────────────┼──────────────────────┤        │\n",
       "│                            │ │        Status │ Connected            │        │\n",
       "│                            │ │         Build │ 1649790728           │        │\n",
       "│                            │ │       Version │ 2022.1.0             │        │\n",
       "│                            │ │     Timestamp │ Apr 12 2022-13:12:08 │        │\n",
       "│                            │ │       Package │ 2022.1.1649790728    │        │\n",
       "│                            │ │ Artifact type │ pyinstaller          │        │\n",
       "│                            │ └───────────────┴──────────────────────┘        │\n",
       "└────────────────────────────┴─────────────────────────────────────────────────┘\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x15a4e2db640>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x15a4e2dbbe0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "session = create_session(cs_server_url=CS_URL, hw_server_url=HW_URL)\n",
    "report_versions(session)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3 - Program the device with the example design\n",
    "\n",
    "After this step,\n",
    "- Device is programmed with the example programming file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "<span style=\"font-weight: bold\">--&gt; INFO: </span>Programming device with: C:\\wrk\\chipscopy\\chipscopy-venv\\Lib\\site-packages\\chipscop\n",
       "y\\examples\\designs\\vck190\\production\\chipscopy_ced\\chipscopy_wrapper.pdi\n",
       "    \n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x15a4e3b5f40>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "b4a25df57f1a41a59db521517d1bd0e6",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Typical case - one device on the board - get it.\n",
    "device = session.devices.filter_by(family=\"versal\").get()\n",
    "device.program(PDI_FILE)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4 - Discover and setup the IBERT core\n",
    "\n",
    "Debug core discovery initializes the chipscope server debug cores.\n",
    "\n",
    "After this step,\n",
    "\n",
    "- The cs_server is initialized and ready for use\n",
    "- The first ibert found is used"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--> Debug core discovery done\n",
      "GT Groups available - ['Quad_205', 'Quad_204', 'Quad_201', 'Quad_105']\n"
     ]
    }
   ],
   "source": [
    "device.discover_and_setup_cores(ibert_scan=True)\n",
    "print(\"--> Debug core discovery done\")\n",
    "\n",
    "if len(device.ibert_cores) == 0:\n",
    "    print(\"No IBERT core found! Exiting...\")\n",
    "    exit()\n",
    "\n",
    "# Use the first available IBERT core from the device\n",
    "ibert = device.ibert_cores.at(index=0)\n",
    "\n",
    "if len(ibert.gt_groups) == 0:\n",
    "    print(\"No GT Groups available for use! Exiting...\")\n",
    "    exit()\n",
    "\n",
    "print(f\"GT Groups available - {[gt_group_obj.name for gt_group_obj in ibert.gt_groups]}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5 - Print the hierarchy of the IBERT core\n",
    "\n",
    "We also ensure that all the quads instantiated by the ChipScoPy CED design are found by the APIs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    },
    "pycharm": {
     "name": "#%%\n"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">IBERT Versal GTY                                                                             \n",
       "├── Quad_205                                                                                 \n",
       "│   ├── PLL_0                                                                                \n",
       "│   ├── PLL_1                                                                                \n",
       "│   ├── PLL_2                                                                                \n",
       "│   ├── PLL_3                                                                                \n",
       "│   ├── CH_0                                                                                 \n",
       "│   │   ├── TX                                                                               \n",
       "│   │   └── RX                                                                               \n",
       "│   ├── CH_1                                                                                 \n",
       "│   │   ├── TX                                                                               \n",
       "│   │   └── RX                                                                               \n",
       "│   ├── CH_2                                                                                 \n",
       "│   │   ├── TX                                                                               \n",
       "│   │   └── RX                                                                               \n",
       "│   └── CH_3                                                                                 \n",
       "│       ├── TX                                                                               \n",
       "│       └── RX                                                                               \n",
       "├── Quad_204                                                                                 \n",
       "│   ├── PLL_0                                                                                \n",
       "│   ├── PLL_1                                                                                \n",
       "│   ├── PLL_2                                                                                \n",
       "│   ├── PLL_3                                                                                \n",
       "│   ├── CH_0                                                                                 \n",
       "│   │   ├── TX                                                                               \n",
       "│   │   └── RX                                                                               \n",
       "│   ├── CH_1                                                                                 \n",
       "│   │   ├── TX                                                                               \n",
       "│   │   └── RX                                                                               \n",
       "│   ├── CH_2                                                                                 \n",
       "│   │   ├── TX                                                                               \n",
       "│   │   └── RX                                                                               \n",
       "│   └── CH_3                                                                                 \n",
       "│       ├── TX                                                                               \n",
       "│       └── RX                                                                               \n",
       "├── Quad_201                                                                                 \n",
       "│   ├── PLL_0                                                                                \n",
       "│   ├── PLL_1                                                                                \n",
       "│   ├── PLL_2                                                                                \n",
       "│   ├── PLL_3                                                                                \n",
       "│   ├── CH_0                                                                                 \n",
       "│   │   ├── TX                                                                               \n",
       "│   │   └── RX                                                                               \n",
       "│   ├── CH_1                                                                                 \n",
       "│   │   ├── TX                                                                               \n",
       "│   │   └── RX                                                                               \n",
       "│   ├── CH_2                                                                                 \n",
       "│   │   ├── TX                                                                               \n",
       "│   │   └── RX                                                                               \n",
       "│   └── CH_3                                                                                 \n",
       "│       ├── TX                                                                               \n",
       "│       └── RX                                                                               \n",
       "└── Quad_105                                                                                 \n",
       "    ├── PLL_0                                                                                \n",
       "    ├── PLL_1                                                                                \n",
       "    ├── PLL_2                                                                                \n",
       "    ├── PLL_3                                                                                \n",
       "    ├── CH_0                                                                                 \n",
       "    │   ├── TX                                                                               \n",
       "    │   └── RX                                                                               \n",
       "    ├── CH_1                                                                                 \n",
       "    │   ├── TX                                                                               \n",
       "    │   └── RX                                                                               \n",
       "    ├── CH_2                                                                                 \n",
       "    │   ├── TX                                                                               \n",
       "    │   └── RX                                                                               \n",
       "    └── CH_3                                                                                 \n",
       "        ├── TX                                                                               \n",
       "        └── RX                                                                               \n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x15a4e172fa0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "report_hierarchy(ibert)\n",
    "\n",
    "assert len(ibert.gt_groups) == 4\n",
    "\n",
    "q205 = one(ibert.gt_groups.filter_by(name=\"Quad_205\"))\n",
    "q204 = one(ibert.gt_groups.filter_by(name=\"Quad_204\"))\n",
    "q201 = one(ibert.gt_groups.filter_by(name=\"Quad_201\"))\n",
    "q105 = one(ibert.gt_groups.filter_by(name=\"Quad_105\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6 - Create links between following TXs and RXs\n",
    "- Quad 205 CH0 TX to Quad 205 CH0 RX\n",
    "- Quad 204 CH1 TX to Quad 204 CH1 RX\n",
    "- Quad 201 CH2 TX to Quad 201 CH2 RX\n",
    "- Quad 105 CH3 TX to Quad 105 CH3 RX"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--> Done creating links\n"
     ]
    }
   ],
   "source": [
    "links = create_links(\n",
    "    txs=[q205.gts[0].tx, q204.gts[1].tx, q201.gts[2].tx, q105.gts[3].tx],\n",
    "    rxs=[q205.gts[0].rx, q204.gts[1].rx, q201.gts[2].rx, q105.gts[3].rx],\n",
    ")\n",
    "\n",
    "print(\"--> Done creating links\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "raw_mimetype": "text/markdown"
   },
   "source": [
    "## 7 - Print the valid values for pattern and loopback, set the pattern for the TXs and RXs to \"PRBS 31\" and set loopback to \"Near-End PMA\"\n",
    "\n",
    "In order to lock the internal pattern checker, TX and RX patterns need to match. We also need to have some kind of loopback, internal/external.\n",
    "\n",
    "We are assuming that no external cable loopback is present and hence making use of internal loopback."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "raw_mimetype": "text/x-python",
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "----- Link_0 -----\n",
      "--> Valid values for TX pattern - ['User Design', 'PRBS Disabled', 'PRBS 7', 'PRBS 9', 'PRBS 15', 'PRBS 23', 'PRBS 31', 'Configurable data pattern', 'Square wave (2 * UI)', 'Square wave (Int data width * UI)']\n",
      "--> Valid values for RX pattern - ['User Design', 'PRBS Disabled', 'PRBS 7', 'PRBS 9', 'PRBS 15', 'PRBS 23', 'PRBS 31']\n",
      "--> Valid values for RX loopback - ['User Design', 'None', 'Near-End PCS', 'Far-End PCS', 'Near-End PMA', 'Far-End PMA']\n",
      "\n",
      "--> Set both patterns to 'PRBS 31' & loopback to 'Near-End PMA' for Link_0\n",
      "--> RX and TX PLLs are locked for Link_0. Checking for link lock...\n",
      "--> Link_0 is linked as expected\n",
      "\n",
      "----- Link_1 -----\n",
      "--> Valid values for TX pattern - ['User Design', 'PRBS Disabled', 'PRBS 7', 'PRBS 9', 'PRBS 15', 'PRBS 23', 'PRBS 31', 'Configurable data pattern', 'Square wave (2 * UI)', 'Square wave (Int data width * UI)']\n",
      "--> Valid values for RX pattern - ['User Design', 'PRBS Disabled', 'PRBS 7', 'PRBS 9', 'PRBS 15', 'PRBS 23', 'PRBS 31']\n",
      "--> Valid values for RX loopback - ['User Design', 'None', 'Near-End PCS', 'Far-End PCS', 'Near-End PMA', 'Far-End PMA']\n",
      "\n",
      "--> Set both patterns to 'PRBS 31' & loopback to 'Near-End PMA' for Link_1\n",
      "--> RX and TX PLLs are locked for Link_1. Checking for link lock...\n",
      "--> Link_1 is linked as expected\n",
      "\n",
      "----- Link_2 -----\n",
      "--> Valid values for TX pattern - ['User Design', 'PRBS Disabled', 'PRBS 7', 'PRBS 9', 'PRBS 15', 'PRBS 23', 'PRBS 31', 'Configurable data pattern', 'Square wave (2 * UI)', 'Square wave (Int data width * UI)']\n",
      "--> Valid values for RX pattern - ['User Design', 'PRBS Disabled', 'PRBS 7', 'PRBS 9', 'PRBS 15', 'PRBS 23', 'PRBS 31']\n",
      "--> Valid values for RX loopback - ['User Design', 'None', 'Near-End PCS', 'Far-End PCS', 'Near-End PMA', 'Far-End PMA']\n",
      "\n",
      "--> Set both patterns to 'PRBS 31' & loopback to 'Near-End PMA' for Link_2\n",
      "--> RX and TX PLLs are locked for Link_2. Checking for link lock...\n",
      "--> Link_2 is linked as expected\n",
      "\n",
      "----- Link_3 -----\n",
      "--> Valid values for TX pattern - ['User Design', 'PRBS Disabled', 'PRBS 7', 'PRBS 9', 'PRBS 15', 'PRBS 23', 'PRBS 31', 'Configurable data pattern', 'Square wave (2 * UI)', 'Square wave (Int data width * UI)']\n",
      "--> Valid values for RX pattern - ['User Design', 'PRBS Disabled', 'PRBS 7', 'PRBS 9', 'PRBS 15', 'PRBS 23', 'PRBS 31']\n",
      "--> Valid values for RX loopback - ['User Design', 'None', 'Near-End PCS', 'Far-End PCS', 'Near-End PMA', 'Far-End PMA']\n",
      "\n",
      "--> Set both patterns to 'PRBS 31' & loopback to 'Near-End PMA' for Link_3\n",
      "--> RX and TX PLLs are locked for Link_3. Checking for link lock...\n",
      "--> Link_3 is linked as expected\n"
     ]
    }
   ],
   "source": [
    "for link in links:\n",
    "    print(f\"\\n----- {link.name} -----\")\n",
    "    _, tx_pattern_report = link.tx.property.report(link.tx.property_for_alias[PATTERN]).popitem()\n",
    "    _, rx_pattern_report = link.rx.property.report(link.rx.property_for_alias[PATTERN]).popitem()\n",
    "    _, rx_loopback_report = link.tx.property.report(\n",
    "        link.rx.property_for_alias[RX_LOOPBACK]\n",
    "    ).popitem()\n",
    "\n",
    "    print(f\"--> Valid values for TX pattern - {tx_pattern_report['Valid values']}\")\n",
    "    print(f\"--> Valid values for RX pattern - {rx_pattern_report['Valid values']}\")\n",
    "    print(f\"--> Valid values for RX loopback - {rx_loopback_report['Valid values']}\")\n",
    "\n",
    "    props = {link.tx.property_for_alias[PATTERN]: \"PRBS 31\"}\n",
    "    link.tx.property.set(**props)\n",
    "    link.tx.property.commit(list(props.keys()))\n",
    "\n",
    "    props = {\n",
    "        link.rx.property_for_alias[PATTERN]: \"PRBS 31\",\n",
    "        link.rx.property_for_alias[RX_LOOPBACK]: \"Near-End PMA\",\n",
    "    }\n",
    "    link.rx.property.set(**props)\n",
    "    link.rx.property.commit(list(props.keys()))\n",
    "    print(f\"\\n--> Set both patterns to 'PRBS 31' & loopback to 'Near-End PMA' for {link}\")\n",
    "\n",
    "    assert link.rx.pll.locked and link.tx.pll.locked\n",
    "    print(f\"--> RX and TX PLLs are locked for {link}. Checking for link lock...\")\n",
    "    assert link.status != \"No link\"\n",
    "    print(f\"--> {link} is linked as expected\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 8 - Create eye scan objects for all the links, set the scan params and start the scan\n",
    "\n",
    "The eye scans will be run in parallel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "lines_to_next_cell": 2,
    "pycharm": {
     "name": "#%%\n"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "74fe4e07812b406d8888e52ada249332",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Started eye scan EyeScan_1\n",
      "Started eye scan EyeScan_2\n",
      "Started eye scan EyeScan_3\n",
      "Started eye scan EyeScan_4\n"
     ]
    }
   ],
   "source": [
    "eye_scans = create_eye_scans(target_objs=[link for link in links])\n",
    "for eye_scan in eye_scans:\n",
    "    eye_scan.params[EYE_SCAN_HORZ_STEP].value = 2\n",
    "    eye_scan.params[EYE_SCAN_VERT_STEP].value = 2\n",
    "    eye_scan.params[EYE_SCAN_HORZ_RANGE].value = \"-0.500 UI to 0.500 UI\"\n",
    "    eye_scan.params[EYE_SCAN_VERT_RANGE].value = \"100%\"\n",
    "    eye_scan.params[EYE_SCAN_TARGET_BER].value = 1e-5\n",
    "\n",
    "    eye_scan.start()\n",
    "    print(f\"Started eye scan {eye_scan}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 9 - Wait for all the eye scans to get done"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "eye_scans[0].wait_till_done()\n",
    "eye_scans[1].wait_till_done()\n",
    "eye_scans[2].wait_till_done()\n",
    "eye_scans[3].wait_till_done()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "lines_to_next_cell": 2
   },
   "source": [
    "## 10 - View Eye Scan Plot.\n",
    "\n",
    "This requires Plotly to be installed. See how to install it [here](https://pages.gitenterprise.xilinx.com/chipscope/chipscopy/2020.2/ibert/scan.html#scan-plots)\n",
    "\n",
    "NOTE - The plot may not display if this notebook is run in Jupyter Lab. For details, see [link](https://plotly.com/python/getting-started/#jupyterlab-support-python-35)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 83504 characters]\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 68824 characters]\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 70536 characters]\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 71876 characters]\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "eye_scans[0].plot.show()\n",
    "eye_scans[1].plot.show()\n",
    "eye_scans[2].plot.show()\n",
    "eye_scans[3].plot.show()"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Raw Cell Format",
  "jupytext": {
   "formats": "ipynb,py:percent"
  },
  "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.8.10"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {
     "01b8c57b53164e0887e4450ad92dc3ff": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "1.2.0",
      "model_name": "LayoutModel",
      "state": {}
     },
     "60536ab8258d4f79a646324a2e5d60f8": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "layout": "IPY_MODEL_01b8c57b53164e0887e4450ad92dc3ff",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">EyeScan_1 progress  <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100%</span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Done</span>\nEyeScan_2 progress  <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100%</span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Done</span>\nEyeScan_3 progress  <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100%</span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Done</span>\nEyeScan_4 progress  <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100%</span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Done</span>\n</pre>\n",
          "text/plain": "<rich.jupyter.JupyterRenderable at 0x227c3959588>"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ]
      }
     },
     "b4b3a5fffe474781b949f3e5e8ec4d44": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "layout": "IPY_MODEL_f9378efc77904cccb1bb3683cd47e393",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">EyeScan_1 progress  <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100%</span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Done</span>\nEyeScan_2 progress  <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100%</span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Done</span>\nEyeScan_3 progress  <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100%</span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Done</span>\nEyeScan_4 progress  <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100%</span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Done</span>\n</pre>\n",
          "text/plain": "<rich.jupyter.JupyterRenderable at 0x1628a2c9c88>"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ]
      }
     },
     "d04c165339374fdaae5b775a1bbc80db": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "1.2.0",
      "model_name": "LayoutModel",
      "state": {}
     },
     "d38ca91e8c514ae88391583bc1db0a3d": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "layout": "IPY_MODEL_d04c165339374fdaae5b775a1bbc80db",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Device program progress <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100%</span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Done</span>\n</pre>\n",
          "text/plain": "<rich.jupyter.JupyterRenderable at 0x227bddf7908>"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ]
      }
     },
     "d4ed878d650c43cd9a8c559468d1cb6e": {
      "model_module": "@jupyter-widgets/output",
      "model_module_version": "1.0.0",
      "model_name": "OutputModel",
      "state": {
       "layout": "IPY_MODEL_f83f0a46fa034a94a988a3bb360aee42",
       "outputs": [
        {
         "data": {
          "text/html": "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">Device program progress <span style=\"color: #729c1f; text-decoration-color: #729c1f\">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</span> <span style=\"color: #800080; text-decoration-color: #800080\">100%</span> <span style=\"color: #008000; text-decoration-color: #008000; font-weight: bold\">Done</span>\n</pre>\n",
          "text/plain": "<rich.jupyter.JupyterRenderable at 0x162ffda2cc8>"
         },
         "metadata": {},
         "output_type": "display_data"
        }
       ]
      }
     },
     "f83f0a46fa034a94a988a3bb360aee42": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "1.2.0",
      "model_name": "LayoutModel",
      "state": {}
     },
     "f9378efc77904cccb1bb3683cd47e393": {
      "model_module": "@jupyter-widgets/base",
      "model_module_version": "1.2.0",
      "model_name": "LayoutModel",
      "state": {}
     }
    },
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
