{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\">\n",
    "<link href=\"https://fonts.googleapis.com/css2?family=Fira+Code&display=swap\" rel=\"stylesheet\">\n",
    "\n",
    "### License\n",
    "\n",
    "<p style=\"font-family: 'Fira Code', monospace; font-size: 1.2rem\">\n",
    "Copyright 2021 Xilinx, Inc.<br><br>\n",
    "Licensed under the Apache License, Version 2.0 (the \"License\");<br>\n",
    "you may not use this file except in compliance with the License.<br><br>\n",
    "You may obtain a copy of the License at <a href=\"http://www.apache.org/licenses/LICENSE-2.0\"?>http://www.apache.org/licenses/LICENSE-2.0</a><br><br>\n",
    "Unless required by applicable law or agreed to in writing, software<br>\n",
    "distributed under the License is distributed on an \"AS IS\" BASIS,<br>\n",
    "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.<br>\n",
    "See the License for the specific language governing permissions and<br>\n",
    "limitations under the License.<br>\n",
    "</p>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ChipScoPy DDR 2D Eye Margin Scan Example\n",
    "\n",
    "\n",
    "<img src=\"../img/api_overview.png\" width=\"500\" align=\"left\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Description\n",
    "This demo shows how to exercise and run Versal DDRMC 2D Margin Scan features\n",
    "\n",
    "\n",
    "## Requirements\n",
    "- Local or remote Xilinx Versal board, such as a VCK190\n",
    "- Xilinx hw_server 2022.1 installed and running\n",
    "- Xilinx cs_server 2022.1 installed and running\n",
    "- Python 3.8 or greater installed\n",
    "- ChipScoPy 2022.1 installed\n",
    "- Jupyter notebook support installed - Please do so, using the command `pip install chipscopy[jupyter]`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1 - Initialization: Imports and File Paths\n",
    "\n",
    "After this step,\n",
    "- Required functions and classes are imported\n",
    "- URL paths are set correctly\n",
    "- File paths to example files are set correctly"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "import os\n",
    "import pprint\n",
    "from chipscopy import create_session, delete_session, report_versions\n",
    "from chipscopy import get_design_files\n",
    "from ddr_scan_util import convert_vref_pct_to_code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "pycharm": {
     "is_executing": true
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "HW_URL: TCP:localhost:3121\n",
      "CS_URL: TCP:localhost:3042\n",
      "PROGRAMMING_FILE: C:\\wrk\\chipscopy\\chipscopy-venv\\Lib\\site-packages\\chipscopy\\examples\\designs\\vck190\\production\\chipscopy_ced\\chipscopy_wrapper.pdi\n",
      "PROBES_FILE:C:\\wrk\\chipscopy\\chipscopy-venv\\Lib\\site-packages\\chipscopy\\examples\\designs\\vck190\\production\\chipscopy_ced\\chipscopy_wrapper.ltx\n"
     ]
    }
   ],
   "source": [
    "# Make sure to start the hw_server and cs_server prior to running.\n",
    "# Specify locations of the running hw_server and cs_server below.\n",
    "# The default is localhost - but can be other locations on the network.\n",
    "CS_URL = os.getenv(\"CS_SERVER_URL\", \"TCP:localhost:3042\")\n",
    "HW_URL = os.getenv(\"HW_SERVER_URL\", \"TCP:localhost:3121\")\n",
    "\n",
    "# The get_design_files() function tries to find the PDI and LTX files. In non-standard\n",
    "# configurations, you can put the path for PROGRAMMING_FILE and PROBES_FILE below.\n",
    "design_files = get_design_files(\"vck190/production/chipscopy_ced\")\n",
    "\n",
    "PROGRAMMING_FILE = design_files.programming_file\n",
    "PROBES_FILE = design_files.probes_file\n",
    "\n",
    "print(f\"HW_URL: {HW_URL}\")\n",
    "print(f\"CS_URL: {CS_URL}\")\n",
    "print(f\"PROGRAMMING_FILE: {PROGRAMMING_FILE}\")\n",
    "print(f\"PROBES_FILE:{PROBES_FILE}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "pycharm": {
     "is_executing": true
    }
   },
   "outputs": [],
   "source": [
    "# Which DDRMC target (0..3) for given ACAP\n",
    "DDR_INDEX = 0\n",
    "# Which Rank of the memory interface\n",
    "RANK = 0\n",
    "# Read or Write Margin : \"READ\" \"WRITE\"\n",
    "MARGIN_MODE = \"READ\"\n",
    "# Data pattern used for margin check : \"SIMPLE\" \"COMPLEX\"\n",
    "DATA_PATTERN = \"COMPLEX\"\n",
    "# VREF Percentage Minimum (reccommended: Read :DDR4 25, LP4 5 , Write : DDR4 60  , LP4 10)\n",
    "VREF_PCT_MIN = 25\n",
    "# VREF Percentage Maximum (reccommended: Read:DDR4 50 , LP4 35 , Write : DDR4 90  , LP4 30)\n",
    "VREF_PCT_MAX = 50\n",
    "# Steps to show in the 2D eye scan  ( 1 step takes ~1 second to capture)\n",
    "STEPS = 15\n",
    "# Which nibble (read mode) or byte lane (write) to display\n",
    "DISPLAY_INDEX = 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2 - Create a session and connect to the hw_server and cs_server\n",
    "\n",
    "The session is a container that keeps track of devices and debug cores.\n",
    "After this step,\n",
    "- Session is initialized and connected to server(s)\n",
    "- Versions are detected and reported to stdout"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x264906ccf70>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-style: italic\">                         ChipScoPy Version Information                          </span>\n",
       "┌────────────────────────────┬─────────────────────────────────────────────────┐\n",
       "│<span style=\"font-weight: bold\">                     Entity </span>│<span style=\"font-weight: bold\"> Version                                         </span>│\n",
       "├────────────────────────────┼─────────────────────────────────────────────────┤\n",
       "│                  ChipScoPy │ ┌───────────┬──────────────────────┐            │\n",
       "│                            │ │<span style=\"font-weight: bold\"> Attribute </span>│<span style=\"font-weight: bold\"> Value                </span>│            │\n",
       "│                            │ ├───────────┼──────────────────────┤            │\n",
       "│                            │ │     Build │ 2022.1.1654231490    │            │\n",
       "│                            │ │ Timestamp │ Jun 02 2022-22:44:50 │            │\n",
       "│                            │ └───────────┴──────────────────────┘            │\n",
       "│                            │                                                 │\n",
       "│ hw_server @ localhost:3121 │ ┌───────────┬─────────────────────────────────┐ │\n",
       "│                            │ │<span style=\"font-weight: bold\"> Attribute </span>│<span style=\"font-weight: bold\"> Value                           </span>│ │\n",
       "│                            │ ├───────────┼─────────────────────────────────┤ │\n",
       "│                            │ │    Status │ Connected                       │ │\n",
       "│                            │ │     Build │ 1641456835                      │ │\n",
       "│                            │ │   Version │ 2022.1                          │ │\n",
       "│                            │ │ Timestamp │ Thu 06 Jan 2022 08:13:55 AM UTC │ │\n",
       "│                            │ └───────────┴─────────────────────────────────┘ │\n",
       "│                            │                                                 │\n",
       "│ cs_server @ localhost:3042 │ ┌───────────────┬──────────────────────┐        │\n",
       "│                            │ │<span style=\"font-weight: bold\">     Attribute </span>│<span style=\"font-weight: bold\"> Value                </span>│        │\n",
       "│                            │ ├───────────────┼──────────────────────┤        │\n",
       "│                            │ │        Status │ Connected            │        │\n",
       "│                            │ │         Build │ 1649790728           │        │\n",
       "│                            │ │       Version │ 2022.1.0             │        │\n",
       "│                            │ │     Timestamp │ Apr 12 2022-13:12:08 │        │\n",
       "│                            │ │       Package │ 2022.1.1649790728    │        │\n",
       "│                            │ │ Artifact type │ pyinstaller          │        │\n",
       "│                            │ └───────────────┴──────────────────────┘        │\n",
       "└────────────────────────────┴─────────────────────────────────────────────────┘\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x264906b0970>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">\n",
       "\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x26490573550>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "session = create_session(cs_server_url=CS_URL, hw_server_url=HW_URL)\n",
    "report_versions(session)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3 - Program the device with the example design\n",
    "\n",
    "After this step,\n",
    "- Device is programmed with the example programming file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "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: C:\\wrk\\chipscopy\\chipscopy-venv\\Lib\\site-packages\\chipscop\n",
       "y\\examples\\designs\\vck190\\production\\chipscopy_ced\\chipscopy_wrapper.pdi\n",
       "    \n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x26490739190>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "7c7e0020c75a4d7696221842cd37d20d",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Output()"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Typical case - one device on the board - get it.\n",
    "device = session.devices.filter_by(family=\"versal\").get()\n",
    "device.program(PROGRAMMING_FILE)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4 - Discover Debug Cores\n",
    "\n",
    "Debug core discovery initializes the chipscope server debug cores. This brings debug cores in the chipscope server online.\n",
    "\n",
    "After this step,\n",
    "\n",
    "- The cs_server is initialized and ready for use"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Debug cores setup and ready for use.\n"
     ]
    }
   ],
   "source": [
    "device.discover_and_setup_cores(ltx_file=PROBES_FILE)\n",
    "print(f\"Debug cores setup and ready for use.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5 - Get a list of the integrated DDR Memory Controllers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4 integrated DDRMC cores exist on this device.\n",
      " DDRMC instance 0 is enabled\n",
      " DDRMC instance 1 is disabled\n",
      " DDRMC instance 2 is disabled\n",
      " DDRMC instance 3 is disabled\n"
     ]
    }
   ],
   "source": [
    "ddr_list = device.ddrs\n",
    "print(f\"{len(ddr_list)} integrated DDRMC cores exist on this device.\")\n",
    "\n",
    "ddr_index = 0\n",
    "for ddr in ddr_list:\n",
    "    if ddr.is_enabled:\n",
    "        print(f\" DDRMC instance {ddr_index} is enabled\")\n",
    "    else:\n",
    "        print(f\" DDRMC instance {ddr_index} is disabled\")\n",
    "    ddr_index += 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6- Select a target DDR by index and display calibration status"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calibration status of DDRMC instance 0 is PASS\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    ddr = ddr_list[DDR_INDEX]\n",
    "    props = ddr.ddr_node.get_property([\"cal_status\"])\n",
    "    print(f\"Calibration status of DDRMC instance {DDR_INDEX} is {props['cal_status']}\")\n",
    "except:\n",
    "    print(f\"The DDR controller at index {DDR_INDEX} is not in use\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Initialization complete.\n"
     ]
    }
   ],
   "source": [
    "## Initialize and activate the Margin Check feature in the DDRMC\n",
    "ddr.ddr_node.set_property({\"mgchk_enable\": 1})\n",
    "ddr.ddr_node.commit_property_group([])\n",
    "ddr.ddr_node.set_property({\"mgchk_enable\": 0})\n",
    "ddr.ddr_node.commit_property_group([])\n",
    "print(\"Initialization complete.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7 - Setting the 2D eye scan read or write mode"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Setting 2D eye for READ margin\n"
     ]
    }
   ],
   "source": [
    "if MARGIN_MODE == \"READ\":\n",
    "    print(\"Setting 2D eye for READ margin\")\n",
    "    ddr.set_eye_scan_read_mode()\n",
    "elif MARGIN_MODE == \"WRITE\":\n",
    "    print(\"Setting 2D eye for WRITE margin\")\n",
    "    ddr.set_eye_scan_write_mode()\n",
    "else:\n",
    "    print(\n",
    "        f\" ERROR: MARGIN_MODE is set to {MARGIN_MODE} which is an illegal value, only READ or WRITE is allowed\"\n",
    "    )\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 8 - Setting the 2D eye scan data pattern mode"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Setting 2D eye for COMPLEX data pattern\n"
     ]
    }
   ],
   "source": [
    "if DATA_PATTERN == \"SIMPLE\":\n",
    "    print(\"Setting 2D eye for SIMPLE data pattern\")\n",
    "    ddr.set_eye_scan_simple_pattern()\n",
    "elif DATA_PATTERN == \"COMPLEX\":\n",
    "    print(\"Setting 2D eye for COMPLEX data pattern\")\n",
    "    ddr.set_eye_scan_complex_pattern()\n",
    "else:\n",
    "    print(\n",
    "        f\" ERROR: DATA_PATTERN is set to {DATA_PATTERN} which is an illegal value, only SIMPLE or COMPLEX is allowed\"\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 9 - Setting the Vref sample min/max range"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Vref Min setting...\n",
      " Requested Read Vref %: 25 actual % : 25.0 \n",
      "Vref Max setting...\n",
      " Requested Read Vref %: 50 actual % : 50.0 \n",
      "Dividing the Vref range into 15 steps\n"
     ]
    }
   ],
   "source": [
    "print(\"Vref Min setting...\")\n",
    "vref_min_code = convert_vref_pct_to_code(ddr, MARGIN_MODE, VREF_PCT_MIN)\n",
    "print(\"Vref Max setting...\")\n",
    "vref_max_code = convert_vref_pct_to_code(ddr, MARGIN_MODE, VREF_PCT_MAX)\n",
    "\n",
    "ddr.set_eye_scan_vref_min(vref_min_code)\n",
    "ddr.set_eye_scan_vref_max(vref_max_code)\n",
    "ddr.set_eye_scan_vref_steps(STEPS)\n",
    "print(f\"Dividing the Vref range into {STEPS} steps\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 10 - Run 2D Margin Scan after settings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "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\">Min VRef is set at:  <span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">25.0</span> %, value  <span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">256</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x26490900af0>"
      ]
     },
     "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\">Max VRef is set at:  <span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">50.0</span> %, value  <span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">512</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x26490900c40>"
      ]
     },
     "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\">Number of VRef steps is set at:  <span style=\"color: #000080; text-decoration-color: #000080; font-weight: bold\">15</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x264909009a0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "d919db26ed1e45e9b33601b953150235",
       "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\">Info: Margin Scans in progress<span style=\"color: #808000; text-decoration-color: #808000\">...</span>\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x26490905b20>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ddr.run_eye_scan()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 11 - Display Scan Plots by a given Unit(nibble/byte) index\n",
    "\n",
    "You can display static or dynamic plots. The display_type controls the display output.\n",
    "- \"static\" is a simple image that can be saved.\n",
    "- \"dynamic\" is an interactive javascript plot.\n",
    "- The default is \"dynamic\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 42816 characters]\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 43348 characters]\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ddr.display_eye_scan(DISPLAY_INDEX, display_type=\"static\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Optionally you can return figures as a list for later operations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "figs = ddr.display_eye_scan(DISPLAY_INDEX + 1, return_as_list=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following loop demonstrates how you can display the graphs from a list created previously.\n",
    "It is easy to display interactive or static images.\n",
    "\n",
    "Here we get the list of figures and output them to png format."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 44180 characters]\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 43596 characters]\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import Image, display\n",
    "\n",
    "for fig in figs:\n",
    "    # To display interactive images, uncomment the following line:\n",
    "    # fig.show()\n",
    "\n",
    "    # To display a static png image:\n",
    "    image_bytes = fig.to_image(format=\"png\")\n",
    "    ipython_image = Image(image_bytes)\n",
    "    display(ipython_image)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 12 - Save the Eye Scan data from latest run"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "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",
       "Info: Data are being formatted and saved to: myoutput.csv\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x26490bead60>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ddr.save_eye_scan_data(\"myoutput.csv\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 13 - Load Eye Scan data from a given data file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "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",
       "Info: Scan data are being loaded successfully from: myoutput.csv\n",
       "</pre>\n"
      ],
      "text/plain": [
       "<rich.jupyter.JupyterRenderable at 0x26490c3e760>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ddr.load_eye_scan_data(\"myoutput.csv\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 14 - Review overall Scan status and Control group detail from latest run"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{ 'es_data_need_update': 0,\n",
      "  'es_vref_max': 512,\n",
      "  'es_vref_min': 256,\n",
      "  'es_vref_steps': 15,\n",
      "  'eye_scan_error': 'None',\n",
      "  'eye_scan_status': 'DONE',\n",
      "  'mgchk_abort': 0,\n",
      "  'mgchk_ack': 0,\n",
      "  'mgchk_bitslect': 0,\n",
      "  'mgchk_ctrl': 64,\n",
      "  'mgchk_def_rd_vref_0': 373,\n",
      "  'mgchk_def_rd_vref_1': 0,\n",
      "  'mgchk_def_wr_vref': 28,\n",
      "  'mgchk_def_wr_vref_range': 0,\n",
      "  'mgchk_done': 0,\n",
      "  'mgchk_enable': 0,\n",
      "  'mgchk_enable_status': 1,\n",
      "  'mgchk_error': 0,\n",
      "  'mgchk_mode': 1,\n",
      "  'mgchk_pattern_config_0': 0,\n",
      "  'mgchk_pattern_config_1': 0,\n",
      "  'mgchk_pattern_config_2': 0,\n",
      "  'mgchk_pattern_mode': 1,\n",
      "  'mgchk_rank': 0,\n",
      "  'mgchk_rd_vref_0': 508,\n",
      "  'mgchk_rd_vref_1': 0,\n",
      "  'mgchk_rw_mode': 0,\n",
      "  'mgchk_start': 1,\n",
      "  'mgchk_step': 0,\n",
      "  'mgchk_unit': 0,\n",
      "  'mgchk_wr_vref': 0}\n"
     ]
    }
   ],
   "source": [
    "props = ddr.ddr_node.get_property_group([\"eye_scan_stat\", \"eye_scan_ctrl\"])\n",
    "print(pprint.pformat(props, indent=2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 15 - (Optional) Report Full DDR config and calibration/margin Info"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "# (uncomment to see report)\n",
    "# ddr.report()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "## When done with testing, close the connection\n",
    "delete_session(session)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
