{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The autoreload extension is already loaded. To reload it, use:\n",
      "  %reload_ext autoreload\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "import numpy as np\n",
    "from collections import defaultdict, Counter\n",
    "import time\n",
    "from matplotlib import pyplot\n",
    "import json5\n",
    "from matplotlib import pyplot as pyplot\n",
    "from scipy.cluster.hierarchy import dendrogram\n",
    "import pandas\n",
    "import logging\n",
    "logging.basicConfig(format='%(message)s', level=logging.DEBUG)\n",
    "\n",
    "import importlib\n",
    "import duhportinf\n",
    "import duhportinf._optimize\n",
    "import duhportinf.busdef\n",
    "import duhportinf.main_portinf as main\n",
    "from   duhportinf.busdef import BusDef\n",
    "from   duhportinf._optimize import MatchCost\n",
    "from   duhportinf import util\n",
    "from   duhportinf._bundle import BundleTree, Interface\n",
    "\n",
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "block_root = '/ip-block-designs'\n",
    "bus_spec_rootdir = '/bus-defs/specs'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [],
   "source": [
    "pcie_json_path = os.path.join(\n",
    "    block_root,\n",
    "    'block-plda-pcie-controller',\n",
    "    'PLDA_ws.json5',\n",
    ")\n",
    "ddr_json_path = os.path.join(\n",
    "    block_root,\n",
    "    'block-cadence-ddr3',\n",
    "    'ddr.json5',\n",
    ")\n",
    "nvdla_json_path = os.path.join(\n",
    "    block_root,\n",
    "    'block-nvdla',\n",
    "    'nvdla.json5',\n",
    ")\n",
    "ark_json_path = os.path.join(\n",
    "    block_root,\n",
    "    'block-ark',\n",
    "    'ark.json5',\n",
    ")\n",
    "pcie_ports  = util.get_unassigned_ports(pcie_json_path)\n",
    "ddr_ports   = util.get_unassigned_ports(ddr_json_path)\n",
    "nvdla_ports = util.get_unassigned_ports(nvdla_json_path)\n",
    "ark_ports   = util.get_unassigned_ports(ark_json_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [],
   "source": [
    "bus_defs = duhportinf.load_bus_defs(bus_spec_rootdir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "56 axi0 ddr ports\n",
      "                                        \r"
     ]
    }
   ],
   "source": [
    "ddr_axi0_ports = [p for p in ddr_ports if p[0].startswith('axi0')]\n",
    "#ddr_axi0_ports.append(('bs', 0, 0))\n",
    "print('{} axi0 ddr ports'.format(len(ddr_axi0_ports)))\n",
    "ddr_i_bus_mappings = main.get_bus_matches(ddr_axi0_ports, list(bus_defs))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "size:56\n"
     ]
    }
   ],
   "source": [
    "for interface, bus_mappings in ddr_i_bus_mappings:\n",
    "    print('size:{}'.format(interface.size))\n",
    "util.dump_json_bus_candidates('testy.json', ddr_json_path, ddr_i_bus_mappings)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def debug(ports, dport, bus_abstract_names):\n",
    "    # filter to get debug bus defs\n",
    "    bus_abstract_names = set(bus_abstract_names)\n",
    "    dbus_defs = list(filter(\n",
    "        lambda bd: bd.abstract_type.name in bus_abstract_names,\n",
    "        bus_defs,\n",
    "    ))\n",
    "    \n",
    "    pg, Z, wire_names = duhportinf._grouper.get_port_grouper(ports)\n",
    "    pg_bus_pairings = duhportinf.main._get_bus_pairings(pg, dbus_defs)\n",
    "    # filter only for port_group with dport\n",
    "    pg_bus_pairings = list(filter(\n",
    "        lambda x: dport in x[2],\n",
    "        pg_bus_pairings,\n",
    "    ))\n",
    "    pg_bus_mappings = duhportinf.main._get_initial_bus_matches(pg, pg_bus_pairings)\n",
    "    return list(map(lambda x: x[2:], pg_bus_mappings))\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "port_path = '/ip-block-designs/tmp/tmp.json5' \n",
    "ports = duhportinf.get_ports_from_json5(port_path)\n",
    "dport = ('front_port_axi4_0_ar_ready', 1, -1)\n",
    "pg_bus_mappings = debug(ports, dport, ['AXI4_rtl'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total time: 13.745474338531494s                                                  \n"
     ]
    }
   ],
   "source": [
    "stime = time.time()\n",
    "\n",
    "nvdla_pg_bus_mappings = duhportinf.get_bus_matches(nvdla_ports, list(bus_defs))\n",
    "etime = time.time()\n",
    "print('total time: {}s'.format(etime-stime))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [],
   "source": [
    "util.dump_json_bus_candidates('testy.json', nvdla_json_path, nvdla_pg_bus_mappings)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                                                                                 \r"
     ]
    }
   ],
   "source": [
    "bt = BundleTree(ddr_ports)\n",
    "ddr_bus_pairings = main._get_bus_pairings(bt, list(bus_defs))\n",
    "ddr_bus_mappings = main._get_initial_bus_matches(bt, ddr_bus_pairings)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "pairings\n",
      "  - interface size:8, prefix:lp_ext_\n",
      "  - interface size:51, prefix:axi1_\n",
      "  - interface size:51, prefix:axi0_\n",
      "  - interface size:5, prefix:phy_reg_\n",
      "  - interface size:8, prefix:phy_reg\n",
      "  - interface size:13, prefix:regH\n",
      "  - interface size:5, prefix:dfi_wrdata_\n",
      "  - interface size:6, prefix:dfi_rddata_\n",
      "  - interface size:5, prefix:dfi_rdlvl_\n",
      "  - interface size:4, prefix:dfi_wrlvl_\n",
      "  - interface size:51, prefix:dfi_\n",
      "mappings\n",
      "  - interface size:13, prefix:regH\n",
      "  - interface size:5, prefix:phy_reg_\n",
      "  - interface size:4, prefix:dfi_wrlvl_\n",
      "  - interface size:5, prefix:dfi_wrdata_\n",
      "  - interface size:5, prefix:dfi_rdlvl_\n",
      "  - interface size:6, prefix:dfi_rddata_\n",
      "  - interface size:8, prefix:lp_ext_\n",
      "  - interface size:51, prefix:axi0_\n",
      "  - interface size:51, prefix:axi1_\n",
      "  - interface size:51, prefix:dfi_\n"
     ]
    }
   ],
   "source": [
    "print('pairings')\n",
    "for nid, _, interface, _ in ddr_bus_pairings:\n",
    "    print('  - interface size:{}, prefix:{}'.format(interface.size, interface.prefix))\n",
    "print('mappings')\n",
    "for nid, _, interface, _ in ddr_bus_mappings:\n",
    "    print('  - interface size:{}, prefix:{}'.format(interface.size, interface.prefix))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total time: 36.72839069366455s                                                   \n"
     ]
    }
   ],
   "source": [
    "stime = time.time()\n",
    "\n",
    "ddr_pg_bus_mappings = duhportinf.get_bus_matches(ddr_ports, list(bus_defs))\n",
    "\n",
    "etime = time.time()\n",
    "print('total time: {}s'.format(etime-stime))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "util.dump_json_bus_candidates('testy.json', ddr_json_path, ddr_pg_bus_mappings)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hierarchically clustering ports and selecting port groups\n",
      "  - done\n",
      "initial bus pairing with port groups\n",
      "  - done\n",
      "bus mapping\n",
      "  - done                                                                         \n",
      "total time: 13.784493684768677s\n"
     ]
    }
   ],
   "source": [
    "s_pcie_ports = list(filter(lambda p: 'axi4' not in p[0], pcie_ports))\n",
    "stime = time.time()\n",
    "pcie_pg_bus_mappings = duhportinf.get_bus_matches(s_pcie_ports, list(bus_defs))\n",
    "\n",
    "etime = time.time()\n",
    "print('total time: {}s'.format(etime-stime))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "port group\n",
      "  -  ('pl_rxdata', None, 1)\n",
      "  -  ('pl_rxstatus', None, 1)\n",
      "  -  ('pl_phystatus', None, 1)\n",
      "  -  ('pl_rxstandby', None, -1)\n",
      "  -  ('pl_rxpolarity', None, -1)\n",
      "  -  ('pl_txcompliance', None, -1)\n",
      "  -  ('pl_txelecidle', None, -1)\n",
      "  -  ('pl_txsyncheader', None, -1)\n",
      "  -  ('pl_txstartblock', None, -1)\n",
      "  -  ('pl_txdatavalid', None, -1)\n",
      "  -  ('pl_txdatak', None, -1)\n",
      "  -  ('pl_txdata', None, -1)\n",
      "  -  ('pl_txdetectrx', None, -1)\n",
      "  -  ('pl_pll_rate', 3, -1)\n",
      "  -  ('pl_pll_ack', 1, 1)\n",
      "  -  ('pl_width', 2, -1)\n",
      "  -  ('pl_ltssm', 5, -1)\n",
      "  -  ('pl_blockaligncontrol', 1, -1)\n",
      "  -  ('pl_txdeemph', 1, -1)\n",
      "  -  ('pl_txswing', 1, -1)\n",
      "  -  ('pl_txmargin', 3, -1)\n",
      "  -  ('pl_rate', 2, -1)\n",
      "  -  ('pl_powerdown', 2, -1)\n",
      "  -  ('pl_spor', 1, 1)\n",
      "  -  ('pl_npor', 1, 1)\n",
      "  -  ('pl_srst', 1, 1)\n",
      "  -  ('pl_rstnp', 1, 1)\n",
      "  -  ('pl_rstn', 1, 1)\n",
      "  -  ('pl_rstn_srst_out', 1, -1)\n",
      "  -  ('pl_pclk_change_ok', None, 1)\n",
      "  -  ('pl_pclk_change_ack', None, -1)\n",
      "  -  ('pl_pclk', 1, 1)\n",
      "  -  ('pl_pclk_rate', 3, -1)\n",
      "bus mappings\n",
      "  - cost:121.01(n:0.50;w:36;d:21) bus_def:{'vendor': 'amba.com', 'library': 'AMBA4', 'name': 'AXI4_rtl', 'version': 'r0p0_0'}\n",
      "  - cost:132.87(n:0.43;w:36;d:24) bus_def:{'vendor': 'amba.com', 'library': 'AMBA4', 'name': 'ACE-Lite_rtl', 'version': 'r0p0_0'}\n",
      "  - cost:132.87(n:0.43;w:36;d:24) bus_def:{'vendor': 'amba.com', 'library': 'AMBA4', 'name': 'ACP_rtl', 'version': 'r0p0_0'}\n",
      "  - cost:135.05(n:0.03;w:35;d:25) bus_def:{'vendor': 'intel.com', 'library': 'PHY', 'name': 'PIPE_rtl', 'version': '4.4.0'}\n",
      "  - cost:144.06(n:0.53;w:39;d:26) bus_def:{'vendor': 'amba.com', 'library': 'AMBA4', 'name': 'ACE_rtl', 'version': 'r0p0_0'}\n"
     ]
    }
   ],
   "source": [
    "dport = ('pl_pll_ack', 1, 1)\n",
    "for interface, bus_mappings in pcie_pg_bus_mappings:\n",
    "    if dport in interface.ports:\n",
    "        print('port group')\n",
    "        for port in interface.ports:\n",
    "            print('  - ', port)\n",
    "        print('bus mappings')\n",
    "        for bm in bus_mappings:\n",
    "            print('  - cost:{} bus_def:{}'.format(\n",
    "                bm.cost,\n",
    "                str(bm.bus_def.abstract_type),\n",
    "            ))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "def dump_nonaxi_dendogram(path, ports):\n",
    "    assert path.endswith('.pdf')\n",
    "    nonaxi_ports = list(filter(\n",
    "        lambda p: not p[0].startswith('axi'),\n",
    "        ports,\n",
    "    ))\n",
    "    _, Z, wire_names = abxportinf.get_port_grouper(nonaxi_ports)\n",
    "    fig, ax = pyplot.subplots(1,1, figsize=(10,40))\n",
    "    _ = dendrogram(\n",
    "        Z,\n",
    "        ax=ax,\n",
    "        orientation='left',\n",
    "        labels=wire_names,\n",
    "    )\n",
    "    pyplot.savefig(path)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "dump_nonaxi_dendogram('ddr-nonaxi-dendogram.pdf', ddr_ports)\n",
    "dump_nonaxi_dendogram('pcie-nonaxi-dendogram.pdf', pcie_ports)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "util.dump_json_bus_candidates('ddr-busprop.json', ddr_pg_bus_mappings)\n",
    "util.dump_json_bus_candidates('pcie-busprop.json', pcie_pg_bus_mappings)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
