{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "229f142a",
      "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": "d52776aa",
      "metadata": {},
      "source": [
        "# IBERT link and eye scan example\n",
        "\n",
        "\n",
        "<img src=\"../../img/api_overview.png\" width=\"500\" align=\"left\">"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "862a1951",
      "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",
        "- Run a sweep on a link\n",
        "\n",
        "\n",
        "## Requirements\n",
        "- Local or remote Xilinx Versal board, such as a VCK190\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]`\n",
        "- Optional - [External loopback](https://www.samtec.com/kits/optics-fpga/hspce-fmcp/) (For the sweep example only)."
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b9578481",
      "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,
      "id": "da6f53d0",
      "metadata": {},
      "outputs": [],
      "source": [
        "import os\n",
        "from more_itertools import one\n",
        "from itertools import product\n",
        "\n",
        "from chipscopy import (\n",
        "    create_session,\n",
        "    report_versions,\n",
        "    report_hierarchy,\n",
        "    get_design_files,\n",
        "    delete_session,\n",
        ")\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",
        "    TX_PRE_CURSOR,\n",
        "    TX_POST_CURSOR,\n",
        "    TX_DIFFERENTIAL_SWING,\n",
        "    RX_TERMINATION_VOLTAGE,\n",
        "    RX_COMMON_MODE,\n",
        ")\n",
        "from chipscopy.api.ibert import create_eye_scans, create_links"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "010c9983",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "PROGRAMMING_FILE: /scratch/chipscopy/venv/lib/python3.11/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",
        "# specify hw and if programming is desired\n",
        "HW_PLATFORM = os.getenv(\"HW_PLATFORM\", \"vck190\")\n",
        "PROG_DEVICE = os.getenv(\"PROG_DEVICE\", True)\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(f\"{HW_PLATFORM}/production/chipscopy_ced\")\n",
        "PDI_FILE = design_files.programming_file\n",
        "\n",
        "print(f\"PROGRAMMING_FILE: {PDI_FILE}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9beeb7c4",
      "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,
      "id": "375480ed",
      "metadata": {},
      "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",
              "\n",
              "</pre>\n"
            ],
            "text/plain": [
              "\n",
              "\n"
            ]
          },
          "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 │ 2024.1.1717606426    │     │\n",
              "│                            │ │ Timestamp │ Jun 05 2024-09:53:46 │     │\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 │ 1716424495               │ │\n",
              "│                            │ │   Version │ 2024.1                   │ │\n",
              "│                            │ │ Timestamp │ Wed May 22 18:34:55 2024 │ │\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 │ 1714182049           │ │\n",
              "│                            │ │       Version │ 2024.1.0             │ │\n",
              "│                            │ │     Timestamp │ Apr 26 2024-18:40:49 │ │\n",
              "│                            │ │       Package │ 2024.1.1714182049    │ │\n",
              "│                            │ │ Artifact type │ pyinstaller          │ │\n",
              "│                            │ └───────────────┴──────────────────────┘ │\n",
              "└────────────────────────────┴──────────────────────────────────────────┘\n",
              "</pre>\n"
            ],
            "text/plain": [
              "\u001b[3m                      ChipScoPy Version Information                      \u001b[0m\n",
              "┌────────────────────────────┬──────────────────────────────────────────┐\n",
              "│\u001b[1m \u001b[0m\u001b[1m                    Entity\u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mVersion                                 \u001b[0m\u001b[1m \u001b[0m│\n",
              "├────────────────────────────┼──────────────────────────────────────────┤\n",
              "│                  ChipScoPy │ ┌───────────┬──────────────────────┐     │\n",
              "│                            │ │\u001b[1m \u001b[0m\u001b[1mAttribute\u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mValue               \u001b[0m\u001b[1m \u001b[0m│     │\n",
              "│                            │ ├───────────┼──────────────────────┤     │\n",
              "│                            │ │     Build │ 2024.1.1717606426    │     │\n",
              "│                            │ │ Timestamp │ Jun 05 2024-09:53:46 │     │\n",
              "│                            │ └───────────┴──────────────────────┘     │\n",
              "│                            │                                          │\n",
              "│ hw_server @ localhost:3121 │ ┌───────────┬──────────────────────────┐ │\n",
              "│                            │ │\u001b[1m \u001b[0m\u001b[1mAttribute\u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mValue                   \u001b[0m\u001b[1m \u001b[0m│ │\n",
              "│                            │ ├───────────┼──────────────────────────┤ │\n",
              "│                            │ │    Status │ Connected                │ │\n",
              "│                            │ │     Build │ 1716424495               │ │\n",
              "│                            │ │   Version │ 2024.1                   │ │\n",
              "│                            │ │ Timestamp │ Wed May 22 18:34:55 2024 │ │\n",
              "│                            │ └───────────┴──────────────────────────┘ │\n",
              "│                            │                                          │\n",
              "│ cs_server @ localhost:3042 │ ┌───────────────┬──────────────────────┐ │\n",
              "│                            │ │\u001b[1m \u001b[0m\u001b[1m    Attribute\u001b[0m\u001b[1m \u001b[0m│\u001b[1m \u001b[0m\u001b[1mValue               \u001b[0m\u001b[1m \u001b[0m│ │\n",
              "│                            │ ├───────────────┼──────────────────────┤ │\n",
              "│                            │ │        Status │ Connected            │ │\n",
              "│                            │ │         Build │ 1714182049           │ │\n",
              "│                            │ │       Version │ 2024.1.0             │ │\n",
              "│                            │ │     Timestamp │ Apr 26 2024-18:40:49 │ │\n",
              "│                            │ │       Package │ 2024.1.1714182049    │ │\n",
              "│                            │ │ Artifact type │ pyinstaller          │ │\n",
              "│                            │ └───────────────┴──────────────────────┘ │\n",
              "└────────────────────────────┴──────────────────────────────────────────┘\n"
            ]
          },
          "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": [
              "\n",
              "\n"
            ]
          },
          "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",
      "id": "9c7eb4ee",
      "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,
      "id": "6af04dc1",
      "metadata": {},
      "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: \n",
              "/scratch/chipscopy/venv/lib/python3.11/site-packages/chipscopy/examples/designs/vck190/production/chipscopy_ced/chi\n",
              "pscopy_wrapper.pdi\n",
              "    \n",
              "</pre>\n"
            ],
            "text/plain": [
              "\n",
              "\u001b[1m--> INFO: \u001b[0mProgramming device with: \n",
              "/scratch/chipscopy/venv/lib/python3.11/site-packages/chipscopy/examples/designs/vck190/production/chipscopy_ced/chi\n",
              "pscopy_wrapper.pdi\n",
              "    \n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "3819c2f1eec149f88a6630b8f31561e8",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "Output()"
            ]
          },
          "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\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "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",
        "if PROG_DEVICE:\n",
        "    device.program(PDI_FILE)\n",
        "else:\n",
        "    print(\"skipping programming\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "607bc8cf",
      "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,
      "id": "047404f9",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "--> Debug core discovery done\n",
            "GT Groups available - ['Quad_105', 'Quad_201', 'Quad_204', 'Quad_205']\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",
      "id": "bd44220a",
      "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,
      "id": "4f3f7ddc",
      "metadata": {},
      "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_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",
              "├── 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_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_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",
              "</pre>\n"
            ],
            "text/plain": [
              "IBERT Versal GTY\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",
              "├── 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_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_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"
            ]
          },
          "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",
      "id": "b9ecd22c",
      "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,
      "id": "d720ee49",
      "metadata": {},
      "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",
      "id": "0118e277",
      "metadata": {},
      "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,
      "id": "fcb5965b",
      "metadata": {},
      "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",
      "id": "342db7e7",
      "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,
      "id": "a9fe570f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "application/vnd.jupyter.widget-view+json": {
              "model_id": "441720f5787a4b41bb839f06b45f21e2",
              "version_major": 2,
              "version_minor": 0
            },
            "text/plain": [
              "Output()"
            ]
          },
          "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\">Started eye scan EyeScan_1\n",
              "</pre>\n"
            ],
            "text/plain": [
              "Started eye scan EyeScan_1\n"
            ]
          },
          "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\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "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\">Started eye scan EyeScan_2\n",
              "</pre>\n"
            ],
            "text/plain": [
              "Started eye scan EyeScan_2\n"
            ]
          },
          "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\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "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\">Started eye scan EyeScan_3\n",
              "</pre>\n"
            ],
            "text/plain": [
              "Started eye scan EyeScan_3\n"
            ]
          },
          "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\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "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\">Started eye scan EyeScan_4\n",
              "</pre>\n"
            ],
            "text/plain": [
              "Started eye scan EyeScan_4\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "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 = 10\n",
        "    eye_scan.params[EYE_SCAN_VERT_STEP].value = 10\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": "7d48b5c6",
      "metadata": {},
      "source": [
        "## 9 - Wait for all the eye scans to get done"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "5a7279ed",
      "metadata": {},
      "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\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "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",
      "id": "6b84fbb3",
      "metadata": {},
      "source": [
        "## 10 - 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": 11,
      "id": "0ce6be60",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "image/png": "[encoded data, 105432 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 90900 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 87832 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 84624 characters]",
            "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()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4e40c733",
      "metadata": {},
      "source": [
        "# IBERT Sweep Example\n",
        "\n",
        "This step begins the sweep example, in which for a single link we iterate through valid property values for our desired TX/RX properties, creating an eye scan for each combination of values and allowing us to identify the property values corresponding to the best eye scan. \n",
        "\n",
        "Note that while the eye scan example assumed that no external cable loopback was present, this example was designed to work for devices with external loopback - regardless of the property values we are sweeping over, using internal loopback would likely cause there to not be any appreciable difference in the eye scans generated by the sweep. \n",
        "\n",
        "For an example of an external loopback module utilized in this example, click [here](https://www.samtec.com/kits/optics-fpga/hspce-fmcp/).\n",
        "\n",
        "Finally, for the purposes of this example, we will arbitrarily be using the Quad 205 CH0 TX to Quad 205 CH0 RX link."
      ]
    },
    {
      "cell_type": "markdown",
      "id": "438dcce7",
      "metadata": {},
      "source": [
        "## 11 - Cache Properties for Sweep.\n",
        "\n",
        "As performing a sweep will continuously modify our RX and TX properties, we must begin our sweep by storing the current values in order to restore them after we are done."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "0aa61b62",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "----- Link_0 -----\n",
            "--> Original value of TX Pre Cursor - User Design\n",
            "--> Original value of TX Post Cursor - User Design\n",
            "--> Original value of TX Diff Swing - User Design\n",
            "--> Original value of RX Termination Voltage - 800mv\n"
          ]
        }
      ],
      "source": [
        "link = links[0]\n",
        "\n",
        "#Disabling internal loopback for the reasons outlined above\n",
        "props = {\n",
        "    link.rx.property_for_alias[RX_LOOPBACK]: \"None\"\n",
        "}\n",
        "link.rx.property.set(**props)\n",
        "link.rx.property.commit(list(props.keys()))\n",
        "\n",
        "print(f\"\\n----- {link.name} -----\")\n",
        "\n",
        "orig_precursor = list(link.tx.property.refresh(link.tx.property_for_alias[TX_PRE_CURSOR]).values())[0]\n",
        "orig_postcursor = list(link.tx.property.refresh(link.tx.property_for_alias[TX_POST_CURSOR]).values())[0]\n",
        "orig_diffswing = list(link.tx.property.refresh(link.tx.property_for_alias[TX_DIFFERENTIAL_SWING]).values())[0]\n",
        "orig_termvolt = list(link.tx.property.refresh(link.rx.property_for_alias[RX_TERMINATION_VOLTAGE]).values())[0]\n",
        "\n",
        "print(f\"--> Original value of TX Pre Cursor - {orig_precursor}\")\n",
        "print(f\"--> Original value of TX Post Cursor - {orig_postcursor}\")\n",
        "print(f\"--> Original value of TX Diff Swing - {orig_diffswing}\")\n",
        "print(f\"--> Original value of RX Termination Voltage - {orig_termvolt}\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ea9143ac",
      "metadata": {},
      "source": [
        "## 12 - Find Properties for Sweep.\n",
        "In this step, we find all possible values of the properties we wish to sweep over. For the purposes of this example, only two possible values from each property are used."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "60f8d85e",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "----- Link_0 -----\n",
            "--> Valid values for TX Pre Cursor - ['User Design', '0 dB', '0.60 dB', '1.03 dB', '1.50 dB', '2.00 dB', '2.53 dB', '3.11 dB', '3.73 dB', '4.40 dB']\n",
            "--> Valid values for TX Post Cursor - ['User Design', '0 dB', '0.21 dB', '0.29 dB', '0.77 dB', '1.27 dB', '1.81 dB', '2.38 dB', '3.01 dB', '3.63 dB', '4.35 dB', '5.24 dB', '6.16 dB', '7.19 dB', '8.31 dB', '9.65 dB', '11.20 dB', '13.10 dB', '15.40 dB', '18.80 dB']\n",
            "--> Valid values for TX Diff Swing - ['User Design', '223 mV', '246 mV', '269 mV', '291 mV', '314 mV', '338 mV', '361 mV', '384 mV', '408 mV', '431 mV', '455 mV', '478 mV', '502 mV', '528 mV', '552 mV', '574 mV', '597 mV', '622 mV', '644 mV', '667 mV', '691 mV', '716 mV', '732 mV', '756 mV', '780 mV', '804 mV', '827 mV', '851 mV', '873 mV', '895 mV', '918 mV', '938 mV']\n",
            "--> Valid values for RX Termination Voltage - ['300mv', '350mv', '400mv', '450mv', '500mv', '550mv', '600mv', '650mv', '700mv', '750mv', '800mv', '850mv', '900mv', '950mv', '1000mv', '1100mv']\n"
          ]
        }
      ],
      "source": [
        "_, tx_precursor_report = link.tx.property.report(link.tx.property_for_alias[TX_PRE_CURSOR]).popitem()\n",
        "_, tx_postcursor_report = link.tx.property.report(link.tx.property_for_alias[TX_POST_CURSOR]).popitem()\n",
        "_, tx_diffswing_report = link.tx.property.report(link.tx.property_for_alias[TX_DIFFERENTIAL_SWING]).popitem()\n",
        "_, rx_termvolt_report = link.tx.property.report(link.rx.property_for_alias[RX_TERMINATION_VOLTAGE]).popitem()\n",
        "\n",
        "print(f\"\\n----- {link.name} -----\")\n",
        "print(f\"--> Valid values for TX Pre Cursor - {tx_precursor_report['Valid values']}\")\n",
        "print(f\"--> Valid values for TX Post Cursor - {tx_postcursor_report['Valid values']}\")\n",
        "print(f\"--> Valid values for TX Diff Swing - {tx_diffswing_report['Valid values']}\")\n",
        "print(f\"--> Valid values for RX Termination Voltage - {rx_termvolt_report['Valid values']}\")\n",
        "\n",
        "selected_precurs = tx_precursor_report['Valid values'][0:2]\n",
        "selected_postcurs = tx_postcursor_report['Valid values'][0:2]\n",
        "selected_diffswing = tx_diffswing_report['Valid values'][0:2]\n",
        "selected_termvolt = rx_termvolt_report['Valid values'][0:2]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a8b5f765",
      "metadata": {},
      "source": [
        "## 13 - Perform the Sweep.\n",
        "Iteration over combinations of property values is performed using the itertools product method, imported in the first cell of this example notebook.\n",
        "\n",
        "This step displays the resulting eye scans, completing the sweep."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "3541b973",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "-----Total Eye Scans in this Sweep: 16-----\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_5\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_6\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_7\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_8\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_9\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_10\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_11\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_12\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_13\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_14\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_15\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_16\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_17\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_18\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_19\n"
          ]
        },
        {
          "data": {
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n"
            ],
            "text/plain": []
          },
          "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",
              "</pre>\n"
            ],
            "text/plain": [
              "\n"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Finished eye scan EyeScan_20\n"
          ]
        }
      ],
      "source": [
        "combinations = list(product(selected_precurs, \n",
        "                selected_postcurs, selected_diffswing, \n",
        "                    selected_termvolt))\n",
        "print(f\"-----Total Eye Scans in this Sweep: {len(combinations)}-----\")\n",
        "\n",
        "eye_scans = []\n",
        "for (precurs, poscurs, difswing, tervolt) in combinations:\n",
        "    props = {\n",
        "        link.tx.property_for_alias[TX_PRE_CURSOR]: precurs,\n",
        "        link.tx.property_for_alias[TX_POST_CURSOR]: poscurs,\n",
        "        link.tx.property_for_alias[TX_DIFFERENTIAL_SWING]: difswing\n",
        "    }\n",
        "    link.tx.property.set(**props)\n",
        "    link.tx.property.commit(list(props.keys()))\n",
        "    \n",
        "    props = {\n",
        "        link.rx.property_for_alias[RX_TERMINATION_VOLTAGE]: tervolt,\n",
        "    }\n",
        "    link.rx.property.set(**props)\n",
        "    link.rx.property.commit(list(props.keys()))\n",
        "    \n",
        "    eye_scan = create_eye_scans(target_objs=link)[0]\n",
        "    eye_scan.params[EYE_SCAN_HORZ_STEP].value = 10\n",
        "    eye_scan.params[EYE_SCAN_VERT_STEP].value = 10\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",
        "    eye_scan.start()\n",
        "    eye_scan.wait_till_done()\n",
        "    print(f\"Finished eye scan {eye_scan}\")    \n",
        "    title_string = f\"Pre Cursor: {precurs}, Post Cursor: {poscurs}, Diff Swing: {difswing},\" + \"<br>\" + f\" Termination Voltage: {tervolt}\" #, Common mode: {commode}\n",
        "    eye_scans.append([eye_scan,title_string])\n",
        "    \n",
        "\n",
        "\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c4dec2d7",
      "metadata": {},
      "source": [
        "## 14 - Find the Sweep's Best Eye Scan.\n",
        "Using the eye scans that we have created with the sweep, we can deduce which eye scan and its corresponding properties are the most desirable based on many different, often arbitrary metrics. In this example, we will use the proportion of 0 Bit Error Rate within each eye scan. Other ways of identifying eye-scan quality could include calculating the largest width of the dark blue area, or even simply eye-balling the area of the graph. \n",
        "\n",
        "In this cell, we calculate our metric using the eye scan's raw data, sorting the resulting eye scans in descending order and printing them out."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "4d19bd5c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "image/png": "[encoded data, 54808 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 54636 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 54624 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 54308 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 55408 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 55212 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 55000 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 53704 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 53300 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 54348 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 54984 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 54608 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 55152 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 54456 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 54792 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "image/png": "[encoded data, 55192 characters]",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "for scan in eye_scans:\n",
        "    scan.append(sum([1 for i in scan[0].scan_data.raw.error_count if i == 0])/len(scan[0].scan_data.raw.error_count))\n",
        "\n",
        "eye_scans.sort(key=lambda x: x[2], reverse=True)\n",
        "\n",
        "for scan in eye_scans:\n",
        "    scan[1] += f\", Zero Error Rate: {scan[2]}\"\n",
        "    scan[0].plot.show(title=scan[1])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4a9c9bc0",
      "metadata": {},
      "source": [
        "## 15 - Restore Original Property Values.\n",
        "After completing the sweep, we must finally restore each property to their original values, which we had cached in step 11."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "dd4b21b3",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Post-sweep value of TX Pre Cursor: User Design\n",
            "Post-sweep value of TX Post Cursor: User Design\n",
            "Post-sweep value of TX Diff Swing: User Design\n",
            "Post-sweep value of RX Termination Voltage Cursor: 800mv\n"
          ]
        }
      ],
      "source": [
        "props = {\n",
        "    link.tx.property_for_alias[TX_PRE_CURSOR]: orig_precursor,\n",
        "    link.tx.property_for_alias[TX_POST_CURSOR]: orig_postcursor,\n",
        "    link.tx.property_for_alias[TX_DIFFERENTIAL_SWING]: orig_diffswing,\n",
        "\n",
        "}    \n",
        "link.tx.property.set(**props)  \n",
        "link.tx.property.commit(list(props.keys()))\n",
        "\n",
        "props = {\n",
        "    link.rx.property_for_alias[RX_TERMINATION_VOLTAGE]: orig_termvolt,\n",
        "\n",
        "}    \n",
        "link.rx.property.set(**props)  \n",
        "link.rx.property.commit(list(props.keys()))\n",
        "\n",
        "\n",
        "print(f\"Post-sweep value of TX Pre Cursor: {list(link.tx.property.refresh(link.tx.property_for_alias[TX_PRE_CURSOR]).values())[0]}\")\n",
        "print(f\"Post-sweep value of TX Post Cursor: {list(link.tx.property.refresh(link.tx.property_for_alias[TX_POST_CURSOR]).values())[0]}\")\n",
        "print(f\"Post-sweep value of TX Diff Swing: {list(link.tx.property.refresh(link.tx.property_for_alias[TX_DIFFERENTIAL_SWING]).values())[0]}\")\n",
        "print(f\"Post-sweep value of RX Termination Voltage Cursor: {list(link.rx.property.refresh(link.rx.property_for_alias[RX_TERMINATION_VOLTAGE]).values())[0]}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "f7343614",
      "metadata": {},
      "outputs": [],
      "source": [
        "## When done with testing, close the connection\n",
        "delete_session(session)"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "venv",
      "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.11.2"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
