{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "e1008e94",
      "metadata": {},
      "source": [
        "### License\n",
        "Copyright (C) 2021-2022, Xilinx, Inc.\n",
        "<br>\n",
        "Copyright (C) 2022-2024, Advanced Micro Devices, Inc.\n",
        "<p>\n",
        "Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "you may not use this file except in compliance with the License.\n",
        "<p>\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\n",
        "distributed under the License is distributed on an \"AS IS\" BASIS, \n",
        "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "See the License for the specific language governing permissions and\n",
        "limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b3ae6c31",
      "metadata": {},
      "source": [
        "# IBERT Landlocked GTYP decoupling example"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2e1b13cf",
      "metadata": {},
      "source": [
        "## Description\n",
        "This example shows how to interact with Landlocked (CPM5-controlled) GTYP with ChipScoPy APIs.\n",
        "- Program the pcie-ced design with Quad104 and Quad105 onto Production vpk120 board.\n",
        "- Verify that the expected IBERT quads are instantiated by the design\n",
        "- Decouple the quads from CPM5\n",
        "- Change rate for all the links in those quads\n",
        "- Plot Eye Scan diagram for these links\n",
        "\n",
        "## Requirements\n",
        "- Xilinx vpk120 production board\n",
        "- PCIE Loopback card\n",
        "- Xilinx hw_server 2024.1 installed and running\n",
        "- Xilinx cs_server 2024.1 installed and running\n",
        "- Python 3.8 or greater installed\n",
        "- ChipScoPy 2024.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",
      "id": "0ca6b89c",
      "metadata": {},
      "source": [
        "## 1 - Initialization: Imports\n",
        "Import required functions and classes"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "53ceb800",
      "metadata": {},
      "outputs": [],
      "source": [
        "import os\n",
        "from more_itertools import one\n",
        "from itertools import product\n",
        "\n",
        "from chipscopy import create_session, report_versions, report_hierarchy, get_design_files\n",
        "from chipscopy.api.ibert.aliases import (\n",
        "    PATTERN,\n",
        "    RX_LOOPBACK,\n",
        "    EYE_SCAN_HORZ_STEP,\n",
        "    EYE_SCAN_VERT_STEP,\n",
        "    EYE_SCAN_HORZ_RANGE,\n",
        "    EYE_SCAN_VERT_RANGE,\n",
        "    EYE_SCAN_TARGET_BER,\n",
        ")\n",
        "from chipscopy.api.ibert import  create_links, create_eye_scans"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "84d97f97",
      "metadata": {},
      "source": [
        "## 2 - Define some helper functions to achieve decoupling\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "e4eef47c",
      "metadata": {},
      "outputs": [],
      "source": [
        "def is_quad_decoupled(quad):\n",
        "    prop_name = \"CAPTIVE_QUAD_DECOUPLED\"\n",
        "    prop_val = quad.property.refresh(prop_name)[prop_name]\n",
        "    print(f\"{prop_name} = {prop_val}\")\n",
        "    \n",
        "def decouple_quad_using_prop(quad):\n",
        "    props = {\n",
        "        \"CAPTIVE_QUAD_DECOUPLE\": 1,\n",
        "    }\n",
        "    quad.property.set(**props)\n",
        "    quad.property.commit(list(props.keys()))\n",
        "\n",
        "def decouple_gtyp_quad(quads):\n",
        "    print(f\"\\n--------> Decouple GTYPs from CPM5\")\n",
        "    for quad in quads:\n",
        "        decouple_quad_using_prop(quad)\n",
        "        is_quad_decoupled(quad)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "dd96417c",
      "metadata": {},
      "source": [
        "## 3 - Define some helper functions to achieve rate change\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "fc484ce0",
      "metadata": {},
      "outputs": [],
      "source": [
        "def get_current_channel_rate(quad):\n",
        "    prop_name = \"CAPTIVE_QUAD_PCIE_RATE\"\n",
        "    prop_val = quad.property.refresh(prop_name)[prop_name]\n",
        "    print(f\"{prop_name} = {prop_val}\")\n",
        "\n",
        "def set_channel_rate_using_prop(quad, rate):\n",
        "    props = {\n",
        "        \"CAPTIVE_QUAD_PCIE_RATE\": rate,\n",
        "    }\n",
        "    quad.property.set(**props)\n",
        "    quad.property.commit(list(props.keys()))\n",
        "    \n",
        "def setRate(quads, rate):\n",
        "    print(f\"\\n--------> Setting line rate to {rate}\")\n",
        "    for quad in quads:\n",
        "        set_channel_rate_using_prop(quad, rate)\n",
        "        get_current_channel_rate(quad)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "32143f61",
      "metadata": {},
      "source": [
        "## 4- Define helper functions to set and report link properties"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "e1565764",
      "metadata": {},
      "outputs": [],
      "source": [
        "def setLinkProperties(links):\n",
        "    print(\"--------> Setting both Tx and RX patterns to 'PRBS 7' & loopback to 'Near-End PMA' for all links\")\n",
        "    for link in links:\n",
        "        props = {link.tx.property_for_alias[PATTERN]: \"PRBS 7\"}\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 7\",\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",
        "\n",
        "def printLinkProperties(links):\n",
        "    for link in links:\n",
        "        current_txpattern = list(link.tx.property.refresh(link.tx.property_for_alias[PATTERN]).values())[0]\n",
        "        current_rxpattern = list(link.tx.property.refresh(link.rx.property_for_alias[PATTERN]).values())[0]\n",
        "        current_rxloopback = list(link.tx.property.refresh(link.rx.property_for_alias[RX_LOOPBACK]).values())[0]\n",
        "        print(f\"\\n----- {link.name} -----\")\n",
        "        print(f\"Current value of TX pattern - {current_txpattern}\")\n",
        "        print(f\"Current value of RX pattern - {current_rxpattern}\")\n",
        "        print(f\"Current value of RX loopback - {current_rxloopback}\")\n",
        "        print(f\"Line Rate Detected = {link.status}.\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "721a4112",
      "metadata": {},
      "source": [
        "## 5- 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": null,
      "id": "4c7dd3f1",
      "metadata": {},
      "outputs": [],
      "source": [
        "CS_URL = os.getenv(\"CS_SERVER_URL\", \"TCP:localhost:3042\")\n",
        "HW_URL = os.getenv(\"HW_SERVER_URL\", \"TCP:localhost:3121\")\n",
        "\n",
        "session = create_session(cs_server_url=CS_URL, hw_server_url=HW_URL)\n",
        "report_versions(session)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "73a4b8e3",
      "metadata": {},
      "source": [
        "## 6 - Program the device with vpk120 pcie-ced design and discover cores"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "4cd4d4c2",
      "metadata": {},
      "outputs": [],
      "source": [
        "design_files = get_design_files(\"vpk120/production/pcie_pio_ced/\")\n",
        "\n",
        "PDI_FILE = design_files.programming_file\n",
        "\n",
        "print(f\"PROGRAMMING_FILE: {PDI_FILE}\")\n",
        "\n",
        "device = session.devices.filter_by(family=\"versal\").get()\n",
        "device.program(PDI_FILE)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1e500ff1",
      "metadata": {},
      "source": [
        "## 7 - 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": null,
      "id": "7d5145f4",
      "metadata": {},
      "outputs": [],
      "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_gtyp = one(device.ibert_cores.filter_by(name=\"IBERT Versal GTYP\"))\n",
        "\n",
        "if len(ibert_gtyp.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_gtyp.gt_groups]}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d430a8b1",
      "metadata": {},
      "source": [
        "## 8 - 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": null,
      "id": "3f45ca31",
      "metadata": {},
      "outputs": [],
      "source": [
        "report_hierarchy(ibert_gtyp)\n",
        "\n",
        "gt_group = ibert_gtyp.gt_groups.filter_by(name=\"Quad_104\")[0]\n",
        "\n",
        "q104 = one(ibert_gtyp.gt_groups.filter_by(name=\"Quad_104\"))\n",
        "q105 = one(ibert_gtyp.gt_groups.filter_by(name=\"Quad_105\"))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f18b21f0",
      "metadata": {},
      "source": [
        "## 9 - Create links between following TXs and RXs and set loopback mode\n",
        "\n",
        "- Quad 104 CH0 TX to Quad 104 CH0 RX\n",
        "- Quad 104 CH1 TX to Quad 104 CH1 RX\n",
        "- Quad 104 CH2 TX to Quad 104 CH3 RX\n",
        "- Quad 104 CH3 TX to Quad 104 CH3 RX\n",
        "- Quad 105 CH0 TX to Quad 105 CH0 RX\n",
        "- Quad 105 CH1 TX to Quad 105 CH1 RX\n",
        "- Quad 105 CH3 TX to Quad 105 CH3 RX\n",
        "- Quad 105 CH3 TX to Quad 105 CH3 RX"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "76fc2c6b",
      "metadata": {},
      "outputs": [],
      "source": [
        "links = create_links(\n",
        "    txs=[q104.gts[0].tx, q104.gts[1].tx, q104.gts[2].tx, q104.gts[3].tx, q105.gts[0].tx, q105.gts[1].tx, q105.gts[2].tx, q105.gts[3].tx],\n",
        "    rxs=[q104.gts[0].rx, q104.gts[1].rx, q104.gts[2].rx, q104.gts[3].rx, q105.gts[0].rx, q105.gts[1].rx, q105.gts[2].rx, q105.gts[3].rx],\n",
        ")\n",
        "\n",
        "print(\"--> Done creating links\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "64bd9267",
      "metadata": {},
      "source": [
        "## 10 - Decouple Quads from CPM5"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "3f203af8",
      "metadata": {},
      "outputs": [],
      "source": [
        "land_Locked_Quads = [q104,q105]\n",
        "#Decouple GTYPs from CPM5\n",
        "decouple_gtyp_quad(land_Locked_Quads)\n",
        "\n",
        "#set loopback mode with Tx and Rx pattern\n",
        "setLinkProperties(links)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c2a7ca82",
      "metadata": {},
      "source": [
        "## 11 - Set rate to Gen1"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "1337754c",
      "metadata": {},
      "outputs": [],
      "source": [
        "#set line rate\n",
        "setRate(land_Locked_Quads, 'Gen1')\n",
        "printLinkProperties(links)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cdd42d3d",
      "metadata": {},
      "source": [
        "## 12 - Create Eye Scan Diagrams"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bea574d5-4a9d-487e-8d30-bfe435f55770",
      "metadata": {},
      "source": [
        "#### Check if PLL is locked and link is up before performing Eye Scan "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "b64361a0-9e89-42ed-8846-6e8526ffde79",
      "metadata": {},
      "outputs": [],
      "source": [
        "for link in links:\n",
        "    assert link.rx.pll.locked and link.tx.pll.locked\n",
        "    print(f\"--> RX and TX PLLs are locked for {link}\")\n",
        "    assert link.status != \"No link\"\n",
        "    print(f\"--> {link} is linked as expected\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a16f68b1",
      "metadata": {},
      "outputs": [],
      "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",
      "id": "90aedd32",
      "metadata": {},
      "source": [
        "## 13 - Wait for all the eye scans to get done"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "7e609b6e",
      "metadata": {},
      "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()\n",
        "eye_scans[4].wait_till_done()\n",
        "eye_scans[5].wait_till_done()\n",
        "eye_scans[6].wait_till_done()\n",
        "eye_scans[7].wait_till_done()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "897a3585",
      "metadata": {},
      "source": [
        "## 14 - View Eye Scan Plot.\n",
        "\n",
        "This requires Plotly to be installed. See how to install it [here](https://xilinx.github.io/chipscopy/2024.1/ibert/eye_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": null,
      "id": "ad1c8b1a",
      "metadata": {},
      "outputs": [],
      "source": [
        "eye_scans[0].plot.show()\n",
        "eye_scans[1].plot.show()\n",
        "eye_scans[2].plot.show()\n",
        "eye_scans[3].plot.show()\n",
        "eye_scans[4].plot.show()\n",
        "eye_scans[5].plot.show()\n",
        "eye_scans[6].plot.show()\n",
        "eye_scans[7].plot.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "2e462716",
      "metadata": {},
      "source": [
        "## 15 - Set rate to Gen2"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "b7aba93c",
      "metadata": {},
      "outputs": [],
      "source": [
        "#set line rate\n",
        "setRate(land_Locked_Quads, 'Gen2')\n",
        "printLinkProperties(links)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "861e70a0",
      "metadata": {},
      "source": [
        "## 16 - Create Eye Scan Diagrams"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cce53a79-5464-405a-9353-2f3e196a2c73",
      "metadata": {},
      "source": [
        "#### Check if PLL is locked and link is up before performing Eye Scan "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "477b759a-6481-49b8-ae53-e663d8d3c5f3",
      "metadata": {},
      "outputs": [],
      "source": [
        "for link in links:\n",
        "    assert link.rx.pll.locked and link.tx.pll.locked\n",
        "    print(f\"--> RX and TX PLLs are locked for {link}\")\n",
        "    assert link.status != \"No link\"\n",
        "    print(f\"--> {link} is linked as expected\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f75807df",
      "metadata": {},
      "outputs": [],
      "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",
      "id": "5d49ff1a",
      "metadata": {},
      "source": [
        "## 17 - Wait for all the eye scans to get done"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "bafc893d",
      "metadata": {},
      "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()\n",
        "eye_scans[4].wait_till_done()\n",
        "eye_scans[5].wait_till_done()\n",
        "eye_scans[6].wait_till_done()\n",
        "eye_scans[7].wait_till_done()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cb2757d7",
      "metadata": {},
      "source": [
        "## 18 - View Eye Scan Plot."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "ebc9437e",
      "metadata": {},
      "outputs": [],
      "source": [
        "eye_scans[0].plot.show()\n",
        "eye_scans[1].plot.show()\n",
        "eye_scans[2].plot.show()\n",
        "eye_scans[3].plot.show()\n",
        "eye_scans[4].plot.show()\n",
        "eye_scans[5].plot.show()\n",
        "eye_scans[6].plot.show()\n",
        "eye_scans[7].plot.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "77b83df6",
      "metadata": {},
      "source": [
        "## 19 - Set rate to Gen3"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "dc3f551c",
      "metadata": {},
      "outputs": [],
      "source": [
        "#set line rate\n",
        "setRate(land_Locked_Quads, 'Gen3')\n",
        "printLinkProperties(links)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a8ca76b9",
      "metadata": {},
      "source": [
        "## 20 - Create Eye Scan Diagrams"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5c1ab7db-0031-4846-a651-628410fa990d",
      "metadata": {},
      "source": [
        "#### Check if PLL is locked and link is up before performing Eye Scan "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "27ca3c0d-92a2-4b80-bc97-68b5cabbebd6",
      "metadata": {},
      "outputs": [],
      "source": [
        "for link in links:\n",
        "    assert link.rx.pll.locked and link.tx.pll.locked\n",
        "    print(f\"--> RX and TX PLLs are locked for {link}\")\n",
        "    assert link.status != \"No link\"\n",
        "    print(f\"--> {link} is linked as expected\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "cdb18c19",
      "metadata": {},
      "outputs": [],
      "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",
      "id": "0705e089",
      "metadata": {},
      "source": [
        "## 21 - Wait for all the eye scans to get done"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "dff65817",
      "metadata": {},
      "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()\n",
        "eye_scans[4].wait_till_done()\n",
        "eye_scans[5].wait_till_done()\n",
        "eye_scans[6].wait_till_done()\n",
        "eye_scans[7].wait_till_done()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "526dc762",
      "metadata": {},
      "source": [
        "## 22 - View Eye Scan Plot."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "b99b3078",
      "metadata": {},
      "outputs": [],
      "source": [
        "eye_scans[0].plot.show()\n",
        "eye_scans[1].plot.show()\n",
        "eye_scans[2].plot.show()\n",
        "eye_scans[3].plot.show()\n",
        "eye_scans[4].plot.show()\n",
        "eye_scans[5].plot.show()\n",
        "eye_scans[6].plot.show()\n",
        "eye_scans[7].plot.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "19262e27",
      "metadata": {},
      "source": [
        "## 23 - Set rate to Gen4"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "449eaf6d",
      "metadata": {},
      "outputs": [],
      "source": [
        "#set line rate\n",
        "setRate(land_Locked_Quads, 'Gen4')\n",
        "printLinkProperties(links)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6ff67daf",
      "metadata": {},
      "source": [
        "## 24 - Create Eye Scan Diagrams"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9fff9707-27b6-4729-9d23-88655f5f5369",
      "metadata": {},
      "source": [
        "#### Check if PLL is locked and link is up before performing Eye Scan "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "090b4a47-b5e5-473e-96fd-ec05b654312f",
      "metadata": {},
      "outputs": [],
      "source": [
        "for link in links:\n",
        "    assert link.rx.pll.locked and link.tx.pll.locked\n",
        "    print(f\"--> RX and TX PLLs are locked for {link}\")\n",
        "    assert link.status != \"No link\"\n",
        "    print(f\"--> {link} is linked as expected\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "7cee7bb3",
      "metadata": {},
      "outputs": [],
      "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",
      "id": "de70efa7",
      "metadata": {},
      "source": [
        "## 25 - Wait for all the eye scans to get done"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "74752ac8",
      "metadata": {},
      "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()\n",
        "eye_scans[4].wait_till_done()\n",
        "eye_scans[5].wait_till_done()\n",
        "eye_scans[6].wait_till_done()\n",
        "eye_scans[7].wait_till_done()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "27533847",
      "metadata": {},
      "source": [
        "## 26 - View Eye Scan Plot"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "23285c58",
      "metadata": {},
      "outputs": [],
      "source": [
        "eye_scans[0].plot.show()\n",
        "eye_scans[1].plot.show()\n",
        "eye_scans[2].plot.show()\n",
        "eye_scans[3].plot.show()\n",
        "eye_scans[4].plot.show()\n",
        "eye_scans[5].plot.show()\n",
        "eye_scans[6].plot.show()\n",
        "eye_scans[7].plot.show()"
      ]
    }
  ],
  "metadata": {
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
