Bruno JJE
Published © GPL3+

NN Training at the Edge with PyTorch, PYNQ and an Ultra96-V2

Inference at the edge is the new hype. But what about training at the edge ? This project aims at exploring that with FPGA acceleration.

IntermediateWork in progress1 hour2,490
NN Training at the Edge with PyTorch, PYNQ and an Ultra96-V2

Things used in this project

Hardware components

Ultra96-V2
Avnet Ultra96-V2
×1

Software apps and online services

Vivado Design Suite HLx Editions
AMD Vivado Design Suite HLx Editions
PYNQ Framework
AMD PYNQ Framework
Jupyter Notebook
Jupyter Notebook
PyTorch

Story

Read more

Custom parts and enclosures

multaccum PYNQ overlay (bit file)

Floating point computation acceleration of "input @ weights + bias"

multaccum PYNQ overlay (hwh file)

Floating point computation acceleration of "input @ weights + bias"

Code

nn_training_accel.ipynb

Python
Jupyter Notebook : PyTorch MNIST training with PYNQ on Ultra96-V2 with FPGA acceleration
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torchvision\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# MNIST dataset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The dataset is created as a way to access the data we will use for training.\n",
    "\n",
    "We define a transformation that will be applied on each of the image of the dataset when we query them. \n",
    "This will ease the learning.\n",
    "\n",
    "This transformation will :\n",
    "* convert the pixel to float values (instead of value between 0 and 255)\n",
    "* normalize the value of the pixels (mean of 0, standard deviation of 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "transform = torchvision.transforms.Compose([\n",
    "        torchvision.transforms.ToTensor(),\n",
    "        torchvision.transforms.Normalize((0.1307,), (0.3081,))\n",
    "        ])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We create a train and a test dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_dataset = torchvision.datasets.MNIST(\n",
    "    root=\"./torch_datasets\",\n",
    "    train=True,\n",
    "    transform=transform,\n",
    "    download=True\n",
    ")\n",
    "\n",
    "test_dataset = torchvision.datasets.MNIST(\n",
    "    root=\"./torch_datasets\",\n",
    "    train=False,\n",
    "    transform=transform,\n",
    "    download=True\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's play a bit with the content of these datasets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Dataset MNIST\n",
       "    Number of datapoints: 60000\n",
       "    Root location: ./torch_datasets\n",
       "    Split: Train\n",
       "    StandardTransform\n",
       "Transform: Compose(\n",
       "               ToTensor()\n",
       "               Normalize(mean=(0.1307,), std=(0.3081,))\n",
       "           )"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([1, 28, 28]) 5\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f5bd8fc88>"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAP8AAAD8CAYAAAC4nHJkAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvAOZPmwAADmtJREFUeJzt3W+sVPWdx/HPFwT/UFQIV3ulKF00ZgmJYEbYhI2iRLSbKvCgBmIQTQM+ANkmEBfhATxwE6PbdlVMk4slQFJpGyorJGYtGo1L3BgGJQiLbNVc6V0QLqFYqw9Q+O6De2hu8c5vhpkzc+byfb8ScmfO9/zmfDPczz0z85uZn7m7AMQzpOgGABSD8ANBEX4gKMIPBEX4gaAIPxAU4QeCIvxAUIQfCOqSVh5szJgxPn78+FYeEgilu7tbJ06csFr2bSj8ZnavpGclDZX0ors/ldp//PjxKpfLjRwSQEKpVKp537of9pvZUEkvSPqBpImS5pvZxHpvD0BrNfKcf6qkj9z9E3c/LenXkmbn0xaAZmsk/GMl/bHf9Z5s298ws8VmVjazcm9vbwOHA5CnRsI/0IsK3/p8sLt3uXvJ3UsdHR0NHA5AnhoJf4+kcf2uf0/SkcbaAdAqjYR/t6SbzOz7ZjZc0jxJ2/NpC0Cz1T3V5+7fmNlSSa+pb6pvg7sfyK0zAE3V0Dy/u78q6dWcegHQQry9FwiK8ANBEX4gKMIPBEX4gaAIPxAU4QeCIvxAUIQfCIrwA0ERfiAowg8ERfiBoAg/EBThB4Ii/EBQhB8IivADQRF+ICjCDwRF+IGgCD8QFOEHgiL8QFCEHwiK8ANBEX4gKMIPBEX4gaAaWqXXzLolfSHpjKRv3L2UR1PIz5kzZ5L1zz//vKnHX7duXcXaV199lRx76NChZP2FF15I1lesWFGxtmXLluTYyy67LFlfuXJlsr5mzZpkvR00FP7Mne5+IofbAdBCPOwHgmo0/C7p92a2x8wW59EQgNZo9GH/dHc/YmbXSNppZh+6+9v9d8j+KCyWpOuvv77BwwHIS0Nnfnc/kv08LmmbpKkD7NPl7iV3L3V0dDRyOAA5qjv8ZjbCzEaeuyxplqT9eTUGoLkaedh/raRtZnbudl5y9//MpSsATVd3+N39E0m35NjLRevw4cPJ+unTp5P1d955J1nftWtXxdqpU6eSY7du3ZqsF2ncuHHJ+mOPPZasb9u2rWJt5MiRybG33JL+1b7jjjuS9cGAqT4gKMIPBEX4gaAIPxAU4QeCIvxAUHl8qi+8999/P1m/6667kvVmf6y2XQ0dOjRZf/LJJ5P1ESNGJOsPPvhgxdp1112XHDtq1Khk/eabb07WBwPO/EBQhB8IivADQRF+ICjCDwRF+IGgCD8QFPP8ObjhhhuS9TFjxiTr7TzPP23atGS92nz4m2++WbE2fPjw5NgFCxYk62gMZ34gKMIPBEX4gaAIPxAU4QeCIvxAUIQfCIp5/hyMHj06WX/mmWeS9R07diTrU6ZMSdaXLVuWrKdMnjw5WX/99deT9Wqfqd+/v/I6Ls8991xyLJqLMz8QFOEHgiL8QFCEHwiK8ANBEX4gKMIPBFV1nt/MNkj6oaTj7j4p2zZa0m8kjZfULekBd/9T89oc3ObMmZOsV/te/2rLSe/bt69i7cUXX0yOXbFiRbJebR6/mkmTJlWsdXV1NXTbaEwtZ/6Nku49b9tKSW+4+02S3siuAxhEqobf3d+WdPK8zbMlbcoub5KUPrUBaDv1Pue/1t2PSlL285r8WgLQCk1/wc/MFptZ2czKvb29zT4cgBrVG/5jZtYpSdnP45V2dPcudy+5e6mjo6POwwHIW73h3y5pYXZ5oaRX8mkHQKtUDb+ZbZH035JuNrMeM/uxpKck3W1mf5B0d3YdwCBSdZ7f3edXKM3MuZewrrzyyobGX3XVVXWPrfY+gHnz5iXrQ4bwPrHBiv85ICjCDwRF+IGgCD8QFOEHgiL8QFB8dfdFYO3atRVre/bsSY596623kvVqX909a9asZB3tizM/EBThB4Ii/EBQhB8IivADQRF+ICjCDwTFPP9FIPX12uvXr0+OvfXWW5P1RYsWJet33nlnsl4qlSrWlixZkhxrZsk6GsOZHwiK8ANBEX4gKMIPBEX4gaAIPxAU4QeCYp7/IjdhwoRkfePGjcn6I488kqxv3ry57vqXX36ZHPvQQw8l652dnck60jjzA0ERfiAowg8ERfiBoAg/EBThB4Ii/EBQVef5zWyDpB9KOu7uk7JtayUtktSb7bbK3V9tVpNonrlz5ybrN954Y7K+fPnyZD31vf9PPPFEcuynn36arK9evTpZHzt2bLIeXS1n/o2S7h1g+8/dfXL2j+ADg0zV8Lv725JOtqAXAC3UyHP+pWa2z8w2mNmo3DoC0BL1hv8XkiZImizpqKSfVtrRzBabWdnMyr29vZV2A9BidYXf3Y+5+xl3PytpvaSpiX273L3k7qWOjo56+wSQs7rCb2b9P041V9L+fNoB0Cq1TPVtkTRD0hgz65G0RtIMM5ssySV1S3q0iT0CaAJz95YdrFQqeblcbtnx0HynTp1K1nfs2FGx9vDDDyfHVvvdnDlzZrK+c+fOZP1iVCqVVC6Xa1rwgHf4AUERfiAowg8ERfiBoAg/EBThB4Jiqg+FufTSS5P1r7/+OlkfNmxYsv7aa69VrM2YMSM5drBiqg9AVYQfCIrwA0ERfiAowg8ERfiBoAg/EBRLdCNp3759yfrWrVuT9d27d1esVZvHr2bixInJ+u23397Q7V/sOPMDQRF+ICjCDwRF+IGgCD8QFOEHgiL8QFDM81/kDh06lKw///zzyfrLL7+crH/22WcX3FOtLrkk/evZ2dmZrA8ZwrkthXsHCIrwA0ERfiAowg8ERfiBoAg/EBThB4KqOs9vZuMkbZb0XUlnJXW5+7NmNlrSbySNl9Qt6QF3/1PzWo2r2lz6Sy+9VLG2bt265Nju7u56WsrFbbfdlqyvXr06Wb///vvzbCecWs7830ha7u5/L+kfJC0xs4mSVkp6w91vkvRGdh3AIFE1/O5+1N3fyy5/IemgpLGSZkvalO22SdKcZjUJIH8X9JzfzMZLmiLpXUnXuvtRqe8PhKRr8m4OQPPUHH4z+46k30n6ibv/+QLGLTazspmVe3t76+kRQBPUFH4zG6a+4P/K3c990uOYmXVm9U5Jxwca6+5d7l5y91JHR0cePQPIQdXwm5lJ+qWkg+7+s36l7ZIWZpcXSnol//YANEstH+mdLmmBpA/MbG+2bZWkpyT91sx+LOmwpB81p8XB79ixY8n6gQMHkvWlS5cm6x9++OEF95SXadOmJeuPP/54xdrs2bOTY/lIbnNVDb+775JUab3vmfm2A6BV+NMKBEX4gaAIPxAU4QeCIvxAUIQfCIqv7q7RyZMnK9YeffTR5Ni9e/cm6x9//HFdPeVh+vTpyfry5cuT9XvuuSdZv/zyyy+4J7QGZ34gKMIPBEX4gaAIPxAU4QeCIvxAUIQfCCrMPP+7776brD/99NPJ+u7duyvWenp66uopL1dccUXF2rJly5Jjq3099ogRI+rqCe2PMz8QFOEHgiL8QFCEHwiK8ANBEX4gKMIPBBVmnn/btm0N1RsxceLEZP2+++5L1ocOHZqsr1ixomLt6quvTo5FXJz5gaAIPxAU4QeCIvxAUIQfCIrwA0ERfiAoc/f0DmbjJG2W9F1JZyV1ufuzZrZW0iJJvdmuq9z91dRtlUolL5fLDTcNYGClUknlctlq2beWN/l8I2m5u79nZiMl7TGznVnt5+7+b/U2CqA4VcPv7kclHc0uf2FmByWNbXZjAJrrgp7zm9l4SVMknftOrKVmts/MNpjZqApjFptZ2czKvb29A+0CoAA1h9/MviPpd5J+4u5/lvQLSRMkTVbfI4OfDjTO3bvcveTupY6OjhxaBpCHmsJvZsPUF/xfufvLkuTux9z9jLuflbRe0tTmtQkgb1XDb2Ym6ZeSDrr7z/pt7+y321xJ+/NvD0Cz1PJq/3RJCyR9YGbn1ppeJWm+mU2W5JK6JaXXqQbQVmp5tX+XpIHmDZNz+gDaG+/wA4Ii/EBQhB8IivADQRF+ICjCDwRF+IGgCD8QFOEHgiL8QFCEHwiK8ANBEX4gKMIPBFX1q7tzPZhZr6RP+20aI+lEyxq4MO3aW7v2JdFbvfLs7QZ3r+n78loa/m8d3Kzs7qXCGkho197atS+J3upVVG887AeCIvxAUEWHv6vg46e0a2/t2pdEb/UqpLdCn/MDKE7RZ34ABSkk/GZ2r5kdMrOPzGxlET1UYmbdZvaBme01s0KXFM6WQTtuZvv7bRttZjvN7A/ZzwGXSSuot7Vm9n/ZfbfXzP6poN7GmdmbZnbQzA6Y2T9n2wu97xJ9FXK/tfxhv5kNlfS/ku6W1CNpt6T57v4/LW2kAjPrllRy98LnhM3sdkl/kbTZ3Sdl256WdNLdn8r+cI5y939pk97WSvpL0Ss3ZwvKdPZfWVrSHEkPq8D7LtHXAyrgfivizD9V0kfu/om7n5b0a0mzC+ij7bn725JOnrd5tqRN2eVN6vvlabkKvbUFdz/q7u9ll7+QdG5l6ULvu0RfhSgi/GMl/bHf9R6115LfLun3ZrbHzBYX3cwArs2WTT+3fPo1BfdzvqorN7fSeStLt819V8+K13krIvwDrf7TTlMO0939Vkk/kLQke3iL2tS0cnOrDLCydFuod8XrvBUR/h5J4/pd/56kIwX0MSB3P5L9PC5pm9pv9eFj5xZJzX4eL7ifv2qnlZsHWllabXDftdOK10WEf7ekm8zs+2Y2XNI8SdsL6ONbzGxE9kKMzGyEpFlqv9WHt0tamF1eKOmVAnv5G+2ycnOllaVV8H3XbiteF/Imn2wq498lDZW0wd3/teVNDMDM/k59Z3upbxHTl4rszcy2SJqhvk99HZO0RtJ/SPqtpOslHZb0I3dv+QtvFXqbob6Hrn9dufncc+wW9/aPkv5L0geSzmabV6nv+XVh912ir/kq4H7jHX5AULzDDwiK8ANBEX4gKMIPBEX4gaAIPxAU4QeCIvxAUP8Pt/ALPExulGgAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f5f308fd0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "timg, c = train_dataset[0]\n",
    "print(timg.shape, c)\n",
    "plt.imshow(timg.squeeze(0), cmap='gray_r')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Dataset MNIST\n",
       "    Number of datapoints: 10000\n",
       "    Root location: ./torch_datasets\n",
       "    Split: Test\n",
       "    StandardTransform\n",
       "Transform: Compose(\n",
       "               ToTensor()\n",
       "               Normalize(mean=(0.1307,), std=(0.3081,))\n",
       "           )"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([1, 28, 28]) 7\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x7f5bd21ba8>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f88355da0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "timg, c = test_dataset[0]\n",
    "print(timg.shape, c)\n",
    "plt.imshow(timg.squeeze(0), cmap='gray_r')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# DataLoader"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will now define the size of the batch we want to use. And we will create a dataloader that will allow us to get data from the dataset by batch of the given size (this will be easier than creating a loop ourselves)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "batchsize = 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_loader = torch.utils.data.DataLoader(train_dataset, batchsize)\n",
    "test_loader = torch.utils.data.DataLoader(test_dataset, batchsize)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#PYNQ Overlay"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will load the PYNQ overlay, and define handler for the AXI GPIO and DMA that are present in this overlay."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "\n",
       "try {\n",
       "require(['notebook/js/codecell'], function(codecell) {\n",
       "  codecell.CodeCell.options_default.highlight_modes[\n",
       "      'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n",
       "  Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
       "      Jupyter.notebook.get_cells().map(function(cell){\n",
       "          if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
       "  });\n",
       "});\n",
       "} catch (e) {};\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "\n",
       "try {\n",
       "require(['notebook/js/codecell'], function(codecell) {\n",
       "  codecell.CodeCell.options_default.highlight_modes[\n",
       "      'magic_text/x-csrc'] = {'reg':[/^%%pybind11/]};\n",
       "  Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n",
       "      Jupyter.notebook.get_cells().map(function(cell){\n",
       "          if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n",
       "  });\n",
       "});\n",
       "} catch (e) {};\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from pynq import Overlay\n",
    "from pynq import allocate\n",
    "import pynq.lib.dma"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load the overlay\n",
    "overlay = Overlay(\"/home/xilinx/pynq/overlays/multaccum/multaccum.bit\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load the AXI GPIO and DMAs\n",
    "axigpio_size = overlay.multaccum.din_size\n",
    "dma_in_a = overlay.multaccum.in_a_dma\n",
    "dma_in_b = overlay.multaccum.in_b_dma\n",
    "dma_out = overlay.multaccum.out_dma"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The DMAs require contiguous memory buffer. Let's allocate them."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "n = 2**21\n",
    "in_a_buffer = allocate(shape=(n,), dtype=np.float32)\n",
    "in_b_buffer = allocate(shape=(n,), dtype=np.float32)\n",
    "\n",
    "out_buffer = allocate(shape=(2**16,), dtype=np.float32)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Overlay driver function"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will now define the 'multaccumx' function that will use the FPGA to perform the following computation :\n",
    "\n",
    "    output = inputs @ weights.t() + bias"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def multaccumx(inputs, weights, bias):\n",
    "\n",
    "    # Check that the arguments are corretly shaped\n",
    "    if inputs.dim() != 2:\n",
    "        print(\"ERROR : 'inputs' dim is not 2 !\", inputs.dim())\n",
    "        print(inputs.shape)\n",
    "        return 0\n",
    "    if weights.dim() != 2:\n",
    "        print(\"ERROR : 'weights' dim is not 2 !\", weights.dim())\n",
    "        return 0\n",
    "    if bias.dim() != 1:\n",
    "        print(\"ERROR : 'bias' dim is not 1 !\", bias.dim())\n",
    "        return 0\n",
    "\n",
    "    #Store the sizes\n",
    "    nb_din, sz_din = inputs.shape\n",
    "    nb_neuron, sz_neuron = weights.shape\n",
    "    sz_bias = bias.shape[0]\n",
    "\n",
    "    # Check that the size match\n",
    "    if sz_din != sz_neuron:\n",
    "        print(\"ERROR : 'inputs' and 'weights' size is not equal !\", sz_din, sz_neuron)\n",
    "        return 0\n",
    "    if nb_neuron != sz_bias:\n",
    "        print(\"ERROR : 'weights' and 'bias' size is not equal !\", nb_neuron, sz_bias)\n",
    "        return 0\n",
    "\n",
    "    # Configure the 'multaccum' FPGA IP with din size minus 1\n",
    "    # (this is used in the IP to generate internal AXI Stream tlast) \n",
    "    axigpio_size.register_map.GPIO_DATA = sz_din-1    \n",
    "\n",
    "    # Store the weigths in the continuous buffer that will be transfered by the DMA\n",
    "    in_b_buffer[:nb_neuron*sz_neuron] = weights.flatten()\n",
    "\n",
    "    # Loop on all din\n",
    "    for i in range(nb_din):\n",
    "\n",
    "        # Store the inputs data in the continuous buffer that will be transfered by the DMA\n",
    "        # (the inputs data are repetaed as many times as the number of neuron in the layer)\n",
    "        in_a_buffer[:nb_neuron*sz_din] = inputs[i].unsqueeze(0).expand(nb_neuron, -1).flatten()\n",
    "\n",
    "        # Launch the DMA transferts\n",
    "        dma_out.recvchannel.transfer(out_buffer[i*nb_neuron:])\n",
    "        dma_in_b.sendchannel.transfer(in_b_buffer[:nb_neuron*sz_neuron])\n",
    "        dma_in_a.sendchannel.transfer(in_a_buffer[:nb_neuron*sz_din])\n",
    "\n",
    "        # Wait the end of result reception\n",
    "        dma_out.recvchannel.wait()\n",
    "\n",
    "    # Copy the result from the continuous buffer as a tensor of the correct shape\n",
    "    dout = torch.tensor(out_buffer[:nb_din*nb_neuron]).view(nb_din, nb_neuron) + bias\n",
    "    return dout\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Custom autograd function"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The 'multaccumx' function is just performing a computation.\n",
    "\n",
    "To be able to use it in a layer of a neural network, we need to wrap it to associate the corresponding gradient computation that will be required during the backward pass of the training."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "class MyLinx(torch.autograd.Function):\n",
    "    \"\"\"\n",
    "    We can implement our own custom autograd Functions by subclassing\n",
    "    torch.autograd.Function and implementing the forward and backward passes\n",
    "    which operate on Tensors.\n",
    "    \"\"\"\n",
    "\n",
    "    @staticmethod\n",
    "    def forward(ctx, input, weight, bias=None):\n",
    "        \"\"\"\n",
    "        In the forward pass we receive a context object and a Tensor containing the\n",
    "        input; we must return a Tensor containing the output, and we can use the\n",
    "        context object to cache objects for use in the backward pass.\n",
    "        \"\"\"\n",
    "        ctx.save_for_backward(input, weight, bias)\n",
    "        output = multaccumx(input, weight, bias)\n",
    "        #  if bias is not None:\n",
    "        #      output += bias.unsqueeze(0).expand_as(output)\n",
    "        return output\n",
    "\n",
    "    # This function has only a single output, so it gets only one gradient\n",
    "    @staticmethod\n",
    "    def backward(ctx, grad_output):\n",
    "        \"\"\"\n",
    "        In the backward pass we receive the context object and a Tensor containing\n",
    "        the gradient of the loss with respect to the output produced during the\n",
    "        forward pass. We can retrieve cached data from the context object, and must\n",
    "        compute and return the gradient of the loss with respect to the input to the\n",
    "        forward function.\n",
    "        \"\"\"\n",
    "        input, weight, bias = ctx.saved_tensors\n",
    "        grad_input = grad_weight = grad_bias = None\n",
    "\n",
    "        if ctx.needs_input_grad[0]:\n",
    "            grad_input = grad_output.mm(weight)\n",
    "        if ctx.needs_input_grad[1]:\n",
    "            grad_weight = grad_output.t().mm(input)\n",
    "        if bias is not None and ctx.needs_input_grad[2]:\n",
    "            grad_bias = grad_output.sum(0).squeeze(0)\n",
    "\n",
    "        return grad_input, grad_weight, grad_bias\n",
    "\n",
    "\n",
    "mylinx = MyLinx.apply\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Custom nn.Linear"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "PyTorch contains object that can easily be used to build a neural network.\n",
    "\n",
    "We don't want to recreate completely such an object, as we just want to change\n",
    "the way the forward computation of a linear layer is computed (to use the FPGA to compute it).\n",
    "\n",
    "We can do this by simply overiding the forward part of the existing 'nn.Linear' object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "class myLinearX(nn.Linear):\n",
    "        \n",
    "    def forward(self, input):\n",
    "        #output = input @ self.weight.t() + self.bias\n",
    "        output = mylinx(input.flatten(1), self.weight, self.bias)\n",
    "        return output"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Neural Network Model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We have now all the pieces we needed. We can define the neural network model we want, and use our new 'myLinearX' linear layer in it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "mymodelx = nn.Sequential(\n",
    "    nn.Flatten(),\n",
    "    myLinearX(784,128),\n",
    "    nn.ReLU(),\n",
    "    myLinearX(128,32),\n",
    "    nn.ReLU(),\n",
    "    myLinearX(32, 10),\n",
    "    nn.LogSoftmax(dim=1)\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This model defines :\n",
    "* the architecture of the network,\n",
    "* the parameters of the network,\n",
    "* the initilization of these parameters,\n",
    "* and the gradient that will be computed.\n",
    "\n",
    "We also need to define the way we will upgrade the parameters with the computed gradient, and the associated learning rate. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "myoptimizerx = torch.optim.SGD(mymodelx.parameters(), lr=1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Training time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To train our network we need to :\n",
    "* reinitialize all the gradients to 0\n",
    "* perform a forward pass on a batch of data to compute the output of the model\n",
    "* compute a loss to evaluate how far our output is from the required output\n",
    "* use the computed loss to perform the backward pass that will define all the gradients\n",
    "* update the parameters with the computed gradient as defined in our optimizer\n",
    "* repeat until the end of the train dataset\n",
    "\n",
    "We will gather all theses steps in a 'train' function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train(model, train_loader, optimizer, epoch):\n",
    "    model.train()\n",
    "    for batch_idx, (data, target) in enumerate(train_loader):\n",
    "        optimizer.zero_grad()\n",
    "        output = model(data)\n",
    "        loss = F.nll_loss(output, target)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        if batch_idx % 1000 == 0:\n",
    "            print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n",
    "                epoch, batch_idx * len(data), len(train_loader.dataset),\n",
    "                100. * batch_idx / len(train_loader), loss.item()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We need to evaluate how good our training is.\n",
    "\n",
    "For this, the output of the model is used to perform a prediction that is supposed to match with the target output. We will use the test dataset to check how many time the prediciotn is correct for data our model have not used for its training.\n",
    "\n",
    "As this is for evaluation only, we will only perform the forward pass, and no gradient computation will be required.\n",
    "\n",
    "Let's define a 'test' fucntion that will perform this evaluation on the test dataset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test(model, test_loader):\n",
    "    model.eval()\n",
    "    test_loss = 0\n",
    "    correct = 0\n",
    "    with torch.no_grad():\n",
    "        for batch_idx, (data, target) in enumerate(test_loader):\n",
    "            output = model(data)\n",
    "            test_loss += F.nll_loss(output, target, reduction='sum').item()  # sum up batch loss\n",
    "            pred = output.argmax(dim=1, keepdim=True)  # get the index of the max log-probability\n",
    "            correct += pred.eq(target.view_as(pred)).sum().item()\n",
    "            if batch_idx % 1000 == 0:\n",
    "                print(\"Test batch index:\", batch_idx)\n",
    "\n",
    "    test_loss /= len(test_loader.dataset)\n",
    "\n",
    "    print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)\\n'.format(\n",
    "        test_loss, correct, len(test_loader.dataset),\n",
    "        100. * correct / len(test_loader.dataset)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now launch the training. As this training is slow, we will do only one epoch."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train Epoch: 0 [0/60000 (0%)]\tLoss: 2.406540\n",
      "Train Epoch: 0 [4000/60000 (7%)]\tLoss: 1.743816\n",
      "Train Epoch: 0 [8000/60000 (13%)]\tLoss: 0.602789\n",
      "Train Epoch: 0 [12000/60000 (20%)]\tLoss: 0.708294\n",
      "Train Epoch: 0 [16000/60000 (27%)]\tLoss: 0.649807\n",
      "Train Epoch: 0 [20000/60000 (33%)]\tLoss: 0.687648\n",
      "Train Epoch: 0 [24000/60000 (40%)]\tLoss: 0.352677\n",
      "Train Epoch: 0 [28000/60000 (47%)]\tLoss: 0.047605\n",
      "Train Epoch: 0 [32000/60000 (53%)]\tLoss: 0.208460\n",
      "Train Epoch: 0 [36000/60000 (60%)]\tLoss: 0.310835\n",
      "Train Epoch: 0 [40000/60000 (67%)]\tLoss: 0.026316\n",
      "Train Epoch: 0 [44000/60000 (73%)]\tLoss: 0.335622\n",
      "Train Epoch: 0 [48000/60000 (80%)]\tLoss: 0.087380\n",
      "Train Epoch: 0 [52000/60000 (87%)]\tLoss: 0.023506\n",
      "Train Epoch: 0 [56000/60000 (93%)]\tLoss: 0.228996\n"
     ]
    },
    {
     "ename": "NameError",
     "evalue": "name 'device' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-21-b75fede2fb66>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mepoch\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m     \u001b[0mtrain\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmymodelx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtrain_loader\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmyoptimizerx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mepoch\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m     \u001b[0mtest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmymodelx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtest_loader\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m<ipython-input-20-dc8d1d609526>\u001b[0m in \u001b[0;36mtest\u001b[0;34m(model, test_loader)\u001b[0m\n\u001b[1;32m      5\u001b[0m     \u001b[0;32mwith\u001b[0m \u001b[0mtorch\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mno_grad\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      6\u001b[0m         \u001b[0;32mfor\u001b[0m \u001b[0mbatch_idx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtarget\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtest_loader\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 7\u001b[0;31m             \u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtarget\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdevice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtarget\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mto\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdevice\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      8\u001b[0m             \u001b[0moutput\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmodel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      9\u001b[0m             \u001b[0mtest_loss\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mF\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnll_loss\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0moutput\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtarget\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreduction\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'sum'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitem\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m  \u001b[0;31m# sum up batch loss\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mNameError\u001b[0m: name 'device' is not defined"
     ]
    }
   ],
   "source": [
    "for epoch in range(1):\n",
    "    train(mymodelx, train_loader, myoptimizerx, epoch)\n",
    "    test(mymodelx, test_loader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test batch index: 0\n",
      "Test batch index: 1000\n",
      "Test batch index: 2000\n",
      "\n",
      "Test set: Average loss: 0.3096, Accuracy: 9058/10000 (90.58%)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "test(mymodelx, test_loader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}

design_multaccum.tcl

Tcl
TCL script to rebuild the 'multaccum' Vivado block design used as PYNQ overlay
################################################################
# This is a generated script based on design: design_1
#
# Though there are limitations about the generated script,
# the main purpose of this utility is to make learning
# IP Integrator Tcl commands easier.
################################################################

namespace eval _tcl {
proc get_script_folder {} {
   set script_path [file normalize [info script]]
   set script_folder [file dirname $script_path]
   return $script_folder
}
}
variable script_folder
set script_folder [_tcl::get_script_folder]

################################################################
# Check if script is running in correct Vivado version.
################################################################
set scripts_vivado_version 2020.1
set current_vivado_version [version -short]

if { [string first $scripts_vivado_version $current_vivado_version] == -1 } {
   puts ""
   catch {common::send_gid_msg -ssname BD::TCL -id 2041 -severity "ERROR" "This script was generated using Vivado <$scripts_vivado_version> and is being run in <$current_vivado_version> of Vivado. Please run the script in Vivado <$scripts_vivado_version> then open the design in Vivado <$current_vivado_version>. Upgrade the design by running \"Tools => Report => Report IP Status...\", then run write_bd_tcl to create an updated script."}

   return 1
}

################################################################
# START
################################################################

# To test this script, run the following commands from Vivado Tcl console:
# source design_1_script.tcl


# The design that will be created by this Tcl script contains the following 
# module references:
# gentlast

# Please add the sources of those modules before sourcing this Tcl script.

# If there is no project opened, this script will create a
# project, but make sure you do not have an existing project
# <./myproj/project_1.xpr> in the current working folder.

set list_projs [get_projects -quiet]
if { $list_projs eq "" } {
   create_project project_1 myproj -part xczu3eg-sbva484-1-i
   set_property BOARD_PART avnet.com:ultra96v2:part0:1.1 [current_project]
}


# CHANGE DESIGN NAME HERE
variable design_name
set design_name design_1

# If you do not already have an existing IP Integrator design open,
# you can create a design using the following command:
#    create_bd_design $design_name

# Creating design if needed
set errMsg ""
set nRet 0

set cur_design [current_bd_design -quiet]
set list_cells [get_bd_cells -quiet]

if { ${design_name} eq "" } {
   # USE CASES:
   #    1) Design_name not set

   set errMsg "Please set the variable <design_name> to a non-empty value."
   set nRet 1

} elseif { ${cur_design} ne "" && ${list_cells} eq "" } {
   # USE CASES:
   #    2): Current design opened AND is empty AND names same.
   #    3): Current design opened AND is empty AND names diff; design_name NOT in project.
   #    4): Current design opened AND is empty AND names diff; design_name exists in project.

   if { $cur_design ne $design_name } {
      common::send_gid_msg -ssname BD::TCL -id 2001 -severity "INFO" "Changing value of <design_name> from <$design_name> to <$cur_design> since current design is empty."
      set design_name [get_property NAME $cur_design]
   }
   common::send_gid_msg -ssname BD::TCL -id 2002 -severity "INFO" "Constructing design in IPI design <$cur_design>..."

} elseif { ${cur_design} ne "" && $list_cells ne "" && $cur_design eq $design_name } {
   # USE CASES:
   #    5) Current design opened AND has components AND same names.

   set errMsg "Design <$design_name> already exists in your project, please set the variable <design_name> to another value."
   set nRet 1
} elseif { [get_files -quiet ${design_name}.bd] ne "" } {
   # USE CASES: 
   #    6) Current opened design, has components, but diff names, design_name exists in project.
   #    7) No opened design, design_name exists in project.

   set errMsg "Design <$design_name> already exists in your project, please set the variable <design_name> to another value."
   set nRet 2

} else {
   # USE CASES:
   #    8) No opened design, design_name not in project.
   #    9) Current opened design, has components, but diff names, design_name not in project.

   common::send_gid_msg -ssname BD::TCL -id 2003 -severity "INFO" "Currently there is no design <$design_name> in project, so creating one..."

   create_bd_design $design_name

   common::send_gid_msg -ssname BD::TCL -id 2004 -severity "INFO" "Making design <$design_name> as current_bd_design."
   current_bd_design $design_name

}

common::send_gid_msg -ssname BD::TCL -id 2005 -severity "INFO" "Currently the variable <design_name> is equal to \"$design_name\"."

if { $nRet != 0 } {
   catch {common::send_gid_msg -ssname BD::TCL -id 2006 -severity "ERROR" $errMsg}
   return $nRet
}

set bCheckIPsPassed 1
##################################################################
# CHECK IPs
##################################################################
set bCheckIPs 1
if { $bCheckIPs == 1 } {
   set list_check_ips "\ 
xilinx.com:ip:smartconnect:1.0\
xilinx.com:ip:clk_wiz:6.0\
xilinx.com:ip:proc_sys_reset:5.0\
xilinx.com:ip:zynq_ultra_ps_e:3.3\
xilinx.com:ip:axis_broadcaster:1.1\
xilinx.com:ip:axis_subset_converter:1.1\
xilinx.com:ip:axi_gpio:2.0\
xilinx.com:ip:floating_point:7.1\
xilinx.com:ip:c_shift_ram:12.0\
xilinx.com:ip:axi_dma:7.1\
xilinx.com:ip:util_vector_logic:2.0\
xilinx.com:ip:xlconstant:1.1\
"

   set list_ips_missing ""
   common::send_gid_msg -ssname BD::TCL -id 2011 -severity "INFO" "Checking if the following IPs exist in the project's IP catalog: $list_check_ips ."

   foreach ip_vlnv $list_check_ips {
      set ip_obj [get_ipdefs -all $ip_vlnv]
      if { $ip_obj eq "" } {
         lappend list_ips_missing $ip_vlnv
      }
   }

   if { $list_ips_missing ne "" } {
      catch {common::send_gid_msg -ssname BD::TCL -id 2012 -severity "ERROR" "The following IPs are not found in the IP Catalog:\n  $list_ips_missing\n\nResolution: Please add the repository containing the IP(s) to the project." }
      set bCheckIPsPassed 0
   }

}

##################################################################
# CHECK Modules
##################################################################
set bCheckModules 1
if { $bCheckModules == 1 } {
   set list_check_mods "\ 
gentlast\
"

   set list_mods_missing ""
   common::send_gid_msg -ssname BD::TCL -id 2020 -severity "INFO" "Checking if the following modules exist in the project's sources: $list_check_mods ."

   foreach mod_vlnv $list_check_mods {
      if { [can_resolve_reference $mod_vlnv] == 0 } {
         lappend list_mods_missing $mod_vlnv
      }
   }

   if { $list_mods_missing ne "" } {
      catch {common::send_gid_msg -ssname BD::TCL -id 2021 -severity "ERROR" "The following module(s) are not found in the project: $list_mods_missing" }
      common::send_gid_msg -ssname BD::TCL -id 2022 -severity "INFO" "Please add source files for the missing module(s) above."
      set bCheckIPsPassed 0
   }
}

if { $bCheckIPsPassed != 1 } {
  common::send_gid_msg -ssname BD::TCL -id 2023 -severity "WARNING" "Will not continue with creation of design due to the error(s) above."
  return 3
}

##################################################################
# DESIGN PROCs
##################################################################


# Hierarchical cell: multaccum
proc create_hier_cell_multaccum { parentCell nameHier } {

  variable script_folder

  if { $parentCell eq "" || $nameHier eq "" } {
     catch {common::send_gid_msg -ssname BD::TCL -id 2092 -severity "ERROR" "create_hier_cell_multaccum() - Empty argument(s)!"}
     return
  }

  # Get object for parentCell
  set parentObj [get_bd_cells $parentCell]
  if { $parentObj == "" } {
     catch {common::send_gid_msg -ssname BD::TCL -id 2090 -severity "ERROR" "Unable to find parent cell <$parentCell>!"}
     return
  }

  # Make sure parentObj is hier blk
  set parentType [get_property TYPE $parentObj]
  if { $parentType ne "hier" } {
     catch {common::send_gid_msg -ssname BD::TCL -id 2091 -severity "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be <hier>."}
     return
  }

  # Save current instance; Restore later
  set oldCurInst [current_bd_instance .]

  # Set parent object as current
  current_bd_instance $parentObj

  # Create cell and set as current instance
  set hier_obj [create_bd_cell -type hier $nameHier]
  current_bd_instance $hier_obj

  # Create interface pins
  create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:aximm_rtl:1.0 M_AXI_MM2S

  create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:aximm_rtl:1.0 M_AXI_MM2S1

  create_bd_intf_pin -mode Master -vlnv xilinx.com:interface:aximm_rtl:1.0 M_AXI_S2MM

  create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S_AXI

  create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S_AXI_LITE

  create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S_AXI_LITE1

  create_bd_intf_pin -mode Slave -vlnv xilinx.com:interface:aximm_rtl:1.0 S_AXI_LITE2


  # Create pins
  create_bd_pin -dir I -type clk aclk
  create_bd_pin -dir I -type rst aresetn
  create_bd_pin -dir I -type rst axi_resetn
  create_bd_pin -dir I -type clk m_axi_s2mm_aclk

  # Create instance: axis_broadcaster_0, and set properties
  set axis_broadcaster_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axis_broadcaster:1.1 axis_broadcaster_0 ]
  set_property -dict [ list \
   CONFIG.M00_TDATA_REMAP {tdata[31:0]} \
   CONFIG.M01_TDATA_REMAP {tdata[31:0]} \
   CONFIG.M_TDATA_NUM_BYTES {4} \
   CONFIG.S_TDATA_NUM_BYTES {4} \
 ] $axis_broadcaster_0

  # Create instance: axis_subset_converter_0, and set properties
  set axis_subset_converter_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:axis_subset_converter:1.1 axis_subset_converter_0 ]
  set_property -dict [ list \
   CONFIG.M_HAS_TLAST {1} \
   CONFIG.M_HAS_TREADY {1} \
   CONFIG.M_TDATA_NUM_BYTES {4} \
   CONFIG.S_HAS_TLAST {1} \
   CONFIG.S_TDATA_NUM_BYTES {4} \
   CONFIG.TDATA_REMAP {tdata[31:0]} \
   CONFIG.TLAST_REMAP {tlast[0]} \
 ] $axis_subset_converter_0

  # Create instance: din_size, and set properties
  set din_size [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_gpio:2.0 din_size ]
  set_property -dict [ list \
   CONFIG.C_ALL_OUTPUTS {1} \
   CONFIG.C_DOUT_DEFAULT {0x00000000} \
   CONFIG.C_GPIO_WIDTH {16} \
   CONFIG.C_IS_DUAL {0} \
 ] $din_size

  # Create instance: faccum, and set properties
  set faccum [ create_bd_cell -type ip -vlnv xilinx.com:ip:floating_point:7.1 faccum ]
  set_property -dict [ list \
   CONFIG.Add_Sub_Value {Add} \
   CONFIG.Axi_Optimize_Goal {Performance} \
   CONFIG.C_Accum_Input_Msb {32} \
   CONFIG.C_Accum_Lsb {-149} \
   CONFIG.C_Accum_Msb {127} \
   CONFIG.C_Latency {39} \
   CONFIG.C_Mult_Usage {Medium_Usage} \
   CONFIG.C_Rate {1} \
   CONFIG.C_Result_Exponent_Width {8} \
   CONFIG.C_Result_Fraction_Width {24} \
   CONFIG.Has_A_TLAST {true} \
   CONFIG.Operation_Type {Accumulator} \
   CONFIG.RESULT_TLAST_Behv {Pass_A_TLAST} \
   CONFIG.Result_Precision_Type {Single} \
 ] $faccum

  # Create instance: faccum_shreg, and set properties
  set faccum_shreg [ create_bd_cell -type ip -vlnv xilinx.com:ip:c_shift_ram:12.0 faccum_shreg ]
  set_property -dict [ list \
   CONFIG.AsyncInitVal {0} \
   CONFIG.DefaultData {0} \
   CONFIG.Depth {39} \
   CONFIG.SyncInitVal {0} \
   CONFIG.Width {1} \
 ] $faccum_shreg

  # Create instance: fmult, and set properties
  set fmult [ create_bd_cell -type ip -vlnv xilinx.com:ip:floating_point:7.1 fmult ]
  set_property -dict [ list \
   CONFIG.Add_Sub_Value {Both} \
   CONFIG.Axi_Optimize_Goal {Performance} \
   CONFIG.C_Latency {11} \
   CONFIG.C_Mult_Usage {Full_Usage} \
   CONFIG.C_Rate {1} \
   CONFIG.C_Result_Exponent_Width {8} \
   CONFIG.C_Result_Fraction_Width {24} \
   CONFIG.Has_A_TLAST {true} \
   CONFIG.Operation_Type {Multiply} \
   CONFIG.RESULT_TLAST_Behv {Pass_A_TLAST} \
   CONFIG.Result_Precision_Type {Single} \
 ] $fmult

  # Create instance: fmult_shreg, and set properties
  set fmult_shreg [ create_bd_cell -type ip -vlnv xilinx.com:ip:c_shift_ram:12.0 fmult_shreg ]
  set_property -dict [ list \
   CONFIG.AsyncInitVal {0} \
   CONFIG.DefaultData {0} \
   CONFIG.Depth {11} \
   CONFIG.SyncInitVal {0} \
   CONFIG.Width {1} \
 ] $fmult_shreg

  # Create instance: gentlast_din, and set properties
  set block_name gentlast
  set block_cell_name gentlast_din
  if { [catch {set gentlast_din [create_bd_cell -type module -reference $block_name $block_cell_name] } errmsg] } {
     catch {common::send_gid_msg -ssname BD::TCL -id 2095 -severity "ERROR" "Unable to add referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."}
     return 1
   } elseif { $gentlast_din eq "" } {
     catch {common::send_gid_msg -ssname BD::TCL -id 2096 -severity "ERROR" "Unable to referenced block <$block_name>. Please add the files for ${block_name}'s definition into the project."}
     return 1
   }
  
  # Create instance: in_a_dma, and set properties
  set in_a_dma [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_dma:7.1 in_a_dma ]
  set_property -dict [ list \
   CONFIG.c_include_s2mm {0} \
   CONFIG.c_include_sg {0} \
   CONFIG.c_sg_include_stscntrl_strm {0} \
   CONFIG.c_sg_length_width {26} \
 ] $in_a_dma

  # Create instance: in_b_dma, and set properties
  set in_b_dma [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_dma:7.1 in_b_dma ]
  set_property -dict [ list \
   CONFIG.c_include_s2mm {0} \
   CONFIG.c_include_sg {0} \
   CONFIG.c_sg_include_stscntrl_strm {0} \
   CONFIG.c_sg_length_width {26} \
 ] $in_b_dma

  # Create instance: out_dma, and set properties
  set out_dma [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_dma:7.1 out_dma ]
  set_property -dict [ list \
   CONFIG.c_include_mm2s {0} \
   CONFIG.c_include_sg {0} \
   CONFIG.c_sg_include_stscntrl_strm {0} \
   CONFIG.c_sg_length_width {26} \
 ] $out_dma

  # Create instance: util_vector_logic_0, and set properties
  set util_vector_logic_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_0 ]
  set_property -dict [ list \
   CONFIG.C_SIZE {1} \
 ] $util_vector_logic_0

  # Create instance: util_vector_logic_1, and set properties
  set util_vector_logic_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:util_vector_logic:2.0 util_vector_logic_1 ]
  set_property -dict [ list \
   CONFIG.C_SIZE {1} \
 ] $util_vector_logic_1

  # Create instance: xlconstant_1, and set properties
  set xlconstant_1 [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlconstant:1.1 xlconstant_1 ]

  # Create interface connections
  connect_bd_intf_net -intf_net Conn1 [get_bd_intf_pins M_AXI_MM2S] [get_bd_intf_pins in_a_dma/M_AXI_MM2S]
  connect_bd_intf_net -intf_net Conn2 [get_bd_intf_pins M_AXI_S2MM] [get_bd_intf_pins out_dma/M_AXI_S2MM]
  connect_bd_intf_net -intf_net Conn3 [get_bd_intf_pins S_AXI_LITE] [get_bd_intf_pins out_dma/S_AXI_LITE]
  connect_bd_intf_net -intf_net Conn4 [get_bd_intf_pins S_AXI_LITE1] [get_bd_intf_pins in_b_dma/S_AXI_LITE]
  connect_bd_intf_net -intf_net Conn5 [get_bd_intf_pins M_AXI_MM2S1] [get_bd_intf_pins in_b_dma/M_AXI_MM2S]
  connect_bd_intf_net -intf_net Conn6 [get_bd_intf_pins S_AXI_LITE2] [get_bd_intf_pins in_a_dma/S_AXI_LITE]
  connect_bd_intf_net -intf_net Conn7 [get_bd_intf_pins S_AXI] [get_bd_intf_pins din_size/S_AXI]
  connect_bd_intf_net -intf_net axis_broadcaster_0_M00_AXIS [get_bd_intf_pins axis_broadcaster_0/M00_AXIS] [get_bd_intf_pins fmult/S_AXIS_B]
  connect_bd_intf_net -intf_net axis_broadcaster_0_M01_AXIS [get_bd_intf_pins axis_broadcaster_0/M01_AXIS] [get_bd_intf_pins axis_subset_converter_0/S_AXIS]
  connect_bd_intf_net -intf_net in_a_dma_M_AXIS_MM2S [get_bd_intf_pins fmult/S_AXIS_A] [get_bd_intf_pins in_a_dma/M_AXIS_MM2S]
  connect_bd_intf_net -intf_net in_b_dma_M_AXIS_MM2S [get_bd_intf_pins axis_broadcaster_0/S_AXIS] [get_bd_intf_pins in_b_dma/M_AXIS_MM2S]

  # Create port connections
  connect_bd_net -net aclk_1 [get_bd_pins aclk] [get_bd_pins axis_broadcaster_0/aclk] [get_bd_pins axis_subset_converter_0/aclk] [get_bd_pins faccum/aclk] [get_bd_pins faccum_shreg/CLK] [get_bd_pins fmult/aclk] [get_bd_pins fmult_shreg/CLK] [get_bd_pins gentlast_din/clk] [get_bd_pins in_a_dma/m_axi_mm2s_aclk] [get_bd_pins in_b_dma/m_axi_mm2s_aclk] [get_bd_pins out_dma/m_axi_s2mm_aclk]
  connect_bd_net -net aresetn_1 [get_bd_pins aresetn] [get_bd_pins axis_broadcaster_0/aresetn] [get_bd_pins axis_subset_converter_0/aresetn] [get_bd_pins gentlast_din/rstn]
  connect_bd_net -net axi_resetn_1 [get_bd_pins axi_resetn] [get_bd_pins din_size/s_axi_aresetn] [get_bd_pins in_a_dma/axi_resetn] [get_bd_pins in_b_dma/axi_resetn] [get_bd_pins out_dma/axi_resetn]
  connect_bd_net -net axis_subset_converter_0_m_axis_tlast [get_bd_pins axis_subset_converter_0/m_axis_tlast] [get_bd_pins util_vector_logic_1/Op1]
  connect_bd_net -net axis_subset_converter_0_m_axis_tvalid [get_bd_pins axis_subset_converter_0/m_axis_tvalid] [get_bd_pins util_vector_logic_1/Op2]
  connect_bd_net -net din_size_gpio_io_o [get_bd_pins din_size/gpio_io_o] [get_bd_pins gentlast_din/i_size_m1]
  connect_bd_net -net faccum_m_axis_result_tdata [get_bd_pins faccum/m_axis_result_tdata] [get_bd_pins out_dma/s_axis_s2mm_tdata]
  connect_bd_net -net faccum_m_axis_result_tlast [get_bd_pins faccum/m_axis_result_tlast] [get_bd_pins util_vector_logic_0/Op1]
  connect_bd_net -net faccum_m_axis_result_tvalid [get_bd_pins faccum/m_axis_result_tvalid] [get_bd_pins util_vector_logic_0/Op2]
  connect_bd_net -net faccum_s_axis_a_tready [get_bd_pins faccum/s_axis_a_tready] [get_bd_pins fmult/m_axis_result_tready] [get_bd_pins gentlast_din/i_ready]
  connect_bd_net -net faccum_shreg_Q [get_bd_pins faccum_shreg/Q] [get_bd_pins out_dma/s_axis_s2mm_tlast]
  connect_bd_net -net fmult_m_axis_result_tdata [get_bd_pins faccum/s_axis_a_tdata] [get_bd_pins fmult/m_axis_result_tdata]
  connect_bd_net -net fmult_m_axis_result_tvalid [get_bd_pins faccum/s_axis_a_tvalid] [get_bd_pins fmult/m_axis_result_tvalid] [get_bd_pins gentlast_din/i_valid]
  connect_bd_net -net fmult_shreg_Q [get_bd_pins faccum_shreg/D] [get_bd_pins fmult_shreg/Q]
  connect_bd_net -net gentlast_din_o_last [get_bd_pins faccum/s_axis_a_tlast] [get_bd_pins gentlast_din/o_last]
  connect_bd_net -net m_axi_s2mm_aclk_1 [get_bd_pins m_axi_s2mm_aclk] [get_bd_pins din_size/s_axi_aclk] [get_bd_pins in_a_dma/s_axi_lite_aclk] [get_bd_pins in_b_dma/s_axi_lite_aclk] [get_bd_pins out_dma/s_axi_lite_aclk]
  connect_bd_net -net out_dma_s_axis_s2mm_tready [get_bd_pins faccum/m_axis_result_tready] [get_bd_pins out_dma/s_axis_s2mm_tready]
  connect_bd_net -net util_vector_logic_0_Res [get_bd_pins out_dma/s_axis_s2mm_tvalid] [get_bd_pins util_vector_logic_0/Res]
  connect_bd_net -net util_vector_logic_1_Res [get_bd_pins fmult_shreg/D] [get_bd_pins util_vector_logic_1/Res]
  connect_bd_net -net xlconstant_1_dout [get_bd_pins axis_subset_converter_0/m_axis_tready] [get_bd_pins xlconstant_1/dout]

  # Restore current instance
  current_bd_instance $oldCurInst
}


