{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "random-thread",
   "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",
   "id": "strange-hobby",
   "metadata": {},
   "source": [
    "# ChipScoPy ILA Monitor Status Example\n",
    "\n",
    "\n",
    "<img src=\"../img/api_overview.png\" width=\"500\" align=\"left\">"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "motivated-ranch",
   "metadata": {},
   "source": [
    "## Description\n",
    "An advanced example showing how to monitor the ILA capture status, by running the function ILA.monitor_status(), in asynchroneous mode.\n",
    "\n",
    "By calling ChipScoPy ILA API function **monitor_status()**, in asynchronous mode we can do the following:\n",
    "- Get periodic updates of ILA core capture status.\n",
    "- Call other ChipScoPy API functions, while monitoring the ILA status.\n",
    "- Cancel the status monitor early.\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",
   "id": "suffering-bench",
   "metadata": {},
   "source": [
    "# Overview\n",
    "### Function monitor_status() Documentation\n",
    "    A. Function monitor_status()\n",
    "    B. Calling monitor_status() in Synchronous Mode\n",
    "    C. Calling monitor_status() in Asynchronous Mode\n",
    "    D. Future Object\n",
    "    E. Progress Function\n",
    "    F. ILAStatus Class\n",
    "    G. ILAState Enum Values\n",
    "### Example Steps\n",
    "    1.  Initialization: Imports and File Paths\n",
    "    2.  Create a session and connect to the hw_server and cs_server\n",
    "    3.  Program the Device\n",
    "    4.  Discover Debug Cores\n",
    "    5.  VIO Control and ILA Capture\n",
    "    6.  Configure the counter using VIO output probes\n",
    "    7.  Define Status Progress Function\n",
    "    8.  Arm ILA to Trigger on VIO Up/Down virtual switch\n",
    "    9.  Start Status Monitor\n",
    "    10. Toggle Counter Direction - Monitor Status\n",
    "    11. Status Monitor Completes\n",
    "    12. Upload and Print Data\n",
    "--------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "seasonal-aberdeen",
   "metadata": {},
   "source": [
    "## A. Function monitor_status()\n",
    "\n",
    "    def monitor_status(\n",
    "       self, max_wait_minutes: float = None, progress=None, done: request.DoneFutureCallback = None\n",
    "    ) -> ILAStatus or request.CsFutureRequestSync:\n",
    "\n",
    "This function monitors ILA capture status and waits until all data has been captured, or until timeout\n",
    "or the function is cancelled.\n",
    "Call this function after arming the ILA and before uploading the waveform.\n",
    "The command operates in synchronous mode if *done* argument has default value *None* .\n",
    "\n",
    "\n",
    "Args:\n",
    "-  **max_wait_minutes** (float): Max time in minutes for status monitor. If *None*, status monitor never times out.\n",
    "-  **progress**(progress_fn) : See Asynchronous Mode, below. This function runs in the TCF Event Thread.\n",
    "-  **done**(request.DoneFutureCallback): Done callback. This function runs in the TCF Event Thread.\n",
    "\n",
    "Returns:\n",
    "- ILAStatus when called synchronously.\n",
    "- \"future object\" when called asynchronously."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "legislative-console",
   "metadata": {},
   "source": [
    "## B. Calling monitor_status() in Synchronous Mode\n",
    "- Typical mode when using this function. It is not covered in this example.\n",
    "- Function waits until all data has been captured in the ILA core, or timeout.\n",
    "- Use default argument value *None* for both arguments *progress* and *done* .\n",
    "- Returns an ILAStatus object."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "associate-mobile",
   "metadata": {},
   "source": [
    "## C. Calling monitor_status() in Asynchronous Mode\n",
    "\n",
    "- This mode is useful for reporting the capture status to stdout or a GUI.\n",
    "- Function does not block. The main thread continues with the next statement.\n",
    "- Returns a *future* object, which represents the monitor.\n",
    "- A blocking function should be called later on the *future* object, in order to let the calling thread wait until the status monitor has completed.\n",
    "- Asynchronous Mode is selected, by specifying a *done* function, which is called after the function has completed.\n",
    "- If no user defined callback is needed, set *done* argument to dummy function *chipscopy.null_callback*, to enable asynchronous mode."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "thick-zoning",
   "metadata": {},
   "source": [
    "## D. Future Object\n",
    "\n",
    "When the *monitor_status* function is called in asynchronous mode, it will return a *future* object.\n",
    "The *future* object has blocking attributes and functions, which will block the current thread until\n",
    "the status monitor has completed.\n",
    "\n",
    "###  Blocking Attributes\n",
    "\n",
    "- *future.result* - Returns *None* or *ILAStatus*. *ILAStatus* object if capture did complete successfully, without timeout.\n",
    "- *future.error* - Returns *None* or *Exception*. *None* if no error otherwise an exception object, e.g. timeout exception.\n",
    "\n",
    "### Non-blocking Attribute\n",
    "\n",
    "- *future.progress* - Returns *None* or *ILAStatus*. Read this attribute in the *progress function*, to get the ILA capture status.\n",
    "\n",
    "### Blocking Function\n",
    "\n",
    "- *future.wait(timeout=None)* - *None* value means wait until status monitor completes. Argument *timeout* is in seconds.\n",
    "\n",
    "### Non-blocking Function\n",
    "\n",
    "- *future.cancel()*  - Cancels the status monitor. An exception will be raised in the thread, which called the function *ILA.monitor_status*."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "organizational-memory",
   "metadata": {},
   "source": [
    "## E. Progress Function\n",
    "\n",
    "- User-defined function which takes one argument *future*.\n",
    "- Useful for reporting ILA capture status.\n",
    "- The *progress function* is only called when the ILA capture status changes.\n",
    "- The *progress function* is called in the TCF Event Thread. The *progress function* must not call any ChipScoPy API function, which interacts with the cs_server or the device.\n",
    "\n",
    ">    Example:\n",
    ">\n",
    ">        def monitor_status_done(future):\n",
    ">            if not future.error:\n",
    ">                # future.result holds an ILAStatus object.\n",
    ">                print_status(future.progress)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "determined-lafayette",
   "metadata": {},
   "source": [
    "## F. ILAStatus Class\n",
    "\n",
    "The following data attributes are available to read, when monitoring the ILA capture status.\n",
    "\n",
    "| Attributes                  | TYPE     | Description                                                 |\n",
    "|:--------------------------- |:-------- |:----------------------------------------------------------- |\n",
    "| capture_state:              | ILAState | Capture state. See below.                                   |\n",
    "| is_armed                    | bool     | Trigger is armed.                                           |\n",
    "| is_full                     | bool     | Data buffer is full.                                        |\n",
    "| samples_captured            | int      | Number of samples captured in current data window.          |\n",
    "| windows_captured            | int      | Number of fully captured data windows.                      |\n",
    "| samples_requested           | int      | Requested number of samples per window, when was ILA armed. |\n",
    "| windows_requested           | int      | Requested number of windows, when ILA was armed.            |\n",
    "| trigger_position_requested  | int      | Requested trigger position, when ILA was armed.             |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "rural-cloud",
   "metadata": {},
   "source": [
    "## G.  ILAState Enum Values\n",
    "\n",
    "ILA Capture State Transitions:<br>\n",
    ">        IDLE -> PRE_TRIGGER -> TRIGGER -> POST_TRIGGER -> IDLE\n",
    "\n",
    "| Enum Value   | Description\n",
    "|:-------------|:-------------------------------- |\n",
    "| IDLE         | Not armed.                       |\n",
    "| PRE_TRIGGER  | Capturing pre-trigger samples.   |\n",
    "| TRIGGER      | Waiting for trigger.             |\n",
    "| POST_TRIGGER | Capturing post-trigger samples.  |\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "empty-austria",
   "metadata": {},
   "source": [
    "# Example Steps"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "tender-thread",
   "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,
   "id": "parallel-intensity",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from time import sleep\n",
    "import chipscopy\n",
    "from chipscopy import get_design_files\n",
    "from chipscopy import get_examples_dir_or_die, null_callback\n",
    "from chipscopy import create_session, report_versions\n",
    "from chipscopy.api.ila import export_waveform, get_waveform_data, ILAStatus, ILAState"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "stretch-lighter",
   "metadata": {
    "lines_to_next_cell": 2
   },
   "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": [
    "# Specify locations of the running hw_server and cs_server below.\n",
    "# To make things convenient, we default to values from the following environment variables.\n",
    "# Modify these if needed.\n",
    "\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": "markdown",
   "id": "faced-pickup",
   "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": "exempt-pollution",
   "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": [
       "<rich.jupyter.JupyterRenderable at 0x24928569b80>"
      ]
     },
     "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 0x24928410fa0>"
      ]
     },
     "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 0x24928410fa0>"
      ]
     },
     "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": "military-thesis",
   "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": "horizontal-learning",
   "metadata": {
    "lines_to_next_cell": 2
   },
   "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 0x249285f6490>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "7fe80a7a8e0b4a21833cf10161dded01",
       "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",
   "id": "obvious-concern",
   "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\n",
    "- ILA and VIO core instances in the device are reported"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "standard-judgment",
   "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": "code",
   "execution_count": 6,
   "id": "relevant-census",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 - D62FB110F1A25D439EB15D9149F450CE   chipscopy_i/counters/ila_fast_counter_0\n",
      "1 - 9125D1429AD25223AECDD656C2856755   chipscopy_i/counters/ila_slow_counter_0\n",
      "2 - C53C0D3572B655B6A8A13A86686D262D   chipscopy_i/noc_tg_bc/noc_bc_axis_ila_0\n"
     ]
    }
   ],
   "source": [
    "# Print out the ILA core instance UUIDs and instance names\n",
    "ila_cores = device.ila_cores\n",
    "for index, ila_core in enumerate(ila_cores):\n",
    "    print(f\"{index} - {ila_core.core_info.uuid}   {ila_core.name}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "documentary-understanding",
   "metadata": {
    "lines_to_next_cell": 2
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 - 0E76DEFA789D564080CFA5332A88DB12   chipscopy_i/noc_tg_bc/noc_tg/inst/u_top_axi_mst/u_tg_top/gen_aximm_reg_space.u_reg_space/gen_vio_status_monitor.u_vio_status_monitor\n",
      "1 - 718A03DBCD265D969EA5C15840AEFD17   chipscopy_i/counters/vio_fast_counter_0\n",
      "2 - 22BC7ED6C4145AAB88C58EAEDFF2B04C   chipscopy_i/counters/vio_slow_counter_0\n",
      "3 - 021098F58FE659EFAD76657E635E53FE   chipscopy_i/noc_tg_bc/axis_vio_0\n"
     ]
    }
   ],
   "source": [
    "# Print out the VIO core instance UUIDs and instance names\n",
    "vio_cores = device.vio_cores\n",
    "for index, vio_core in enumerate(vio_cores):\n",
    "    print(f\"{index} - {vio_core.core_info.uuid}   {vio_core.name}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "latter-answer",
   "metadata": {},
   "source": [
    "## 5 - VIO Control and ILA Capture\n",
    "\n",
    "ILA and VIO are two important building blocks for debugging applications in hardware.\n",
    "This example design shows how to control IP using a VIO core and capture results with ILA.\n",
    "\n",
    "In this design,\n",
    "- A VIO core controls the counter (reset, up/down, ce, load)\n",
    "- An ILA core captures the counter values\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "powered-psychology",
   "metadata": {},
   "source": [
    "<img src=\"img/capture_data.png\" width=\"400\" align=\"left\">"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "remarkable-tiger",
   "metadata": {
    "lines_to_next_cell": 2
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using ILA: 9125D1429AD25223AECDD656C2856755  chipscopy_i/counters/ila_slow_counter_0\n",
      "Using VIO: 22BC7ED6C4145AAB88C58EAEDFF2B04C  chipscopy_i/counters/vio_slow_counter_0\n"
     ]
    }
   ],
   "source": [
    "# Grab the two cores we are interested in for the demonstration\n",
    "# As shown above, a counter is connected to the ILA core.\n",
    "# The VIO core controls the counter.\n",
    "\n",
    "ila = device.ila_cores.get(name=\"chipscopy_i/counters/ila_slow_counter_0\")\n",
    "vio = device.vio_cores.get(name=\"chipscopy_i/counters/vio_slow_counter_0\")\n",
    "\n",
    "print(f\"Using ILA: {ila.core_info.uuid}  {ila.name}\")\n",
    "print(f\"Using VIO: {vio.core_info.uuid}  {vio.name}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "designing-rotation",
   "metadata": {},
   "source": [
    "## 6 - Configure the counter using VIO output probes\n",
    "\n",
    "Set up the VIO core to enable counting up, from 0\n",
    "\n",
    "<img src=\"img/vio_control_counter.png\" width=\"300\" align=\"left\">"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "incident-booth",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Counter is now free-running and counting up\n"
     ]
    }
   ],
   "source": [
    "vio.reset_vio()\n",
    "vio.write_probes(\n",
    "    {\n",
    "        \"chipscopy_i/counters/slow_counter_0_SCLR\": 0,\n",
    "        \"chipscopy_i/counters/slow_counter_0_L\": 0x00000000,\n",
    "        \"chipscopy_i/counters/slow_counter_0_LOAD\": 0,\n",
    "        \"chipscopy_i/counters/slow_counter_0_UP\": 1,\n",
    "        \"chipscopy_i/counters/slow_counter_0_CE\": 1,\n",
    "    }\n",
    ")\n",
    "print(\"Counter is now free-running and counting up\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "textile-nurse",
   "metadata": {},
   "source": [
    "## 7 - Define Status Progress Function\n",
    "- The **status_progress** function will be given to the **ila.monitor_status()** function, as an argument.\n",
    "- The function is called when status changes, but not more often than twice per second.\n",
    "- The argument **future** has a member *progress* of type **ILAStatus**, which contains the status information.\n",
    "- The **status_progress** function,\n",
    "    - prints status to stdout\n",
    "    - cancels the **monitor_status()** function, if 3 waveform windows have been captured.\n",
    "- Note: The monitor function will run in the Event Tread, which handles commands sent to the cs_server.\n",
    "- Important: Do not call an API function which communicates with the cs_server or device, from inside the monitor function. It may put the program in a deadlock."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "tropical-lighting",
   "metadata": {},
   "outputs": [],
   "source": [
    "def status_progress(future):\n",
    "    \"\"\"Called in Event Thread\"\"\"\n",
    "    st: ILAStatus = future.progress\n",
    "    if st:\n",
    "        print_status(st)\n",
    "        if st.windows_captured >= 3:\n",
    "            print(\"\\nCancelling ILA Status Monitor\")\n",
    "            future.cancel()\n",
    "\n",
    "\n",
    "def print_status(st: ILAStatus):\n",
    "    current_window = min(st.windows_captured + 1, st.windows_requested)\n",
    "    print(\n",
    "        f\"\\nCapture State: {st.capture_state.name} - \"\n",
    "        f\" Windows Captured: {st.windows_captured} of {st.windows_requested}.\",\n",
    "        end=\"\",\n",
    "    )\n",
    "    if st.is_full:\n",
    "        print(f\" - Capture is complete.\")\n",
    "    else:\n",
    "        print(f\" - Samples in current window: \" f\"{st.samples_captured} of {st.samples_requested}.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fleet-volleyball",
   "metadata": {},
   "source": [
    "## 8 - Arm ILA to Trigger on VIO Up/Down virtual switch\n",
    "\n",
    "- Set ILA to trigger when UP/DOWN counter signal edge rises or falls.\n",
    "- Set ILA core to capture on a transition of the UP/DOWN toggle switch\n",
    "- Once transition happens, trigger in the middle of the buffer.\n",
    "- Request 10 windows."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "occasional-kazakhstan",
   "metadata": {},
   "source": [
    "<img src=\"img/edge_trigger.png\" width=\"550\" align=\"left\">"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "objective-clock",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ILA is armed\n"
     ]
    }
   ],
   "source": [
    "ila.reset_probes()\n",
    "ila.set_probe_trigger_value(\"chipscopy_i/counters/slow_counter_0_UP_1\", [\"==\", \"B\"])\n",
    "ila.run_basic_trigger(window_count=10, window_size=8, trigger_position=4)\n",
    "\n",
    "print(\"ILA is armed\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "generic-particular",
   "metadata": {},
   "source": [
    "## 9 - Start Status Monitor\n",
    "- Define a *done* function *monitor_status_done*, which will be called when status monitoring ends.\n",
    "- Start the Status Monitor.\n",
    "- Passing in the *status_progress* function, defined above.\n",
    "- Get the *future* object from the *monitor_status* function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "parallel-labor",
   "metadata": {},
   "outputs": [],
   "source": [
    "def monitor_status_done(future):\n",
    "    print(\"\\nCallback function monitor_status_done() called.\")\n",
    "    if not future.error:\n",
    "        # future.result holds an ILAStatus object.\n",
    "        print_status(future.result)\n",
    "\n",
    "\n",
    "# Called asynchronously, with done callback function.\n",
    "# This thread will continue executing while monitoring of the ILA Status will happen in the event thread.\n",
    "future = ila.monitor_status(\n",
    "    max_wait_minutes=0.5, progress=status_progress, done=monitor_status_done\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "billion-financing",
   "metadata": {},
   "source": [
    "## 10 - Toggle Counter Direction - Monitor Status\n",
    "- Use VIO to toggle counter up/down switch 3 times: DOWN/UP/DOWN.\n",
    "- This will cause the running ILA to trigger 3 times, capturing 3 windows of data.\n",
    "- The *status_progress* function will call *future.cancel()*, after 3 windows.\n",
    "- Observe messages:\n",
    "    - *status_progress* prints capture status.\n",
    "    - *status_progress* prints out message when calling *future.cancel()*.\n",
    "    - *done* function *monitor_status_done* prints message when called."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "sharing-affect",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Changing counter up/down direction.\n",
      "\n",
      "Capture State: TRIGGER -  Windows Captured: 0 of 10. - Samples in current window: 4 of 8.\n",
      "\n",
      "Capture State: TRIGGER -  Windows Captured: 1 of 10. - Samples in current window: 4 of 8.\n",
      "\n",
      "Changing counter up/down direction.\n",
      "\n",
      "Capture State: TRIGGER -  Windows Captured: 2 of 10. - Samples in current window: 4 of 8.\n",
      "\n",
      "Changing counter up/down direction.\n",
      "\n",
      "Capture State: TRIGGER -  Windows Captured: 3 of 10. - Samples in current window: 4 of 8.\n",
      "\n",
      "Cancelling ILA Status Monitor\n",
      "\n",
      "Callback function monitor_status_done() called.\n"
     ]
    }
   ],
   "source": [
    "for switch_value in [0, 1, 0]:\n",
    "    print(\"\\nChanging counter up/down direction.\")\n",
    "    vio.write_probes({\"chipscopy_i/counters/slow_counter_0_UP\": switch_value})\n",
    "    # Sleep 2.0 seconds.\n",
    "    sleep(2.0)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "acute-physiology",
   "metadata": {},
   "source": [
    "## 11 - Status Monitor Completes\n",
    "- *future.result* will block until capture completes or is cancelled.\n",
    "- Status monitoring is cancelled.\n",
    "- *future.result* thows the cancel exception."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "collected-institute",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "****** Status Monitor raised exception: 'Request Cancelled' ******\n",
      "\n",
      "Windows avaliable to upload: 3.\n"
     ]
    }
   ],
   "source": [
    "status = None\n",
    "try:\n",
    "    # future.result is blocking, until monitor_status() function has completed or timed-out or been cancelled.\n",
    "    status = future.result\n",
    "except Exception as ex:\n",
    "    # Catch cancel exception here.\n",
    "    print(f\"\\n****** Status Monitor raised exception: '{ex}' ******\\n\")\n",
    "\n",
    "if status:\n",
    "    print(\"Function monitor_status() has completed.\")\n",
    "else:\n",
    "    ila.refresh_status()\n",
    "\n",
    "print(f\"Windows avaliable to upload: {ila.status.windows_captured}.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "forbidden-signal",
   "metadata": {},
   "source": [
    "## 12 - Upload and Print Data\n",
    "- Print the captured ILA samples and mark the trigger position.\n",
    "- Note that counter changes direction after the trigger mark."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "hearing-bosnia",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Window:0  Window Sample:0   359173591  0x15688DD7 \n",
      "Window:0  Window Sample:1   359173592  0x15688DD8 \n",
      "Window:0  Window Sample:2   359173593  0x15688DD9 \n",
      "Window:0  Window Sample:3   359173594  0x15688DDA \n",
      "Window:0  Window Sample:4   359173595  0x15688DDB <-- Trigger\n",
      "Window:0  Window Sample:5   359173594  0x15688DDA \n",
      "Window:0  Window Sample:6   359173593  0x15688DD9 \n",
      "Window:0  Window Sample:7   359173592  0x15688DD8 \n",
      "Window:1  Window Sample:0   141709775  0x087251CF \n",
      "Window:1  Window Sample:1   141709774  0x087251CE \n",
      "Window:1  Window Sample:2   141709773  0x087251CD \n",
      "Window:1  Window Sample:3   141709772  0x087251CC \n",
      "Window:1  Window Sample:4   141709771  0x087251CB <-- Trigger\n",
      "Window:1  Window Sample:5   141709772  0x087251CC \n",
      "Window:1  Window Sample:6   141709773  0x087251CD \n",
      "Window:1  Window Sample:7   141709774  0x087251CE \n",
      "Window:2  Window Sample:0   359620917  0x156F6135 \n",
      "Window:2  Window Sample:1   359620918  0x156F6136 \n",
      "Window:2  Window Sample:2   359620919  0x156F6137 \n",
      "Window:2  Window Sample:3   359620920  0x156F6138 \n",
      "Window:2  Window Sample:4   359620921  0x156F6139 <-- Trigger\n",
      "Window:2  Window Sample:5   359620920  0x156F6138 \n",
      "Window:2  Window Sample:6   359620919  0x156F6137 \n",
      "Window:2  Window Sample:7   359620918  0x156F6136 \n"
     ]
    }
   ],
   "source": [
    "ila.upload()\n",
    "samples = get_waveform_data(\n",
    "    ila.waveform,\n",
    "    [\"chipscopy_i/counters/slow_counter_0_Q_1\"],\n",
    "    include_trigger=True,\n",
    "    include_sample_info=True,\n",
    ")\n",
    "for trigger, sample_index, window_index, window_sample_index, value in zip(*samples.values()):\n",
    "    trigger = \"<-- Trigger\" if trigger else \"\"\n",
    "    print(\n",
    "        f\"Window:{window_index}  Window Sample:{window_sample_index}  {value:10}  0x{value:08X} {trigger}\"\n",
    "    )"
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  },
  "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": 5
}