# Procedure to create entire design; Provide argument to make
# procedure reusable. If parentCell is "", will use root.
proc create_root_design { parentCell } {

  variable script_folder
  variable design_name

  if { $parentCell eq "" } {
     set parentCell [get_bd_cells /]
  }

  # Get object for parentCell
  set parentObj [get_bd_cells $parentCell]
  if { $parentObj == "" } {
     catch {common::send_gid_msg -ssname BD::TCL -id 2090 -severity "ERROR" "Unable to find parent cell <$parentCell>!"}
     return
  }

  # Make sure parentObj is hier blk
  set parentType [get_property TYPE $parentObj]
  if { $parentType ne "hier" } {
     catch {common::send_gid_msg -ssname BD::TCL -id 2091 -severity "ERROR" "Parent <$parentObj> has TYPE = <$parentType>. Expected to be <hier>."}
     return
  }

  # Save current instance; Restore later
  set oldCurInst [current_bd_instance .]

  # Set parent object as current
  current_bd_instance $parentObj


  # Create interface ports

  # Create ports

  # Create instance: axi_smc, and set properties
  set axi_smc [ create_bd_cell -type ip -vlnv xilinx.com:ip:smartconnect:1.0 axi_smc ]
  set_property -dict [ list \
   CONFIG.NUM_SI {3} \
 ] $axi_smc

  # Create instance: clk_wiz_0, and set properties
  set clk_wiz_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:clk_wiz:6.0 clk_wiz_0 ]
  set_property -dict [ list \
   CONFIG.CLKOUT1_JITTER {94.862} \
   CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {300.000} \
   CONFIG.MMCM_CLKOUT0_DIVIDE_F {4.000} \
   CONFIG.USE_LOCKED {true} \
   CONFIG.USE_RESET {false} \
 ] $clk_wiz_0

  # Create instance: multaccum
  create_hier_cell_multaccum [current_bd_instance .] multaccum

  # Create instance: ps8_0_axi_periph, and set properties
  set ps8_0_axi_periph [ create_bd_cell -type ip -vlnv xilinx.com:ip:axi_interconnect:2.1 ps8_0_axi_periph ]
  set_property -dict [ list \
   CONFIG.NUM_MI {4} \
   CONFIG.NUM_SI {2} \
 ] $ps8_0_axi_periph

  # Create instance: rst_ps8_0_100M, and set properties
  set rst_ps8_0_100M [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 rst_ps8_0_100M ]

  # Create instance: rst_ps8_0_300M, and set properties
  set rst_ps8_0_300M [ create_bd_cell -type ip -vlnv xilinx.com:ip:proc_sys_reset:5.0 rst_ps8_0_300M ]

  # Create instance: zynq_ultra_ps_e_0, and set properties
  set zynq_ultra_ps_e_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:zynq_ultra_ps_e:3.3 zynq_ultra_ps_e_0 ]
  set_property -dict [ list \
   CONFIG.PSU_BANK_0_IO_STANDARD {LVCMOS18} \
   CONFIG.PSU_BANK_1_IO_STANDARD {LVCMOS18} \
   CONFIG.PSU_BANK_2_IO_STANDARD {LVCMOS18} \
   CONFIG.PSU_BANK_3_IO_STANDARD {LVCMOS18} \
   CONFIG.PSU_DDR_RAM_HIGHADDR {0x7FFFFFFF} \
   CONFIG.PSU_DDR_RAM_HIGHADDR_OFFSET {0x00000002} \
   CONFIG.PSU_DDR_RAM_LOWADDR_OFFSET {0x80000000} \
   CONFIG.PSU_DYNAMIC_DDR_CONFIG_EN {0} \
   CONFIG.PSU_MIO_0_DIRECTION {out} \
   CONFIG.PSU_MIO_0_INPUT_TYPE {cmos} \
   CONFIG.PSU_MIO_0_POLARITY {Default} \
   CONFIG.PSU_MIO_10_DIRECTION {inout} \
   CONFIG.PSU_MIO_10_POLARITY {Default} \
   CONFIG.PSU_MIO_11_DIRECTION {inout} \
   CONFIG.PSU_MIO_11_POLARITY {Default} \
   CONFIG.PSU_MIO_12_DIRECTION {inout} \
   CONFIG.PSU_MIO_12_POLARITY {Default} \
   CONFIG.PSU_MIO_13_DIRECTION {inout} \
   CONFIG.PSU_MIO_13_DRIVE_STRENGTH {4} \
   CONFIG.PSU_MIO_13_POLARITY {Default} \
   CONFIG.PSU_MIO_14_DIRECTION {inout} \
   CONFIG.PSU_MIO_14_DRIVE_STRENGTH {4} \
   CONFIG.PSU_MIO_14_POLARITY {Default} \
   CONFIG.PSU_MIO_15_DIRECTION {inout} \
   CONFIG.PSU_MIO_15_DRIVE_STRENGTH {4} \
   CONFIG.PSU_MIO_15_POLARITY {Default} \
   CONFIG.PSU_MIO_16_DIRECTION {inout} \
   CONFIG.PSU_MIO_16_DRIVE_STRENGTH {4} \
   CONFIG.PSU_MIO_16_POLARITY {Default} \
   CONFIG.PSU_MIO_17_DIRECTION {inout} \
   CONFIG.PSU_MIO_17_POLARITY {Default} \
   CONFIG.PSU_MIO_18_DIRECTION {inout} \
   CONFIG.PSU_MIO_18_POLARITY {Default} \
   CONFIG.PSU_MIO_19_DIRECTION {inout} \
   CONFIG.PSU_MIO_19_POLARITY {Default} \
   CONFIG.PSU_MIO_1_DIRECTION {in} \
   CONFIG.PSU_MIO_1_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_1_POLARITY {Default} \
   CONFIG.PSU_MIO_1_SLEW {fast} \
   CONFIG.PSU_MIO_20_DIRECTION {inout} \
   CONFIG.PSU_MIO_20_POLARITY {Default} \
   CONFIG.PSU_MIO_21_DIRECTION {inout} \
   CONFIG.PSU_MIO_21_DRIVE_STRENGTH {4} \
   CONFIG.PSU_MIO_21_POLARITY {Default} \
   CONFIG.PSU_MIO_22_DIRECTION {out} \
   CONFIG.PSU_MIO_22_DRIVE_STRENGTH {4} \
   CONFIG.PSU_MIO_22_INPUT_TYPE {cmos} \
   CONFIG.PSU_MIO_22_POLARITY {Default} \
   CONFIG.PSU_MIO_23_DIRECTION {inout} \
   CONFIG.PSU_MIO_23_POLARITY {Default} \
   CONFIG.PSU_MIO_24_DIRECTION {in} \
   CONFIG.PSU_MIO_24_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_24_POLARITY {Default} \
   CONFIG.PSU_MIO_24_SLEW {fast} \
   CONFIG.PSU_MIO_25_DIRECTION {inout} \
   CONFIG.PSU_MIO_25_POLARITY {Default} \
   CONFIG.PSU_MIO_26_DIRECTION {in} \
   CONFIG.PSU_MIO_26_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_26_POLARITY {Default} \
   CONFIG.PSU_MIO_26_SLEW {fast} \
   CONFIG.PSU_MIO_27_DIRECTION {out} \
   CONFIG.PSU_MIO_27_INPUT_TYPE {cmos} \
   CONFIG.PSU_MIO_27_POLARITY {Default} \
   CONFIG.PSU_MIO_28_DIRECTION {in} \
   CONFIG.PSU_MIO_28_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_28_POLARITY {Default} \
   CONFIG.PSU_MIO_28_SLEW {fast} \
   CONFIG.PSU_MIO_29_DIRECTION {out} \
   CONFIG.PSU_MIO_29_INPUT_TYPE {cmos} \
   CONFIG.PSU_MIO_29_POLARITY {Default} \
   CONFIG.PSU_MIO_2_DIRECTION {in} \
   CONFIG.PSU_MIO_2_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_2_POLARITY {Default} \
   CONFIG.PSU_MIO_2_SLEW {fast} \
   CONFIG.PSU_MIO_30_DIRECTION {in} \
   CONFIG.PSU_MIO_30_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_30_POLARITY {Default} \
   CONFIG.PSU_MIO_30_SLEW {fast} \
   CONFIG.PSU_MIO_31_DIRECTION {inout} \
   CONFIG.PSU_MIO_31_POLARITY {Default} \
   CONFIG.PSU_MIO_32_DIRECTION {out} \
   CONFIG.PSU_MIO_32_INPUT_TYPE {cmos} \
   CONFIG.PSU_MIO_32_POLARITY {Default} \
   CONFIG.PSU_MIO_33_DIRECTION {out} \
   CONFIG.PSU_MIO_33_INPUT_TYPE {cmos} \
   CONFIG.PSU_MIO_33_POLARITY {Default} \
   CONFIG.PSU_MIO_34_DIRECTION {out} \
   CONFIG.PSU_MIO_34_INPUT_TYPE {cmos} \
   CONFIG.PSU_MIO_34_POLARITY {Default} \
   CONFIG.PSU_MIO_35_DIRECTION {inout} \
   CONFIG.PSU_MIO_35_POLARITY {Default} \
   CONFIG.PSU_MIO_36_DIRECTION {inout} \
   CONFIG.PSU_MIO_36_POLARITY {Default} \
   CONFIG.PSU_MIO_37_DIRECTION {inout} \
   CONFIG.PSU_MIO_37_POLARITY {Default} \
   CONFIG.PSU_MIO_38_DIRECTION {inout} \
   CONFIG.PSU_MIO_38_POLARITY {Default} \
   CONFIG.PSU_MIO_39_DIRECTION {inout} \
   CONFIG.PSU_MIO_39_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_39_POLARITY {Default} \
   CONFIG.PSU_MIO_39_SLEW {fast} \
   CONFIG.PSU_MIO_3_DIRECTION {out} \
   CONFIG.PSU_MIO_3_INPUT_TYPE {cmos} \
   CONFIG.PSU_MIO_3_POLARITY {Default} \
   CONFIG.PSU_MIO_40_DIRECTION {inout} \
   CONFIG.PSU_MIO_40_POLARITY {Default} \
   CONFIG.PSU_MIO_41_DIRECTION {inout} \
   CONFIG.PSU_MIO_41_POLARITY {Default} \
   CONFIG.PSU_MIO_42_DIRECTION {inout} \
   CONFIG.PSU_MIO_42_POLARITY {Default} \
   CONFIG.PSU_MIO_43_DIRECTION {inout} \
   CONFIG.PSU_MIO_43_POLARITY {Default} \
   CONFIG.PSU_MIO_44_DIRECTION {inout} \
   CONFIG.PSU_MIO_44_POLARITY {Default} \
   CONFIG.PSU_MIO_45_DIRECTION {inout} \
   CONFIG.PSU_MIO_45_POLARITY {Default} \
   CONFIG.PSU_MIO_46_DIRECTION {inout} \
   CONFIG.PSU_MIO_46_POLARITY {Default} \
   CONFIG.PSU_MIO_47_DIRECTION {inout} \
   CONFIG.PSU_MIO_47_POLARITY {Default} \
   CONFIG.PSU_MIO_48_DIRECTION {inout} \
   CONFIG.PSU_MIO_48_POLARITY {Default} \
   CONFIG.PSU_MIO_49_DIRECTION {inout} \
   CONFIG.PSU_MIO_49_POLARITY {Default} \
   CONFIG.PSU_MIO_4_DIRECTION {inout} \
   CONFIG.PSU_MIO_4_POLARITY {Default} \
   CONFIG.PSU_MIO_50_DIRECTION {inout} \
   CONFIG.PSU_MIO_50_POLARITY {Default} \
   CONFIG.PSU_MIO_51_DIRECTION {out} \
   CONFIG.PSU_MIO_51_INPUT_TYPE {cmos} \
   CONFIG.PSU_MIO_51_POLARITY {Default} \
   CONFIG.PSU_MIO_52_DIRECTION {in} \
   CONFIG.PSU_MIO_52_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_52_POLARITY {Default} \
   CONFIG.PSU_MIO_52_SLEW {fast} \
   CONFIG.PSU_MIO_53_DIRECTION {in} \
   CONFIG.PSU_MIO_53_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_53_POLARITY {Default} \
   CONFIG.PSU_MIO_53_SLEW {fast} \
   CONFIG.PSU_MIO_54_DIRECTION {inout} \
   CONFIG.PSU_MIO_54_POLARITY {Default} \
   CONFIG.PSU_MIO_55_DIRECTION {in} \
   CONFIG.PSU_MIO_55_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_55_POLARITY {Default} \
   CONFIG.PSU_MIO_55_SLEW {fast} \
   CONFIG.PSU_MIO_56_DIRECTION {inout} \
   CONFIG.PSU_MIO_56_POLARITY {Default} \
   CONFIG.PSU_MIO_57_DIRECTION {inout} \
   CONFIG.PSU_MIO_57_POLARITY {Default} \
   CONFIG.PSU_MIO_58_DIRECTION {out} \
   CONFIG.PSU_MIO_58_INPUT_TYPE {cmos} \
   CONFIG.PSU_MIO_58_POLARITY {Default} \
   CONFIG.PSU_MIO_59_DIRECTION {inout} \
   CONFIG.PSU_MIO_59_POLARITY {Default} \
   CONFIG.PSU_MIO_5_DIRECTION {inout} \
   CONFIG.PSU_MIO_5_POLARITY {Default} \
   CONFIG.PSU_MIO_60_DIRECTION {inout} \
   CONFIG.PSU_MIO_60_POLARITY {Default} \
   CONFIG.PSU_MIO_61_DIRECTION {inout} \
   CONFIG.PSU_MIO_61_POLARITY {Default} \
   CONFIG.PSU_MIO_62_DIRECTION {inout} \
   CONFIG.PSU_MIO_62_POLARITY {Default} \
   CONFIG.PSU_MIO_63_DIRECTION {inout} \
   CONFIG.PSU_MIO_63_POLARITY {Default} \
   CONFIG.PSU_MIO_64_DIRECTION {in} \
   CONFIG.PSU_MIO_64_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_64_POLARITY {Default} \
   CONFIG.PSU_MIO_64_SLEW {fast} \
   CONFIG.PSU_MIO_65_DIRECTION {in} \
   CONFIG.PSU_MIO_65_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_65_POLARITY {Default} \
   CONFIG.PSU_MIO_65_SLEW {fast} \
   CONFIG.PSU_MIO_66_DIRECTION {inout} \
   CONFIG.PSU_MIO_66_POLARITY {Default} \
   CONFIG.PSU_MIO_67_DIRECTION {in} \
   CONFIG.PSU_MIO_67_DRIVE_STRENGTH {12} \
   CONFIG.PSU_MIO_67_POLARITY {Default} \
   CONFIG.PSU_MIO_67_SLEW {fast} \
   CONFIG.PSU_MIO_68_DIRECTION {inout} \
   CONFIG.PSU_MIO_68_POLARITY {Default} \
   CONFIG.PSU_MIO_69_DIRECTION {inout} \
   CONFIG.PSU_MIO_69_POLARITY {Default} \
   CONFIG.PSU_MIO_6_DIRECTION {inout} \
   CONFIG.PSU_MIO_6_POLARITY {Default} \
   CONFIG.PSU_MIO_70_DIRECTION {out} \
   CONFIG.PSU_MIO_70_INPUT_TYPE {cmos} \
   CONFIG.PSU_MIO_70_POLARITY {Default} \
   CONFIG.PSU_MIO_71_DIRECTION {inout} \
   CONFIG.PSU_MIO_71_POLARITY {Default} \
   CONFIG.PSU_MIO_72_DIRECTION {inout} \
   CONFIG.PSU_MIO_72_POLARITY {Default} \
   CONFIG.PSU_MIO_73_DIRECTION {inout} \
   CONFIG.PSU_MIO_73_POLARITY {Default} \
   CONFIG.PSU_MIO_74_DIRECTION {inout} \
   CONFIG.PSU_MIO_74_POLARITY {Default} \
   CONFIG.PSU_MIO_75_DIRECTION {inout} \
   CONFIG.PSU_MIO_75_POLARITY {Default} \
   CONFIG.PSU_MIO_76_DIRECTION {inout} \
   CONFIG.PSU_MIO_76_POLARITY {Default} \
   CONFIG.PSU_MIO_77_DIRECTION {inout} \
   CONFIG.PSU_MIO_77_POLARITY {Default} \
   CONFIG.PSU_MIO_7_DIRECTION {inout} \
   CONFIG.PSU_MIO_7_POLARITY {Default} \
   CONFIG.PSU_MIO_8_DIRECTION {inout} \
   CONFIG.PSU_MIO_8_POLARITY {Default} \
   CONFIG.PSU_MIO_9_DIRECTION {inout} \
   CONFIG.PSU_MIO_9_POLARITY {Default} \
   CONFIG.PSU_MIO_TREE_PERIPHERALS {UART 1#UART 1#UART 0#UART 0#I2C 1#I2C 1#SPI 1#GPIO0 MIO#GPIO0 MIO#SPI 1#SPI 1#SPI 1#GPIO0 MIO#SD 0#SD 0#SD 0#SD 0#GPIO0 MIO#GPIO0 MIO#GPIO0 MIO#GPIO0 MIO#SD 0#SD 0#GPIO0 MIO#SD 0#GPIO0 MIO#PMU GPI 0#DPAUX#DPAUX#DPAUX#DPAUX#GPIO1 MIO#PMU GPO 0#PMU GPO 1#PMU GPO 2#GPIO1 MIO#GPIO1 MIO#GPIO1 MIO#SPI 0#GPIO1 MIO#GPIO1 MIO#SPI 0#SPI 0#SPI 0#GPIO1 MIO#GPIO1 MIO#SD 1#SD 1#SD 1#SD 1#SD 1#SD 1#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 0#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#USB 1#GPIO2 MIO#GPIO2 MIO} \
   CONFIG.PSU_MIO_TREE_SIGNALS {txd#rxd#rxd#txd#scl_out#sda_out#sclk_out#gpio0[7]#gpio0[8]#n_ss_out[0]#miso#mosi#gpio0[12]#sdio0_data_out[0]#sdio0_data_out[1]#sdio0_data_out[2]#sdio0_data_out[3]#gpio0[17]#gpio0[18]#gpio0[19]#gpio0[20]#sdio0_cmd_out#sdio0_clk_out#gpio0[23]#sdio0_cd_n#gpio0[25]#gpi[0]#dp_aux_data_out#dp_hot_plug_detect#dp_aux_data_oe#dp_aux_data_in#gpio1[31]#gpo[0]#gpo[1]#gpo[2]#gpio1[35]#gpio1[36]#gpio1[37]#sclk_out#gpio1[39]#gpio1[40]#n_ss_out[0]#miso#mosi#gpio1[44]#gpio1[45]#sdio1_data_out[0]#sdio1_data_out[1]#sdio1_data_out[2]#sdio1_data_out[3]#sdio1_cmd_out#sdio1_clk_out#ulpi_clk_in#ulpi_dir#ulpi_tx_data[2]#ulpi_nxt#ulpi_tx_data[0]#ulpi_tx_data[1]#ulpi_stp#ulpi_tx_data[3]#ulpi_tx_data[4]#ulpi_tx_data[5]#ulpi_tx_data[6]#ulpi_tx_data[7]#ulpi_clk_in#ulpi_dir#ulpi_tx_data[2]#ulpi_nxt#ulpi_tx_data[0]#ulpi_tx_data[1]#ulpi_stp#ulpi_tx_data[3]#ulpi_tx_data[4]#ulpi_tx_data[5]#ulpi_tx_data[6]#ulpi_tx_data[7]#gpio2[76]#gpio2[77]} \
   CONFIG.PSU_SD0_INTERNAL_BUS_WIDTH {4} \
   CONFIG.PSU_SD1_INTERNAL_BUS_WIDTH {4} \
   CONFIG.PSU_USB3__DUAL_CLOCK_ENABLE {1} \
   CONFIG.PSU__ACT_DDR_FREQ_MHZ {533.333313} \
   CONFIG.PSU__CAN1__GRP_CLK__ENABLE {0} \
   CONFIG.PSU__CAN1__PERIPHERAL__ENABLE {0} \
   CONFIG.PSU__CRF_APB__ACPU_CTRL__ACT_FREQMHZ {1200.000000} \
   CONFIG.PSU__CRF_APB__ACPU_CTRL__DIVISOR0 {1} \
   CONFIG.PSU__CRF_APB__ACPU_CTRL__SRCSEL {APLL} \
   CONFIG.PSU__CRF_APB__APLL_CTRL__DIV2 {1} \
   CONFIG.PSU__CRF_APB__APLL_CTRL__FBDIV {72} \
   CONFIG.PSU__CRF_APB__APLL_CTRL__FRACDATA {0} \
   CONFIG.PSU__CRF_APB__APLL_CTRL__SRCSEL {PSS_REF_CLK} \
   CONFIG.PSU__CRF_APB__APLL_FRAC_CFG__ENABLED {0} \
   CONFIG.PSU__CRF_APB__APLL_TO_LPD_CTRL__DIVISOR0 {3} \
   CONFIG.PSU__CRF_APB__DBG_FPD_CTRL__ACT_FREQMHZ {250.000000} \
   CONFIG.PSU__CRF_APB__DBG_FPD_CTRL__DIVISOR0 {2} \
   CONFIG.PSU__CRF_APB__DBG_FPD_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRF_APB__DBG_TRACE_CTRL__DIVISOR0 {2} \
   CONFIG.PSU__CRF_APB__DBG_TRACE_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRF_APB__DBG_TSTMP_CTRL__ACT_FREQMHZ {250.000000} \
   CONFIG.PSU__CRF_APB__DBG_TSTMP_CTRL__DIVISOR0 {2} \
   CONFIG.PSU__CRF_APB__DBG_TSTMP_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRF_APB__DDR_CTRL__ACT_FREQMHZ {266.666656} \
   CONFIG.PSU__CRF_APB__DDR_CTRL__DIVISOR0 {4} \
   CONFIG.PSU__CRF_APB__DDR_CTRL__FREQMHZ {533} \
   CONFIG.PSU__CRF_APB__DDR_CTRL__SRCSEL {DPLL} \
   CONFIG.PSU__CRF_APB__DPDMA_REF_CTRL__ACT_FREQMHZ {600.000000} \
   CONFIG.PSU__CRF_APB__DPDMA_REF_CTRL__DIVISOR0 {2} \
   CONFIG.PSU__CRF_APB__DPDMA_REF_CTRL__SRCSEL {APLL} \
   CONFIG.PSU__CRF_APB__DPLL_CTRL__DIV2 {1} \
   CONFIG.PSU__CRF_APB__DPLL_CTRL__FBDIV {64} \
   CONFIG.PSU__CRF_APB__DPLL_CTRL__FRACDATA {0} \
   CONFIG.PSU__CRF_APB__DPLL_CTRL__SRCSEL {PSS_REF_CLK} \
   CONFIG.PSU__CRF_APB__DPLL_FRAC_CFG__ENABLED {0} \
   CONFIG.PSU__CRF_APB__DPLL_TO_LPD_CTRL__DIVISOR0 {3} \
   CONFIG.PSU__CRF_APB__DP_AUDIO_REF_CTRL__ACT_FREQMHZ {24.576040} \
   CONFIG.PSU__CRF_APB__DP_AUDIO_REF_CTRL__DIVISOR0 {16} \
   CONFIG.PSU__CRF_APB__DP_AUDIO_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRF_APB__DP_AUDIO_REF_CTRL__SRCSEL {RPLL} \
   CONFIG.PSU__CRF_APB__DP_AUDIO__FRAC_ENABLED {1} \
   CONFIG.PSU__CRF_APB__DP_STC_REF_CTRL__ACT_FREQMHZ {26.214443} \
   CONFIG.PSU__CRF_APB__DP_STC_REF_CTRL__DIVISOR0 {15} \
   CONFIG.PSU__CRF_APB__DP_STC_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRF_APB__DP_STC_REF_CTRL__SRCSEL {RPLL} \
   CONFIG.PSU__CRF_APB__DP_VIDEO_REF_CTRL__ACT_FREQMHZ {297.029572} \
   CONFIG.PSU__CRF_APB__DP_VIDEO_REF_CTRL__DIVISOR0 {4} \
   CONFIG.PSU__CRF_APB__DP_VIDEO_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRF_APB__DP_VIDEO_REF_CTRL__SRCSEL {VPLL} \
   CONFIG.PSU__CRF_APB__DP_VIDEO__FRAC_ENABLED {1} \
   CONFIG.PSU__CRF_APB__GDMA_REF_CTRL__ACT_FREQMHZ {600.000000} \
   CONFIG.PSU__CRF_APB__GDMA_REF_CTRL__DIVISOR0 {2} \
   CONFIG.PSU__CRF_APB__GDMA_REF_CTRL__SRCSEL {APLL} \
   CONFIG.PSU__CRF_APB__GPU_REF_CTRL__ACT_FREQMHZ {500.000000} \
   CONFIG.PSU__CRF_APB__GPU_REF_CTRL__DIVISOR0 {1} \
   CONFIG.PSU__CRF_APB__GPU_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRF_APB__PCIE_REF_CTRL__DIVISOR0 {2} \
   CONFIG.PSU__CRF_APB__PCIE_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRF_APB__SATA_REF_CTRL__DIVISOR0 {2} \
   CONFIG.PSU__CRF_APB__SATA_REF_CTRL__FREQMHZ {250} \
   CONFIG.PSU__CRF_APB__SATA_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRF_APB__TOPSW_LSBUS_CTRL__ACT_FREQMHZ {100.000000} \
   CONFIG.PSU__CRF_APB__TOPSW_LSBUS_CTRL__DIVISOR0 {5} \
   CONFIG.PSU__CRF_APB__TOPSW_LSBUS_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRF_APB__TOPSW_MAIN_CTRL__ACT_FREQMHZ {533.333313} \
   CONFIG.PSU__CRF_APB__TOPSW_MAIN_CTRL__DIVISOR0 {2} \
   CONFIG.PSU__CRF_APB__TOPSW_MAIN_CTRL__SRCSEL {DPLL} \
   CONFIG.PSU__CRF_APB__VPLL_CTRL__DIV2 {1} \
   CONFIG.PSU__CRF_APB__VPLL_CTRL__FBDIV {71} \
   CONFIG.PSU__CRF_APB__VPLL_CTRL__FRACDATA {0.2871} \
   CONFIG.PSU__CRF_APB__VPLL_CTRL__FRACFREQ {300} \
   CONFIG.PSU__CRF_APB__VPLL_CTRL__SRCSEL {PSS_REF_CLK} \
   CONFIG.PSU__CRF_APB__VPLL_FRAC_CFG__ENABLED {1} \
   CONFIG.PSU__CRF_APB__VPLL_TO_LPD_CTRL__DIVISOR0 {3} \
   CONFIG.PSU__CRL_APB__ADMA_REF_CTRL__ACT_FREQMHZ {500.000000} \
   CONFIG.PSU__CRL_APB__ADMA_REF_CTRL__DIVISOR0 {3} \
   CONFIG.PSU__CRL_APB__ADMA_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__AFI6_REF_CTRL__DIVISOR0 {3} \
   CONFIG.PSU__CRL_APB__AMS_REF_CTRL__ACT_FREQMHZ {51.724136} \
   CONFIG.PSU__CRL_APB__AMS_REF_CTRL__DIVISOR0 {29} \
   CONFIG.PSU__CRL_APB__AMS_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__AMS_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__CAN0_REF_CTRL__DIVISOR0 {15} \
   CONFIG.PSU__CRL_APB__CAN0_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__CAN0_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__CAN1_REF_CTRL__DIVISOR0 {15} \
   CONFIG.PSU__CRL_APB__CAN1_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__CAN1_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__CPU_R5_CTRL__ACT_FREQMHZ {500.000000} \
   CONFIG.PSU__CRL_APB__CPU_R5_CTRL__DIVISOR0 {3} \
   CONFIG.PSU__CRL_APB__CPU_R5_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__CSU_PLL_CTRL__ACT_FREQMHZ {500} \
   CONFIG.PSU__CRL_APB__CSU_PLL_CTRL__DIVISOR0 {4} \
   CONFIG.PSU__CRL_APB__CSU_PLL_CTRL__FREQMHZ {400} \
   CONFIG.PSU__CRL_APB__CSU_PLL_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__DBG_LPD_CTRL__ACT_FREQMHZ {250.000000} \
   CONFIG.PSU__CRL_APB__DBG_LPD_CTRL__DIVISOR0 {6} \
   CONFIG.PSU__CRL_APB__DBG_LPD_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__DLL_REF_CTRL__ACT_FREQMHZ {1500.000000} \
   CONFIG.PSU__CRL_APB__GEM0_REF_CTRL__DIVISOR0 {12} \
   CONFIG.PSU__CRL_APB__GEM0_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__GEM0_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__GEM1_REF_CTRL__DIVISOR0 {12} \
   CONFIG.PSU__CRL_APB__GEM1_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__GEM1_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__GEM2_REF_CTRL__DIVISOR0 {12} \
   CONFIG.PSU__CRL_APB__GEM2_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__GEM2_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__GEM3_REF_CTRL__DIVISOR0 {12} \
   CONFIG.PSU__CRL_APB__GEM3_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__GEM3_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__GEM_TSU_REF_CTRL__DIVISOR0 {6} \
   CONFIG.PSU__CRL_APB__GEM_TSU_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__GEM_TSU_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__I2C0_REF_CTRL__DIVISOR0 {15} \
   CONFIG.PSU__CRL_APB__I2C0_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__I2C0_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__I2C1_REF_CTRL__ACT_FREQMHZ {100.000000} \
   CONFIG.PSU__CRL_APB__I2C1_REF_CTRL__DIVISOR0 {15} \
   CONFIG.PSU__CRL_APB__I2C1_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__I2C1_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__IOPLL_CTRL__DIV2 {0} \
   CONFIG.PSU__CRL_APB__IOPLL_CTRL__FBDIV {45} \
   CONFIG.PSU__CRL_APB__IOPLL_CTRL__FRACDATA {0} \
   CONFIG.PSU__CRL_APB__IOPLL_CTRL__SRCSEL {PSS_REF_CLK} \
   CONFIG.PSU__CRL_APB__IOPLL_FRAC_CFG__ENABLED {0} \
   CONFIG.PSU__CRL_APB__IOPLL_TO_FPD_CTRL__DIVISOR0 {3} \
   CONFIG.PSU__CRL_APB__IOU_SWITCH_CTRL__ACT_FREQMHZ {250.000000} \
   CONFIG.PSU__CRL_APB__IOU_SWITCH_CTRL__DIVISOR0 {6} \
   CONFIG.PSU__CRL_APB__IOU_SWITCH_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__LPD_LSBUS_CTRL__ACT_FREQMHZ {100.000000} \
   CONFIG.PSU__CRL_APB__LPD_LSBUS_CTRL__DIVISOR0 {15} \
   CONFIG.PSU__CRL_APB__LPD_LSBUS_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__LPD_SWITCH_CTRL__ACT_FREQMHZ {500.000000} \
   CONFIG.PSU__CRL_APB__LPD_SWITCH_CTRL__DIVISOR0 {3} \
   CONFIG.PSU__CRL_APB__LPD_SWITCH_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__NAND_REF_CTRL__DIVISOR0 {15} \
   CONFIG.PSU__CRL_APB__NAND_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__NAND_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__PCAP_CTRL__ACT_FREQMHZ {187.500000} \
   CONFIG.PSU__CRL_APB__PCAP_CTRL__DIVISOR0 {8} \
   CONFIG.PSU__CRL_APB__PCAP_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__PL0_REF_CTRL__ACT_FREQMHZ {100.000000} \
   CONFIG.PSU__CRL_APB__PL0_REF_CTRL__DIVISOR0 {15} \
   CONFIG.PSU__CRL_APB__PL0_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__PL0_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__PL1_REF_CTRL__ACT_FREQMHZ {24.999975} \
   CONFIG.PSU__CRL_APB__PL1_REF_CTRL__DIVISOR0 {15} \
   CONFIG.PSU__CRL_APB__PL1_REF_CTRL__DIVISOR1 {4} \
   CONFIG.PSU__CRL_APB__PL1_REF_CTRL__FREQMHZ {100} \
   CONFIG.PSU__CRL_APB__PL1_REF_CTRL__SRCSEL {RPLL} \
   CONFIG.PSU__CRL_APB__PL2_REF_CTRL__ACT_FREQMHZ {299.999700} \
   CONFIG.PSU__CRL_APB__PL2_REF_CTRL__DIVISOR0 {5} \
   CONFIG.PSU__CRL_APB__PL2_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__PL2_REF_CTRL__FREQMHZ {100} \
   CONFIG.PSU__CRL_APB__PL2_REF_CTRL__SRCSEL {RPLL} \
   CONFIG.PSU__CRL_APB__PL3_REF_CTRL__ACT_FREQMHZ {374.999625} \
   CONFIG.PSU__CRL_APB__PL3_REF_CTRL__DIVISOR0 {4} \
   CONFIG.PSU__CRL_APB__PL3_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__PL3_REF_CTRL__FREQMHZ {100} \
   CONFIG.PSU__CRL_APB__PL3_REF_CTRL__SRCSEL {RPLL} \
   CONFIG.PSU__CRL_APB__QSPI_REF_CTRL__DIVISOR0 {12} \
   CONFIG.PSU__CRL_APB__QSPI_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__QSPI_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__RPLL_CTRL__DIV2 {1} \
   CONFIG.PSU__CRL_APB__RPLL_CTRL__FBDIV {70} \
   CONFIG.PSU__CRL_APB__RPLL_CTRL__FRACDATA {0.779} \
   CONFIG.PSU__CRL_APB__RPLL_CTRL__FRACFREQ {25} \
   CONFIG.PSU__CRL_APB__RPLL_CTRL__SRCSEL {PSS_REF_CLK} \
   CONFIG.PSU__CRL_APB__RPLL_FRAC_CFG__ENABLED {1} \
   CONFIG.PSU__CRL_APB__RPLL_TO_FPD_CTRL__DIVISOR0 {3} \
   CONFIG.PSU__CRL_APB__SDIO0_REF_CTRL__ACT_FREQMHZ {187.500000} \
   CONFIG.PSU__CRL_APB__SDIO0_REF_CTRL__DIVISOR0 {8} \
   CONFIG.PSU__CRL_APB__SDIO0_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__SDIO0_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__SDIO1_REF_CTRL__ACT_FREQMHZ {187.500000} \
   CONFIG.PSU__CRL_APB__SDIO1_REF_CTRL__DIVISOR0 {8} \
   CONFIG.PSU__CRL_APB__SDIO1_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__SDIO1_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__SPI0_REF_CTRL__ACT_FREQMHZ {187.500000} \
   CONFIG.PSU__CRL_APB__SPI0_REF_CTRL__DIVISOR0 {8} \
   CONFIG.PSU__CRL_APB__SPI0_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__SPI0_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__SPI1_REF_CTRL__ACT_FREQMHZ {187.500000} \
   CONFIG.PSU__CRL_APB__SPI1_REF_CTRL__DIVISOR0 {8} \
   CONFIG.PSU__CRL_APB__SPI1_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__SPI1_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__TIMESTAMP_REF_CTRL__ACT_FREQMHZ {100.000000} \
   CONFIG.PSU__CRL_APB__TIMESTAMP_REF_CTRL__DIVISOR0 {15} \
   CONFIG.PSU__CRL_APB__TIMESTAMP_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__UART0_REF_CTRL__ACT_FREQMHZ {100.000000} \
   CONFIG.PSU__CRL_APB__UART0_REF_CTRL__DIVISOR0 {15} \
   CONFIG.PSU__CRL_APB__UART0_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__UART0_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__UART1_REF_CTRL__ACT_FREQMHZ {100.000000} \
   CONFIG.PSU__CRL_APB__UART1_REF_CTRL__DIVISOR0 {15} \
   CONFIG.PSU__CRL_APB__UART1_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__UART1_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__USB0_BUS_REF_CTRL__ACT_FREQMHZ {250.000000} \
   CONFIG.PSU__CRL_APB__USB0_BUS_REF_CTRL__DIVISOR0 {6} \
   CONFIG.PSU__CRL_APB__USB0_BUS_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__USB0_BUS_REF_CTRL__FREQMHZ {250} \
   CONFIG.PSU__CRL_APB__USB0_BUS_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__USB1_BUS_REF_CTRL__ACT_FREQMHZ {250.000000} \
   CONFIG.PSU__CRL_APB__USB1_BUS_REF_CTRL__DIVISOR0 {6} \
   CONFIG.PSU__CRL_APB__USB1_BUS_REF_CTRL__DIVISOR1 {1} \
   CONFIG.PSU__CRL_APB__USB1_BUS_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__USB3_DUAL_REF_CTRL__ACT_FREQMHZ {20.000000} \
   CONFIG.PSU__CRL_APB__USB3_DUAL_REF_CTRL__DIVISOR0 {5} \
   CONFIG.PSU__CRL_APB__USB3_DUAL_REF_CTRL__DIVISOR1 {15} \
   CONFIG.PSU__CRL_APB__USB3_DUAL_REF_CTRL__FREQMHZ {20} \
   CONFIG.PSU__CRL_APB__USB3_DUAL_REF_CTRL__SRCSEL {IOPLL} \
   CONFIG.PSU__CRL_APB__USB3__ENABLE {1} \
   CONFIG.PSU__CSUPMU__PERIPHERAL__VALID {1} \
   CONFIG.PSU__DDRC__ADDR_MIRROR {1} \
   CONFIG.PSU__DDRC__AL {0} \
   CONFIG.PSU__DDRC__BANK_ADDR_COUNT {3} \
   CONFIG.PSU__DDRC__BG_ADDR_COUNT {NA} \
   CONFIG.PSU__DDRC__BRC_MAPPING {ROW_BANK_COL} \
   CONFIG.PSU__DDRC__BUS_WIDTH {32 Bit} \
   CONFIG.PSU__DDRC__CL {NA} \
   CONFIG.PSU__DDRC__CLOCK_STOP_EN {0} \
   CONFIG.PSU__DDRC__COL_ADDR_COUNT {10} \
   CONFIG.PSU__DDRC__COMPONENTS {Components} \
   CONFIG.PSU__DDRC__CWL {NA} \
   CONFIG.PSU__DDRC__DDR3L_T_REF_RANGE {NA} \
   CONFIG.PSU__DDRC__DDR3_T_REF_RANGE {NA} \
   CONFIG.PSU__DDRC__DDR4_ADDR_MAPPING {NA} \
   CONFIG.PSU__DDRC__DDR4_CAL_MODE_ENABLE {NA} \
   CONFIG.PSU__DDRC__DDR4_CRC_CONTROL {NA} \
   CONFIG.PSU__DDRC__DDR4_MAXPWR_SAVING_EN {NA} \
   CONFIG.PSU__DDRC__DDR4_T_REF_MODE {NA} \
   CONFIG.PSU__DDRC__DDR4_T_REF_RANGE {NA} \
   CONFIG.PSU__DDRC__DEEP_PWR_DOWN_EN {0} \
   CONFIG.PSU__DDRC__DEVICE_CAPACITY {16384 MBits} \
   CONFIG.PSU__DDRC__DIMM_ADDR_MIRROR {0} \
   CONFIG.PSU__DDRC__DM_DBI {DM_NO_DBI} \
   CONFIG.PSU__DDRC__DQMAP_0_3 {0} \
   CONFIG.PSU__DDRC__DQMAP_12_15 {0} \
   CONFIG.PSU__DDRC__DQMAP_16_19 {0} \
   CONFIG.PSU__DDRC__DQMAP_20_23 {0} \
   CONFIG.PSU__DDRC__DQMAP_24_27 {0} \
   CONFIG.PSU__DDRC__DQMAP_28_31 {0} \
   CONFIG.PSU__DDRC__DQMAP_32_35 {0} \
   CONFIG.PSU__DDRC__DQMAP_36_39 {0} \
   CONFIG.PSU__DDRC__DQMAP_40_43 {0} \
   CONFIG.PSU__DDRC__DQMAP_44_47 {0} \
   CONFIG.PSU__DDRC__DQMAP_48_51 {0} \
   CONFIG.PSU__DDRC__DQMAP_4_7 {0} \
   CONFIG.PSU__DDRC__DQMAP_52_55 {0} \
   CONFIG.PSU__DDRC__DQMAP_56_59 {0} \
   CONFIG.PSU__DDRC__DQMAP_60_63 {0} \
   CONFIG.PSU__DDRC__DQMAP_64_67 {0} \
   CONFIG.PSU__DDRC__DQMAP_68_71 {0} \
   CONFIG.PSU__DDRC__DQMAP_8_11 {0} \
   CONFIG.PSU__DDRC__DRAM_WIDTH {32 Bits} \
   CONFIG.PSU__DDRC__ECC {Disabled} \
   CONFIG.PSU__DDRC__ENABLE_2T_TIMING {0} \
   CONFIG.PSU__DDRC__ENABLE_DP_SWITCH {1} \
   CONFIG.PSU__DDRC__ENABLE_LP4_HAS_ECC_COMP {0} \
   CONFIG.PSU__DDRC__ENABLE_LP4_SLOWBOOT {0} \
   CONFIG.PSU__DDRC__FGRM {NA} \
   CONFIG.PSU__DDRC__LPDDR3_T_REF_RANGE {NA} \
   CONFIG.PSU__DDRC__LPDDR4_T_REF_RANGE {High (95 Max)} \
   CONFIG.PSU__DDRC__LP_ASR {NA} \
   CONFIG.PSU__DDRC__MEMORY_TYPE {LPDDR 4} \
   CONFIG.PSU__DDRC__PARITY_ENABLE {NA} \
   CONFIG.PSU__DDRC__PER_BANK_REFRESH {0} \
   CONFIG.PSU__DDRC__PHY_DBI_MODE {0} \
   CONFIG.PSU__DDRC__RANK_ADDR_COUNT {0} \
   CONFIG.PSU__DDRC__ROW_ADDR_COUNT {16} \
   CONFIG.PSU__DDRC__SB_TARGET {NA} \
   CONFIG.PSU__DDRC__SELF_REF_ABORT {NA} \
   CONFIG.PSU__DDRC__SPEED_BIN {LPDDR4_1066} \
   CONFIG.PSU__DDRC__STATIC_RD_MODE {0} \
   CONFIG.PSU__DDRC__TRAIN_DATA_EYE {1} \
   CONFIG.PSU__DDRC__TRAIN_READ_GATE {1} \
   CONFIG.PSU__DDRC__TRAIN_WRITE_LEVEL {1} \
   CONFIG.PSU__DDRC__T_FAW {40.0} \
   CONFIG.PSU__DDRC__T_RAS_MIN {42} \
   CONFIG.PSU__DDRC__T_RC {63} \
   CONFIG.PSU__DDRC__T_RCD {10} \
   CONFIG.PSU__DDRC__T_RP {12} \
   CONFIG.PSU__DDRC__VENDOR_PART {OTHERS} \
   CONFIG.PSU__DDRC__VREF {0} \
   CONFIG.PSU__DDR_HIGH_ADDRESS_GUI_ENABLE {0} \
   CONFIG.PSU__DDR_QOS_ENABLE {1} \
...

This file has been truncated, please download it to see its full contents.

nn-training-accel git repository

Git repository for this project

Credits

Bruno JJE

Bruno JJE

3 projects • 1 follower
FPGA engineer

Comments