diff --git a/AE.ipynb b/AE.ipynb index 1431fe3..79eb907 100644 --- a/AE.ipynb +++ b/AE.ipynb @@ -15,7 +15,10 @@ "from matplotlib import pyplot as plt\n", "from tensorflow.keras.layers import Dense\n", "from tensorflow.python.keras.regularizers import l2\n", - "import os" + "import os\n", + "\n", + "from tensorflow_model_optimization.python.core.sparsity.keras import prune, pruning_callbacks, pruning_schedule\n", + "from tensorflow_model_optimization.sparsity.keras import strip_pruning, prune_low_magnitude\n" ] }, { @@ -34,7 +37,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -94,7 +97,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": { "deletable": false, "editable": false, @@ -141,12 +144,13 @@ " def build_encoder(self):\n", " \"\"\"Build your encoder architecture and store the output in self.encoder. \n", " The final encoding dimension is 2.\"\"\"\n", + " #pruning_params = {\"pruning_schedule\" : pruning_schedule.ConstantSparsity(0.75, begin_step=2000, frequency=100)}\n", + " #self.encoder = prune_low_magnitude(Dense(32, activation='relu'), **pruning_params)(self.input)\n", + "\n", " self.encoder = Dense(32, activation='relu')(self.input)\n", " self.encoder = Dense(16, activation='relu')(self.encoder) \n", - " \n", - "\n", - " self.encoder = Dense(self.latent_dim, activation='relu', name = 'encoder_output')(self.encoder) \n", - " \n", + " self.encoder = Dense(self.latent_dim, activation='relu', name = 'encoder_output')(self.encoder)\n", + " \n", " #building a model for the encoder in order to be able to predict and plot the latent dimension\n", " self.encoder_model = Model(self.input, self.encoder, name='encoder')\n", "\n", @@ -198,12 +202,22 @@ " batch_size=batch_size, epochs=epochs,\n", " shuffle=True,\n", " )\n", - " else: \n", + " else: \n", + " \"\"\"callbacks = callbacks.all_callbacks(stop_patience = 1000,\n", + " lr_factor = 0.5,\n", + " lr_patience = 10,\n", + " lr_epsilon = 0.000001,\n", + " lr_cooldown = 2,\n", + " lr_minimum = 0.0000001,\n", + " outputDir = 'model_2')\n", + " callbacks.callbacks.append(pruning_callbacks.UpdatePruningStep())\"\"\" \n", " self.history = self.autoencoder.fit(self.x_train, self.x_train,\n", " validation_data=(self.x_test, self.x_test),\n", " batch_size=batch_size, epochs=epochs,\n", - " shuffle=True\n", + " shuffle=True#, callbacks=callbacks\n", " )\n", + " #self.autoencoder = strip_pruning(self.autoencoder)\n", + " #self.autoencoder.save('model/AE_model/KERAS_check_best_model.h5')\n", "\n", " self.history = self.history.history\n", "\n", @@ -291,7 +305,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -304,15 +318,15 @@ "=================================================================\n", "encoder_input (InputLayer) [(None, 100)] 0 \n", "_________________________________________________________________\n", - "dense_12 (Dense) (None, 32) 3232 \n", + "dense_8 (Dense) (None, 32) 3232 \n", "_________________________________________________________________\n", - "dense_13 (Dense) (None, 16) 528 \n", + "dense_9 (Dense) (None, 16) 528 \n", "_________________________________________________________________\n", "encoder_output (Dense) (None, 2) 34 \n", "_________________________________________________________________\n", - "dense_14 (Dense) (None, 16) 48 \n", + "dense_10 (Dense) (None, 16) 48 \n", "_________________________________________________________________\n", - "dense_15 (Dense) (None, 32) 544 \n", + "dense_11 (Dense) (None, 32) 544 \n", "_________________________________________________________________\n", "ecoder_output (Dense) (None, 100) 3300 \n", "=================================================================\n", @@ -321,70 +335,70 @@ "Non-trainable params: 0\n", "_________________________________________________________________\n", "Epoch 1/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1159 - val_loss: 0.0918\n", + "235/235 [==============================] - 1s 2ms/step - loss: 0.1147 - val_loss: 0.0923\n", "Epoch 2/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0870 - val_loss: 0.0831\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0884 - val_loss: 0.0850\n", "Epoch 3/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0815 - val_loss: 0.0790\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0828 - val_loss: 0.0803\n", "Epoch 4/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0781 - val_loss: 0.0764\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0790 - val_loss: 0.0770\n", "Epoch 5/30\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0758 - val_loss: 0.0746\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0761 - val_loss: 0.0743\n", "Epoch 6/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0742 - val_loss: 0.0733\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0742 - val_loss: 0.0730\n", "Epoch 7/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0731 - val_loss: 0.0724\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0729 - val_loss: 0.0717\n", "Epoch 8/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0722 - val_loss: 0.0716\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0718 - val_loss: 0.0708\n", "Epoch 9/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0715 - val_loss: 0.0712\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0710 - val_loss: 0.0701\n", "Epoch 10/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0711 - val_loss: 0.0707\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0703 - val_loss: 0.0696\n", "Epoch 11/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0707 - val_loss: 0.0704\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0697 - val_loss: 0.0690\n", "Epoch 12/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0703 - val_loss: 0.0701\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0691 - val_loss: 0.0685\n", "Epoch 13/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0700 - val_loss: 0.0698\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0686 - val_loss: 0.0681\n", "Epoch 14/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0697 - val_loss: 0.0695\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0682 - val_loss: 0.0677\n", "Epoch 15/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0694 - val_loss: 0.0693\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0679 - val_loss: 0.0674\n", "Epoch 16/30\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0691 - val_loss: 0.0691\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0675 - val_loss: 0.0671\n", "Epoch 17/30\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0689 - val_loss: 0.0688\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0671 - val_loss: 0.0668\n", "Epoch 18/30\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0686 - val_loss: 0.0686\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0669 - val_loss: 0.0665\n", "Epoch 19/30\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0684 - val_loss: 0.0685\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0666 - val_loss: 0.0663\n", "Epoch 20/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0682 - val_loss: 0.0683\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0664 - val_loss: 0.0661\n", "Epoch 21/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0681 - val_loss: 0.0682\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0662 - val_loss: 0.0660\n", "Epoch 22/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0679 - val_loss: 0.0679\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0660 - val_loss: 0.0658\n", "Epoch 23/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0678 - val_loss: 0.0679\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0658 - val_loss: 0.0655\n", "Epoch 24/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0676 - val_loss: 0.0678\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0656 - val_loss: 0.0654\n", "Epoch 25/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0675 - val_loss: 0.0677\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0655 - val_loss: 0.0654\n", "Epoch 26/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0674 - val_loss: 0.0677\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0653 - val_loss: 0.0652\n", "Epoch 27/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0673 - val_loss: 0.0675\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0652 - val_loss: 0.0650\n", "Epoch 28/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0672 - val_loss: 0.0675\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0651 - val_loss: 0.0649\n", "Epoch 29/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0670 - val_loss: 0.0674\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.0650 - val_loss: 0.0649\n", "Epoch 30/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0669 - val_loss: 0.0673\n" + "235/235 [==============================] - 0s 1ms/step - loss: 0.0648 - val_loss: 0.0650\n" ] }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiQAAAJOCAYAAACHnBxMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8rg+JYAAAACXBIWXMAAAsTAAALEwEAmpwYAAEAAElEQVR4nOz9d3gc93mvjd8zu+gdIECwgGDvpEiREtUpWZZsx4pt2YosW/Yr59hWnBOf2M57zuskdlwS/+KSOCdKLp84clwU95LERS5HsrqpQlEUSbFJ7ARYQBC9Y7Ezvz+eGWyb2Z0FFv25ee1FYKd9Z2ax38881bBt20ZRFEVRFGUKMad6AIqiKIqiKCpIFEVRFEWZclSQKIqiKIoy5aggURRFURRlylFBoiiKoijKlKOCRFEURVGUKUcFiaIoCTz55JMsXrx40o/7pje9iYceesh3+fve9z4++clPTuKIgmEYBsePH5+QfX/3u9/l9ttvH/19165drFq1itLSUn76059mvGaKMpNQQTKLWbp0Kb/97W+z3u7mm2/m3/7t33I2jon8wp4sent7KS0t5U1velNW203V5D4T+fWvf819990HwLe+9S1uuOGGSTnu6dOnMQyDkZGRSTleNtx777088sgjo79/6lOf4sMf/jC9vb287W1vS7hmijLTUUGiKAH4j//4DwoKCnj00Ue5ePHiVA9n2jIdJ/XZxJkzZ9iwYcO496P3SZmOqCCZg3R0dHDHHXdQW1tLVVUVd9xxB83NzQB84hOf4JlnnuHDH/4wpaWlfPjDHwbg6NGj3HbbbVRXV7NmzRp+9KMfje7vfe97H3/yJ3/Cm9/8ZsrKytixYwcnTpwA4KabbgLgiiuuoLS0lB/+8Icp4zl+/Dg7d+6koqKCefPm8c53vnN0mWEY/NM//RPLly9n3rx5/K//9b+wLAuAEydO8LrXvY6amhrmzZvHvffeS2dn5+i2TU1NvP3tb6e2tpaamprRcwH4xje+wbp166iqquINb3gDZ86cSXvNHnroIT70oQ+xefNmvvOd7yQsS7YAua6Fvr4+3vSmN3H+/HlKS0spLS3l/PnzDA0N8dGPfpSFCxeycOFCPvrRjzI0NDS6/cMPP8yWLVuorKzkuuuu48CBA6PLli5dyt///d+zefNmKioqeOc738ng4ODo8p/97Gds2bKF8vJyVqxYwW9+8xsAzp8/z1ve8haqq6tZuXIlX/va10a3GRgY4H3vex9VVVWsX7+eF198MeH8zp8/zzve8Q5qa2tZtmwZ//RP/zS67DOf+Qx33XUX73nPeygvL+db3/pWwranTp2isrJy9J598IMfpK6ubnT5e9/7Xv7xH/8RiFnmjhw5woc+9CGee+45SktLqaysHF2/o6PD83MG8Oyzz3LVVVdRUVHBVVddxbPPPptw3eKthZ/5zGd4z3veA8Q+o5WVlZSWlvLcc8+RTDQa5W//9m9ZsWIFZWVlbNu2jaamppT1fvnLX7J161bKy8tpaGjgM5/5zOiywcFB3vOe91BTU0NlZSVXXXUVLS0tgFiEli9fTllZGcuWLeO73/3u6PuupWjFihWcPHmS3//936e0tJShoaEUa2a6z7VhGHzlK19h1apVrFq1KmXsijLl2MqspbGx0X700UdT3r98+bL9k5/8xO7r67O7u7vtu+66y37rW986unznzp321772tdHfe3t77cWLF9vf+MY37EgkYu/du9euqamxDx06ZNu2bd933312dXW1/cILL9iRSMR+97vfbb/zne8c3R6wjx075jvOe+65x/7c5z5nR6NRe2BgwH7mmWcStr355pvttrY2+8yZM/aqVatGx3bs2DH7kUcesQcHB+1Lly7ZN954o/2Rj3zEtm3bHhkZsTdv3mx/9KMftXt7exP2+9Of/tResWKFffjwYTsSidh/8zd/Y1977bW+4zt9+rRtGIZ96NAh++///u/tTZs2JSxPPr/77rvP/sQnPmHbtm0/8cQT9qJFixLW/6u/+it7x44ddktLi33p0iX72muvtT/5yU/atm3be/futWtra+3nn3/eHhkZsb/1rW/ZjY2N9uDgoG3bck+vuuoq+9y5c3ZbW5u9du1a+1/+5V9s27btF154wS4vL7cfeeQROxqN2s3NzfaRI0ds27btG2+80f7jP/5je2BgwH755ZftefPm2Y899pht27b98Y9/3L7hhhvstrY2++zZs/aGDRtGxxyNRu0rr7zS/uxnP2sPDQ3ZJ06csJctW2b/5je/sW3btj/96U/b4XDY/q//+i87Go3a/f39KdevoaHB3rNnj23btr169Wp72bJl9uHDh0eX7d2717btxM/dN7/5Tfv6669P2E+6z1lbW5tdWVlp//u//7sdiUTs733ve3ZlZaV9+fLl0esW/7fw6U9/2r733ntt27btU6dO2YAdiUR8PgG2/aUvfcneuHGjffToUduyLHvfvn2j+46//0888YR94MABOxqN2vv377fr6urs//qv/7Jt27a/+tWv2nfccYfd19dnj4yM2Hv27LG7urrs3t5eu6yszD569Kht27Z9/vx5++DBg57XIfk84q9Zps81YL/+9a+329raPO+Tokw1aiGZg9TU1PCOd7yD4uJiysrK+MQnPsFTTz3lu/7DDz/M0qVL+cM//EPC4TBbt27lHe94Bz/+8Y9H17nzzju5+uqrCYfD3Hvvvezbty/wePLy8jhz5gznz5+nsLAwJXbg4x//ONXV1SxZsoSPfvSjfP/73wdg5cqV3HbbbRQUFFBbW8uf/dmfjZ7H7t27OX/+PH/3d39HSUlJwn6/+tWv8hd/8ResW7eOcDjMX/7lX7Jv3z5fK8m3v/1tNm/ezPr167nnnns4dOgQL7/8cuDzS+a73/0un/rUp6irq6O2tpZPf/rTfPvb3wbgwQcf5I/+6I/YsWMHoVCI++67j4KCAp5//vnR7f/0T/+UhQsXUl1dze///u+PXuuvf/3r/Lf/9t+47bbbME2TRYsWsXbtWpqamti1axdf/OIXKSwsZMuWLXzgAx/g3//93wH40Y9+xCc+8Qmqq6tpaGjgT//0T0eP9eKLL9La2sqnPvUp8vPzWb58OR/84Af5wQ9+MLrOtddey9ve9jZM06SoqCjlfHfu3MlTTz016uq66667eOqppzh16hTd3d1cccUVga+d3+fsl7/8JatWreK9730v4XCYd73rXaxdu5Zf/OIXgfedjn/7t3/jc5/7HGvWrMEwDK644gpqampS1rv55pvZtGkTpmmyefNm3vWud41+JvPy8mhra+P48eOEQiG2bdtGeXk5AKZpcvDgQQYGBliwYMGY3DJBPtd/8Rd/QXV1ted9UpSpRgXJHKS/v58/+qM/orGxkfLycm666SY6OzuJRqOe6585c4YXXniBysrK0dd3v/vdhFiK+vr60Z+Li4vp7e0NPJ4vfelL2LbN1VdfzYYNG/jGN76RsLyhoWH058bGRs6fPw9AS0sL99xzD4sWLaK8vJz3vOc9XL58GRB3TWNjI+Fw2PN8PvKRj4yeS3V1NbZtc+7cOc/x/fu//zv33nsvAIsWLWLnzp3jymw4f/48jY2Nnud05swZvvzlLydc66amptHl4H+tm5qaWLFihefxqqurKSsrSzime77nz59PucYurlCMH8/f/u3fjroaIPH+eLFz506efPJJnn76aW666SZuvvlmnnrqKZ566iluvPFGTDP415DfuSdf0+RzHC9+1zaZF154gVtuuYXa2loqKir46le/OvqZfO9738sb3vAG7rnnHhYuXMj/9//9f0QiEUpKSvjhD3/IV7/6VRYsWMCb3/xmjh49mvUYg3yuM90rRZlKVJDMQb785S/z6quv8sILL9Dd3c3TTz8NgO00fjYMI2H9hoYGdu7cSWdn5+irt7eXf/mXf8nJeOrr6/na177G+fPn+dd//Vf++3//7wkxGfG++rNnz7Jw4UIA/vIv/xLDMHjllVfo7u7mO9/5zug5NDQ0cPbsWc/gvYaGBv71X/814XwGBga47rrrUtZ99tlnOXbsGJ///Oepr6+nvr6eF154ge9973uj+y4uLqa/v390m3ihlnwtARYuXJjw1Bp/Tg0NDXziE59IGFt/fz/vete7Ml7HhoaGhJiK+OO1t7fT09OTcMxFixYBsGDBgpRrHL/PZcuWJYynp6eHX/3qV2nPMZ6dO3fyzDPP8OSTT7Jz505uuOEGdu3axVNPPcXOnTs9t8m0T69zTLZwxZ9jSUlJVvcoGb9rm8y73/1u3vKWt9DU1ERXVxcf+tCHRj+TeXl5fPrTn+bw4cM8++yzPPzww6NWqje84Q08+uijXLhwgbVr1/LBD34w80l7jDHT5zrb66ook4kKkllOJBJhcHBw9DUyMkJPTw9FRUVUVlbS3t7OZz/72YRt5s+fz8mTJ0d/v+OOO3jttdf49re/TSQSIRKJ8OKLL3LkyJFAY0jeXzI//vGPR4Nqq6qqMAwj4an57/7u7+jo6KCpqYkHHnhgNOi1p6eH0tJSKioqOHfuHH/3d383us3VV1/NggUL+PM//3P6+voYHBxk165dAHzoQx/i85//PIcOHQKgq6srwf0Uz0MPPcRtt93G4cOH2bdvH/v27Rs1rf/6178GYMuWLXzve98jGo3ym9/8JsH9NX/+fNra2ujq6hp9713vehef+9znaG1t5fLly/z1X//1aIDlBz/4Qb761a/ywgsvYNs2fX19/PKXv0wQE368//3v55vf/CaPPfYYlmVx7tw5jh49SkNDA9dddx1/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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiQAAAJOCAYAAACHnBxMAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8rg+JYAAAACXBIWXMAAAsTAAALEwEAmpwYAAEAAElEQVR4nOy9d5hcd3n3/TlnZnvvu1qttGpW77LlLttgY8DBGPyCTXlMYlAgIQFyPXmdBEJJcoWS8gR484SYADEtxiGEYgOxccVVlmVZvbeVtve+OzPnvH/cc3baOVO2aHel+3Nde1k7c+ac38ys5/edu3xvw7ZtG0VRFEVRlFnEnO0FKIqiKIqiqCBRFEVRFGXWUUGiKIqiKMqso4JEURRFUZRZRwWJoiiKoiizjgoSRVEURVFmHRUkiqLE8Mwzz7Bw4cKLft23vvWtPPTQQ573f+hDH+Izn/nMRVxRehiGwYkTJ2bk3D/4wQ+47bbbJn5/4YUXWLFiBYWFhfz0pz9N+ZopynxCBcklTGNjI7/5zW8yftxNN93Ev/3bv03bOmbyA/tiMTg4SGFhIW9961szetxsbe7zkV/96lfcd999APz7v/87119//UW57pkzZzAMg2AweFGulwnvf//7efzxxyd+/+xnP8vHP/5xBgcHeec73xnzminKfEcFiaKkwX/913+Rk5PDE088QWtr62wvZ84yFzf1S4mzZ8+ydu3aKZ9H3ydlLqKC5DKkp6eHO+64g6qqKsrKyrjjjjs4f/48AJ/+9Kf57W9/y8c//nEKCwv5+Mc/DsCRI0e49dZbKS8vZ+XKlTzyyCMT5/vQhz7EH/7hH/L2t7+doqIitm/fzsmTJwG48cYbAdi4cSOFhYX86Ec/SljPiRMn2LFjByUlJVRWVvLe97534j7DMPja177G0qVLqays5E//9E+xLAuAkydPcsstt1BRUUFlZSXvf//76e3tnXhsU1MT73rXu6iqqqKiomLiuQB8+9vfZvXq1ZSVlfGWt7yFs2fPJn3NHnroIT760Y+yYcMGvv/978fcFx8BclILQ0NDvPWtb6W5uZnCwkIKCwtpbm5mbGyMT37ykyxYsIAFCxbwyU9+krGxsYnHP/roo2zatInS0lKuvfZa9u3bN3FfY2Mjf//3f8+GDRsoKSnhve99L6OjoxP3/+xnP2PTpk0UFxezbNkyfv3rXwPQ3NzMO97xDsrLy1m+fDnf/OY3Jx4zMjLChz70IcrKylizZg2vvvpqzPNrbm7m3e9+N1VVVSxZsoSvfe1rE/d9/vOf5+677+YDH/gAxcXF/Pu//3vMY0+fPk1paenEe/aRj3yE6urqifs/+MEP8k//9E9AJDJ3+PBhPvrRj/LSSy9RWFhIaWnpxPE9PT2uf2cAL774IldeeSUlJSVceeWVvPjiizGvW3S08POf/zwf+MAHgMjfaGlpKYWFhbz00kvEEwqF+Nu//VuWLVtGUVERW7dupampKeG4xx57jM2bN1NcXExDQwOf//znJ+4bHR3lAx/4ABUVFZSWlnLllVfS1tYGSERo6dKlFBUVsWTJEn7wgx9M3O5EipYtW8apU6f4nd/5HQoLCxkbG0uIZib7uzYMg3/+539mxYoVrFixImHtijLr2Moly+LFi+0nnngi4fbOzk77xz/+sT00NGT39/fbd999t33nnXdO3L9jxw77m9/85sTvg4OD9sKFC+1vf/vbdiAQsPfs2WNXVFTYBw8etG3btu+77z67vLzcfuWVV+xAIGC/733vs9/73vdOPB6wjx8/7rnOe+65x/6bv/kbOxQK2SMjI/Zvf/vbmMfedNNNdldXl3327Fl7xYoVE2s7fvy4/fjjj9ujo6N2e3u7fcMNN9if+MQnbNu27WAwaG/YsMH+5Cc/aQ8ODsac96c//am9bNky+9ChQ3YgELD/+q//2r7mmms813fmzBnbMAz74MGD9t///d/b69evj7k//vndd9999qc//Wnbtm376aeftuvr62OO/8u//Et7+/btdltbm93e3m5fc8019mc+8xnbtm17z549dlVVlf3yyy/bwWDQ/vd//3d78eLF9ujoqG3b8p5eeeWV9oULF+yuri571apV9r/8y7/Ytm3br7zyil1cXGw//vjjdigUss+fP28fPnzYtm3bvuGGG+yPfexj9sjIiP3666/blZWV9pNPPmnbtm0/8MAD9vXXX293dXXZ586ds9euXTux5lAoZG/ZssX+whe+YI+NjdknT560lyxZYv/617+2bdu2P/e5z9l+v9/+7//+bzsUCtnDw8MJr19DQ4O9e/du27Zt+4orrrCXLFliHzp0aOK+PXv22LYd+3f3ne98x77uuutizpPs76yrq8suLS21v/vd79qBQMD+4Q9/aJeWltqd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", "text/plain": [ "
" ] @@ -394,7 +408,7 @@ }, { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -406,7 +420,7 @@ }, { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -437,106 +451,106 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Model: \"functional_3\"\n", + "Model: \"functional_1\"\n", "__________________________________________________________________________________________________\n", "Layer (type) Output Shape Param # Connected to \n", "==================================================================================================\n", "encoder_input (InputLayer) [(None, 100)] 0 \n", "__________________________________________________________________________________________________\n", - "dense_16 (Dense) (None, 32) 3232 encoder_input[0][0] \n", + "dense_12 (Dense) (None, 32) 3232 encoder_input[0][0] \n", "__________________________________________________________________________________________________\n", - "dense_17 (Dense) (None, 16) 528 dense_16[0][0] \n", + "dense_13 (Dense) (None, 16) 528 dense_12[0][0] \n", "__________________________________________________________________________________________________\n", - "encoder_output (Dense) (None, 2) 34 dense_17[0][0] \n", + "encoder_output (Dense) (None, 2) 34 dense_13[0][0] \n", "__________________________________________________________________________________________________\n", - "dense_18 (Dense) (None, 16) 48 encoder_output[0][0] \n", + "dense_14 (Dense) (None, 16) 48 encoder_output[0][0] \n", "__________________________________________________________________________________________________\n", - "dense_20 (Dense) (None, 16) 48 encoder_output[0][0] \n", + "dense_16 (Dense) (None, 16) 48 encoder_output[0][0] \n", "__________________________________________________________________________________________________\n", - "dense_19 (Dense) (None, 32) 544 dense_18[0][0] \n", + "dense_15 (Dense) (None, 32) 544 dense_14[0][0] \n", "__________________________________________________________________________________________________\n", - "dense_21 (Dense) (None, 32) 544 dense_20[0][0] \n", + "dense_17 (Dense) (None, 32) 544 dense_16[0][0] \n", "__________________________________________________________________________________________________\n", - "ecoder_output (Dense) (None, 100) 3300 dense_19[0][0] \n", + "ecoder_output (Dense) (None, 100) 3300 dense_15[0][0] \n", "__________________________________________________________________________________________________\n", - "classifier_output (Dense) (None, 10) 330 dense_21[0][0] \n", + "classifier_output (Dense) (None, 10) 330 dense_17[0][0] \n", "==================================================================================================\n", "Total params: 8,608\n", "Trainable params: 8,608\n", "Non-trainable params: 0\n", "__________________________________________________________________________________________________\n", "Epoch 1/30\n", - "235/235 [==============================] - 1s 5ms/step - loss: 0.3106 - ecoder_output_loss: 0.1251 - classifier_output_loss: 1.8557 - ecoder_output_accuracy: 0.0501 - classifier_output_accuracy: 0.3143 - val_loss: 0.2369 - val_ecoder_output_loss: 0.1027 - val_classifier_output_loss: 1.3422 - val_ecoder_output_accuracy: 0.0431 - val_classifier_output_accuracy: 0.5199\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.2791 - ecoder_output_loss: 0.1228 - classifier_output_loss: 1.5624 - ecoder_output_accuracy: 0.0314 - classifier_output_accuracy: 0.4244 - val_loss: 0.1948 - val_ecoder_output_loss: 0.0917 - val_classifier_output_loss: 1.0316 - val_ecoder_output_accuracy: 0.0329 - val_classifier_output_accuracy: 0.6416\n", "Epoch 2/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.2134 - ecoder_output_loss: 0.0982 - classifier_output_loss: 1.1522 - ecoder_output_accuracy: 0.0386 - classifier_output_accuracy: 0.5996 - val_loss: 0.1941 - val_ecoder_output_loss: 0.0938 - val_classifier_output_loss: 1.0026 - val_ecoder_output_accuracy: 0.0256 - val_classifier_output_accuracy: 0.6663\n", + "235/235 [==============================] - 0s 2ms/step - loss: 0.1771 - ecoder_output_loss: 0.0902 - classifier_output_loss: 0.8688 - ecoder_output_accuracy: 0.0366 - classifier_output_accuracy: 0.7138 - val_loss: 0.1629 - val_ecoder_output_loss: 0.0877 - val_classifier_output_loss: 0.7523 - val_ecoder_output_accuracy: 0.0346 - val_classifier_output_accuracy: 0.7556\n", "Epoch 3/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1848 - ecoder_output_loss: 0.0925 - classifier_output_loss: 0.9234 - ecoder_output_accuracy: 0.0248 - classifier_output_accuracy: 0.7000 - val_loss: 0.1753 - val_ecoder_output_loss: 0.0907 - val_classifier_output_loss: 0.8460 - val_ecoder_output_accuracy: 0.0254 - val_classifier_output_accuracy: 0.7269\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1554 - ecoder_output_loss: 0.0872 - classifier_output_loss: 0.6821 - ecoder_output_accuracy: 0.0381 - classifier_output_accuracy: 0.7871 - val_loss: 0.1485 - val_ecoder_output_loss: 0.0854 - val_classifier_output_loss: 0.6305 - val_ecoder_output_accuracy: 0.0315 - val_classifier_output_accuracy: 0.8038\n", "Epoch 4/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1689 - ecoder_output_loss: 0.0894 - classifier_output_loss: 0.7945 - ecoder_output_accuracy: 0.0198 - classifier_output_accuracy: 0.7484 - val_loss: 0.1630 - val_ecoder_output_loss: 0.0876 - val_classifier_output_loss: 0.7546 - val_ecoder_output_accuracy: 0.0197 - val_classifier_output_accuracy: 0.7637\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1430 - ecoder_output_loss: 0.0849 - classifier_output_loss: 0.5811 - ecoder_output_accuracy: 0.0340 - classifier_output_accuracy: 0.8263 - val_loss: 0.1388 - val_ecoder_output_loss: 0.0835 - val_classifier_output_loss: 0.5524 - val_ecoder_output_accuracy: 0.0289 - val_classifier_output_accuracy: 0.8358\n", "Epoch 5/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1579 - ecoder_output_loss: 0.0874 - classifier_output_loss: 0.7055 - ecoder_output_accuracy: 0.0212 - classifier_output_accuracy: 0.7839 - val_loss: 0.1537 - val_ecoder_output_loss: 0.0859 - val_classifier_output_loss: 0.6786 - val_ecoder_output_accuracy: 0.0247 - val_classifier_output_accuracy: 0.7951\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1354 - ecoder_output_loss: 0.0834 - classifier_output_loss: 0.5209 - ecoder_output_accuracy: 0.0313 - classifier_output_accuracy: 0.8474 - val_loss: 0.1325 - val_ecoder_output_loss: 0.0821 - val_classifier_output_loss: 0.5041 - val_ecoder_output_accuracy: 0.0256 - val_classifier_output_accuracy: 0.8523\n", "Epoch 6/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1499 - ecoder_output_loss: 0.0858 - classifier_output_loss: 0.6409 - ecoder_output_accuracy: 0.0222 - classifier_output_accuracy: 0.8087 - val_loss: 0.1466 - val_ecoder_output_loss: 0.0848 - val_classifier_output_loss: 0.6179 - val_ecoder_output_accuracy: 0.0227 - val_classifier_output_accuracy: 0.8205\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1301 - ecoder_output_loss: 0.0824 - classifier_output_loss: 0.4771 - ecoder_output_accuracy: 0.0300 - classifier_output_accuracy: 0.8630 - val_loss: 0.1282 - val_ecoder_output_loss: 0.0816 - val_classifier_output_loss: 0.4659 - val_ecoder_output_accuracy: 0.0293 - val_classifier_output_accuracy: 0.8688\n", "Epoch 7/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1435 - ecoder_output_loss: 0.0846 - classifier_output_loss: 0.5890 - ecoder_output_accuracy: 0.0232 - classifier_output_accuracy: 0.8287 - val_loss: 0.1409 - val_ecoder_output_loss: 0.0829 - val_classifier_output_loss: 0.5806 - val_ecoder_output_accuracy: 0.0233 - val_classifier_output_accuracy: 0.8354\n", + "235/235 [==============================] - 0s 2ms/step - loss: 0.1261 - ecoder_output_loss: 0.0816 - classifier_output_loss: 0.4443 - ecoder_output_accuracy: 0.0299 - classifier_output_accuracy: 0.8734 - val_loss: 0.1244 - val_ecoder_output_loss: 0.0807 - val_classifier_output_loss: 0.4363 - val_ecoder_output_accuracy: 0.0292 - val_classifier_output_accuracy: 0.8783\n", "Epoch 8/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1375 - ecoder_output_loss: 0.0825 - classifier_output_loss: 0.5506 - ecoder_output_accuracy: 0.0206 - classifier_output_accuracy: 0.8425 - val_loss: 0.1354 - val_ecoder_output_loss: 0.0812 - val_classifier_output_loss: 0.5422 - val_ecoder_output_accuracy: 0.0207 - val_classifier_output_accuracy: 0.8441\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1227 - ecoder_output_loss: 0.0809 - classifier_output_loss: 0.4180 - ecoder_output_accuracy: 0.0301 - classifier_output_accuracy: 0.8813 - val_loss: 0.1213 - val_ecoder_output_loss: 0.0800 - val_classifier_output_loss: 0.4136 - val_ecoder_output_accuracy: 0.0280 - val_classifier_output_accuracy: 0.8852\n", "Epoch 9/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1329 - ecoder_output_loss: 0.0812 - classifier_output_loss: 0.5165 - ecoder_output_accuracy: 0.0217 - classifier_output_accuracy: 0.8543 - val_loss: 0.1318 - val_ecoder_output_loss: 0.0804 - val_classifier_output_loss: 0.5146 - val_ecoder_output_accuracy: 0.0249 - val_classifier_output_accuracy: 0.8567\n", + "235/235 [==============================] - 0s 2ms/step - loss: 0.1200 - ecoder_output_loss: 0.0803 - classifier_output_loss: 0.3965 - ecoder_output_accuracy: 0.0308 - classifier_output_accuracy: 0.8900 - val_loss: 0.1188 - val_ecoder_output_loss: 0.0793 - val_classifier_output_loss: 0.3949 - val_ecoder_output_accuracy: 0.0271 - val_classifier_output_accuracy: 0.8908\n", "Epoch 10/30\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.1290 - ecoder_output_loss: 0.0805 - classifier_output_loss: 0.4853 - ecoder_output_accuracy: 0.0236 - classifier_output_accuracy: 0.8645 - val_loss: 0.1286 - val_ecoder_output_loss: 0.0798 - val_classifier_output_loss: 0.4882 - val_ecoder_output_accuracy: 0.0220 - val_classifier_output_accuracy: 0.8665\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1177 - ecoder_output_loss: 0.0799 - classifier_output_loss: 0.3788 - ecoder_output_accuracy: 0.0326 - classifier_output_accuracy: 0.8951 - val_loss: 0.1174 - val_ecoder_output_loss: 0.0790 - val_classifier_output_loss: 0.3843 - val_ecoder_output_accuracy: 0.0260 - val_classifier_output_accuracy: 0.8931\n", "Epoch 11/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1262 - ecoder_output_loss: 0.0799 - classifier_output_loss: 0.4623 - ecoder_output_accuracy: 0.0238 - classifier_output_accuracy: 0.8717 - val_loss: 0.1257 - val_ecoder_output_loss: 0.0791 - val_classifier_output_loss: 0.4660 - val_ecoder_output_accuracy: 0.0283 - val_classifier_output_accuracy: 0.8747\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1159 - ecoder_output_loss: 0.0795 - classifier_output_loss: 0.3637 - ecoder_output_accuracy: 0.0341 - classifier_output_accuracy: 0.8993 - val_loss: 0.1153 - val_ecoder_output_loss: 0.0787 - val_classifier_output_loss: 0.3667 - val_ecoder_output_accuracy: 0.0256 - val_classifier_output_accuracy: 0.8992\n", "Epoch 12/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1232 - ecoder_output_loss: 0.0795 - classifier_output_loss: 0.4366 - ecoder_output_accuracy: 0.0236 - classifier_output_accuracy: 0.8801 - val_loss: 0.1231 - val_ecoder_output_loss: 0.0785 - val_classifier_output_loss: 0.4457 - val_ecoder_output_accuracy: 0.0232 - val_classifier_output_accuracy: 0.8819\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1141 - ecoder_output_loss: 0.0793 - classifier_output_loss: 0.3478 - ecoder_output_accuracy: 0.0348 - classifier_output_accuracy: 0.9044 - val_loss: 0.1149 - val_ecoder_output_loss: 0.0784 - val_classifier_output_loss: 0.3653 - val_ecoder_output_accuracy: 0.0311 - val_classifier_output_accuracy: 0.9008\n", "Epoch 13/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1207 - ecoder_output_loss: 0.0791 - classifier_output_loss: 0.4164 - ecoder_output_accuracy: 0.0228 - classifier_output_accuracy: 0.8863 - val_loss: 0.1226 - val_ecoder_output_loss: 0.0782 - val_classifier_output_loss: 0.4444 - val_ecoder_output_accuracy: 0.0231 - val_classifier_output_accuracy: 0.8858\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1127 - ecoder_output_loss: 0.0790 - classifier_output_loss: 0.3370 - ecoder_output_accuracy: 0.0341 - classifier_output_accuracy: 0.9077 - val_loss: 0.1134 - val_ecoder_output_loss: 0.0782 - val_classifier_output_loss: 0.3519 - val_ecoder_output_accuracy: 0.0308 - val_classifier_output_accuracy: 0.9047\n", "Epoch 14/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1186 - ecoder_output_loss: 0.0786 - classifier_output_loss: 0.3995 - ecoder_output_accuracy: 0.0245 - classifier_output_accuracy: 0.8918 - val_loss: 0.1199 - val_ecoder_output_loss: 0.0779 - val_classifier_output_loss: 0.4205 - val_ecoder_output_accuracy: 0.0235 - val_classifier_output_accuracy: 0.8912\n", + "235/235 [==============================] - 0s 2ms/step - loss: 0.1114 - ecoder_output_loss: 0.0788 - classifier_output_loss: 0.3266 - ecoder_output_accuracy: 0.0337 - classifier_output_accuracy: 0.9106 - val_loss: 0.1126 - val_ecoder_output_loss: 0.0780 - val_classifier_output_loss: 0.3456 - val_ecoder_output_accuracy: 0.0250 - val_classifier_output_accuracy: 0.9066\n", "Epoch 15/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1166 - ecoder_output_loss: 0.0782 - classifier_output_loss: 0.3844 - ecoder_output_accuracy: 0.0250 - classifier_output_accuracy: 0.8964 - val_loss: 0.1177 - val_ecoder_output_loss: 0.0774 - val_classifier_output_loss: 0.4028 - val_ecoder_output_accuracy: 0.0231 - val_classifier_output_accuracy: 0.8931\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1104 - ecoder_output_loss: 0.0786 - classifier_output_loss: 0.3179 - ecoder_output_accuracy: 0.0335 - classifier_output_accuracy: 0.9130 - val_loss: 0.1130 - val_ecoder_output_loss: 0.0778 - val_classifier_output_loss: 0.3515 - val_ecoder_output_accuracy: 0.0300 - val_classifier_output_accuracy: 0.9042\n", "Epoch 16/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1151 - ecoder_output_loss: 0.0779 - classifier_output_loss: 0.3719 - ecoder_output_accuracy: 0.0260 - classifier_output_accuracy: 0.8999 - val_loss: 0.1162 - val_ecoder_output_loss: 0.0769 - val_classifier_output_loss: 0.3926 - val_ecoder_output_accuracy: 0.0270 - val_classifier_output_accuracy: 0.9000\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1092 - ecoder_output_loss: 0.0783 - classifier_output_loss: 0.3087 - ecoder_output_accuracy: 0.0330 - classifier_output_accuracy: 0.9170 - val_loss: 0.1108 - val_ecoder_output_loss: 0.0776 - val_classifier_output_loss: 0.3325 - val_ecoder_output_accuracy: 0.0321 - val_classifier_output_accuracy: 0.9100\n", "Epoch 17/30\n", - "235/235 [==============================] - 1s 4ms/step - loss: 0.1138 - ecoder_output_loss: 0.0777 - classifier_output_loss: 0.3615 - ecoder_output_accuracy: 0.0261 - classifier_output_accuracy: 0.9034 - val_loss: 0.1149 - val_ecoder_output_loss: 0.0768 - val_classifier_output_loss: 0.3809 - val_ecoder_output_accuracy: 0.0265 - val_classifier_output_accuracy: 0.8989\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1082 - ecoder_output_loss: 0.0780 - classifier_output_loss: 0.3019 - ecoder_output_accuracy: 0.0322 - classifier_output_accuracy: 0.9185 - val_loss: 0.1108 - val_ecoder_output_loss: 0.0774 - val_classifier_output_loss: 0.3338 - val_ecoder_output_accuracy: 0.0277 - val_classifier_output_accuracy: 0.9102\n", "Epoch 18/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1126 - ecoder_output_loss: 0.0775 - classifier_output_loss: 0.3516 - ecoder_output_accuracy: 0.0275 - classifier_output_accuracy: 0.9062 - val_loss: 0.1151 - val_ecoder_output_loss: 0.0767 - val_classifier_output_loss: 0.3845 - val_ecoder_output_accuracy: 0.0245 - val_classifier_output_accuracy: 0.9013\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1073 - ecoder_output_loss: 0.0778 - classifier_output_loss: 0.2944 - ecoder_output_accuracy: 0.0302 - classifier_output_accuracy: 0.9201 - val_loss: 0.1109 - val_ecoder_output_loss: 0.0773 - val_classifier_output_loss: 0.3356 - val_ecoder_output_accuracy: 0.0267 - val_classifier_output_accuracy: 0.9104\n", "Epoch 19/30\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.1118 - ecoder_output_loss: 0.0774 - classifier_output_loss: 0.3442 - ecoder_output_accuracy: 0.0269 - classifier_output_accuracy: 0.9081 - val_loss: 0.1136 - val_ecoder_output_loss: 0.0764 - val_classifier_output_loss: 0.3724 - val_ecoder_output_accuracy: 0.0265 - val_classifier_output_accuracy: 0.9069\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1064 - ecoder_output_loss: 0.0776 - classifier_output_loss: 0.2880 - ecoder_output_accuracy: 0.0305 - classifier_output_accuracy: 0.9218 - val_loss: 0.1094 - val_ecoder_output_loss: 0.0769 - val_classifier_output_loss: 0.3256 - val_ecoder_output_accuracy: 0.0257 - val_classifier_output_accuracy: 0.9126\n", "Epoch 20/30\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.1108 - ecoder_output_loss: 0.0772 - classifier_output_loss: 0.3366 - ecoder_output_accuracy: 0.0269 - classifier_output_accuracy: 0.9107 - val_loss: 0.1121 - val_ecoder_output_loss: 0.0763 - val_classifier_output_loss: 0.3587 - val_ecoder_output_accuracy: 0.0286 - val_classifier_output_accuracy: 0.9087\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1057 - ecoder_output_loss: 0.0774 - classifier_output_loss: 0.2836 - ecoder_output_accuracy: 0.0302 - classifier_output_accuracy: 0.9234 - val_loss: 0.1091 - val_ecoder_output_loss: 0.0768 - val_classifier_output_loss: 0.3234 - val_ecoder_output_accuracy: 0.0248 - val_classifier_output_accuracy: 0.9104\n", "Epoch 21/30\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.1099 - ecoder_output_loss: 0.0770 - classifier_output_loss: 0.3289 - ecoder_output_accuracy: 0.0270 - classifier_output_accuracy: 0.9131 - val_loss: 0.1117 - val_ecoder_output_loss: 0.0761 - val_classifier_output_loss: 0.3557 - val_ecoder_output_accuracy: 0.0312 - val_classifier_output_accuracy: 0.9107\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1049 - ecoder_output_loss: 0.0771 - classifier_output_loss: 0.2783 - ecoder_output_accuracy: 0.0301 - classifier_output_accuracy: 0.9247 - val_loss: 0.1079 - val_ecoder_output_loss: 0.0764 - val_classifier_output_loss: 0.3144 - val_ecoder_output_accuracy: 0.0266 - val_classifier_output_accuracy: 0.9152\n", "Epoch 22/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1091 - ecoder_output_loss: 0.0768 - classifier_output_loss: 0.3224 - ecoder_output_accuracy: 0.0271 - classifier_output_accuracy: 0.9151 - val_loss: 0.1113 - val_ecoder_output_loss: 0.0759 - val_classifier_output_loss: 0.3535 - val_ecoder_output_accuracy: 0.0231 - val_classifier_output_accuracy: 0.9110\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1043 - ecoder_output_loss: 0.0769 - classifier_output_loss: 0.2741 - ecoder_output_accuracy: 0.0298 - classifier_output_accuracy: 0.9260 - val_loss: 0.1074 - val_ecoder_output_loss: 0.0761 - val_classifier_output_loss: 0.3125 - val_ecoder_output_accuracy: 0.0240 - val_classifier_output_accuracy: 0.9152\n", "Epoch 23/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1085 - ecoder_output_loss: 0.0767 - classifier_output_loss: 0.3185 - ecoder_output_accuracy: 0.0273 - classifier_output_accuracy: 0.9158 - val_loss: 0.1106 - val_ecoder_output_loss: 0.0757 - val_classifier_output_loss: 0.3485 - val_ecoder_output_accuracy: 0.0269 - val_classifier_output_accuracy: 0.9101\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1035 - ecoder_output_loss: 0.0766 - classifier_output_loss: 0.2690 - ecoder_output_accuracy: 0.0317 - classifier_output_accuracy: 0.9275 - val_loss: 0.1069 - val_ecoder_output_loss: 0.0759 - val_classifier_output_loss: 0.3093 - val_ecoder_output_accuracy: 0.0277 - val_classifier_output_accuracy: 0.9148\n", "Epoch 24/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1077 - ecoder_output_loss: 0.0765 - classifier_output_loss: 0.3121 - ecoder_output_accuracy: 0.0275 - classifier_output_accuracy: 0.9178 - val_loss: 0.1103 - val_ecoder_output_loss: 0.0757 - val_classifier_output_loss: 0.3461 - val_ecoder_output_accuracy: 0.0244 - val_classifier_output_accuracy: 0.9124\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1029 - ecoder_output_loss: 0.0764 - classifier_output_loss: 0.2647 - ecoder_output_accuracy: 0.0311 - classifier_output_accuracy: 0.9286 - val_loss: 0.1072 - val_ecoder_output_loss: 0.0758 - val_classifier_output_loss: 0.3144 - val_ecoder_output_accuracy: 0.0298 - val_classifier_output_accuracy: 0.9159\n", "Epoch 25/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1071 - ecoder_output_loss: 0.0763 - classifier_output_loss: 0.3079 - ecoder_output_accuracy: 0.0273 - classifier_output_accuracy: 0.9188 - val_loss: 0.1094 - val_ecoder_output_loss: 0.0755 - val_classifier_output_loss: 0.3392 - val_ecoder_output_accuracy: 0.0267 - val_classifier_output_accuracy: 0.9137\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1024 - ecoder_output_loss: 0.0762 - classifier_output_loss: 0.2617 - ecoder_output_accuracy: 0.0322 - classifier_output_accuracy: 0.9300 - val_loss: 0.1068 - val_ecoder_output_loss: 0.0755 - val_classifier_output_loss: 0.3128 - val_ecoder_output_accuracy: 0.0323 - val_classifier_output_accuracy: 0.9144\n", "Epoch 26/30\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.1064 - ecoder_output_loss: 0.0761 - classifier_output_loss: 0.3027 - ecoder_output_accuracy: 0.0269 - classifier_output_accuracy: 0.9201 - val_loss: 0.1089 - val_ecoder_output_loss: 0.0752 - val_classifier_output_loss: 0.3372 - val_ecoder_output_accuracy: 0.0301 - val_classifier_output_accuracy: 0.9153\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1019 - ecoder_output_loss: 0.0761 - classifier_output_loss: 0.2585 - ecoder_output_accuracy: 0.0330 - classifier_output_accuracy: 0.9306 - val_loss: 0.1058 - val_ecoder_output_loss: 0.0753 - val_classifier_output_loss: 0.3045 - val_ecoder_output_accuracy: 0.0245 - val_classifier_output_accuracy: 0.9190\n", "Epoch 27/30\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.1058 - ecoder_output_loss: 0.0759 - classifier_output_loss: 0.2987 - ecoder_output_accuracy: 0.0263 - classifier_output_accuracy: 0.9214 - val_loss: 0.1083 - val_ecoder_output_loss: 0.0751 - val_classifier_output_loss: 0.3313 - val_ecoder_output_accuracy: 0.0280 - val_classifier_output_accuracy: 0.9159\n", + "235/235 [==============================] - 0s 2ms/step - loss: 0.1014 - ecoder_output_loss: 0.0759 - classifier_output_loss: 0.2547 - ecoder_output_accuracy: 0.0328 - classifier_output_accuracy: 0.9317 - val_loss: 0.1056 - val_ecoder_output_loss: 0.0751 - val_classifier_output_loss: 0.3051 - val_ecoder_output_accuracy: 0.0296 - val_classifier_output_accuracy: 0.9169\n", "Epoch 28/30\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.1054 - ecoder_output_loss: 0.0758 - classifier_output_loss: 0.2960 - ecoder_output_accuracy: 0.0261 - classifier_output_accuracy: 0.9221 - val_loss: 0.1077 - val_ecoder_output_loss: 0.0749 - val_classifier_output_loss: 0.3281 - val_ecoder_output_accuracy: 0.0274 - val_classifier_output_accuracy: 0.9183\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1006 - ecoder_output_loss: 0.0757 - classifier_output_loss: 0.2498 - ecoder_output_accuracy: 0.0336 - classifier_output_accuracy: 0.9338 - val_loss: 0.1048 - val_ecoder_output_loss: 0.0750 - val_classifier_output_loss: 0.2976 - val_ecoder_output_accuracy: 0.0301 - val_classifier_output_accuracy: 0.9212\n", "Epoch 29/30\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.1047 - ecoder_output_loss: 0.0756 - classifier_output_loss: 0.2910 - ecoder_output_accuracy: 0.0248 - classifier_output_accuracy: 0.9230 - val_loss: 0.1075 - val_ecoder_output_loss: 0.0746 - val_classifier_output_loss: 0.3286 - val_ecoder_output_accuracy: 0.0221 - val_classifier_output_accuracy: 0.9184\n", + "235/235 [==============================] - 0s 1ms/step - loss: 0.1004 - ecoder_output_loss: 0.0756 - classifier_output_loss: 0.2481 - ecoder_output_accuracy: 0.0330 - classifier_output_accuracy: 0.9340 - val_loss: 0.1049 - val_ecoder_output_loss: 0.0749 - val_classifier_output_loss: 0.3007 - val_ecoder_output_accuracy: 0.0258 - val_classifier_output_accuracy: 0.9197\n", "Epoch 30/30\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.1041 - ecoder_output_loss: 0.0754 - classifier_output_loss: 0.2871 - ecoder_output_accuracy: 0.0240 - classifier_output_accuracy: 0.9242 - val_loss: 0.1070 - val_ecoder_output_loss: 0.0746 - val_classifier_output_loss: 0.3240 - val_ecoder_output_accuracy: 0.0234 - val_classifier_output_accuracy: 0.9189\n" + "235/235 [==============================] - 0s 1ms/step - loss: 0.1001 - ecoder_output_loss: 0.0754 - classifier_output_loss: 0.2463 - ecoder_output_accuracy: 0.0331 - classifier_output_accuracy: 0.9338 - val_loss: 0.1041 - val_ecoder_output_loss: 0.0748 - val_classifier_output_loss: 0.2928 - val_ecoder_output_accuracy: 0.0313 - val_classifier_output_accuracy: 0.9216\n" ] }, { "data": { - "image/png": "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bEt1dTUtLS189rOfTS8Xffvb3+Y3v/lNeqr/Yx/7WPoxVq5cyR133MGSJUsoLi6mp6eHv/qrv2LTpk2sX7+edevWsXHjxnRBtE2bNvHd736XL33pS5SUlLB06dKsu2GyueKKK/jBD37An/3Zn+H1etmyZUt6ZufRRx+lo6OD2tpabr31Vh544AHe//73p7+PTU1NtLS0cOONN/LZz3523PfxySefZNeuXbS0tFBeXs79998/LhCbii1btlBWVpZe+tiyZQtaazZu3Jj1+Pe9732sWbOG6upqysvLz+laAI2NjTz11FP83d/9HaWlpWzYsIHdu3dnHDfR74JlWfzv//2/0/lEL730Uno2ZLKf2ak4398rIRYTpU/NYwpxgVNKceTIEZYuXTrfQxFCCDFNMuMihBBCiEVDAhchhBBCzKtvf/vbrF27ljVr1qQLSeZy/rWjhVgkZFVUCCEWnr179/Ld736X7du343Q6ufnmm7nllltyLuvLjIsQQggh5s2BAwe48soryc/Px263s2XLFn7xi1/kPH5BzriUl5fT3Nw838MQQggh5kRHR0e66OVcuPmGZoaGI3NyrUiifFwl7G3btrFt27b012vXruVrX/saw8PDuN1unnrqKTZt2pTz8RZk4NLc3MyOHTvmexhCCCHEnJjojXo2DA1H2PH7yYtRzoRNN7464Xv6qlWr+OpXv8qNN95IQUEBGzZswGaz5Tx+0qWizs5O3vve97J69WrWrFnDt7/9bQBGRkbYunUry5YtY+vWrfh8vqznP/zwwyxbtoxly5adV2lzIYQQQlyY7rvvPt5++21efvllSkpKWL58ec5jJw1c7HY7f/d3f8f+/ft54403+Kd/+if279/Pt771LW644QaOHDnCDTfcwLe+9a2Mc09Vj3zzzTfZvn07DzzwQM4ARwghhBAXp4GBASDVJuQXv/gFd955Z85jJw1campq0hUpCwsLWbVqFd3d3TzxxBPcfffdANx999386le/yjj3d7/7HVu3bqW0tJSSkhK2bt3K008/PZ3nJIQQQogL1G233cbq1av58Ic/zD/90z9RXFyc89hzynHp6Ohg586dXHnllfT391NTUwOkmoSd2eH1lO7u7nEdSevr63N2zX3wwQd58MEHARgcHDyXYQkhhBBiEXvllVemfOyUt0MHg0Fuu+02/v7v/56ioqJx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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiUAAAJOCAYAAABoXndyAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8rg+JYAAAACXBIWXMAAAsTAAALEwEAmpwYAAEAAElEQVR4nOzdd3xk1X3w/8+9d4p6713b+2oLu5SFBWwwGIxNsQ0GB9vE2E6cGDvJgxM7Lkme2H4cP3F58osNccEYU9zABTB9gQW2965V772NNO3e8/vjakc7mhmVXUkrrb7v10sv0Nx27qyk+51zvud7NKWUQgghhBDiAtMvdAOEEEIIIUCCEiGEEELMEhKUCCGEEGJWkKBECCGEELOCBCVCCCGEmBUkKBFCCCHErCBBiRDinLz22msUFRXN+HVvvPFGHnnkkZjbP/axj/HlL3/5vK8zVeeJJSkpiaqqKgCGhoZ43/veR2pqKh/84Ad57LHHuP7666ft2kLMVhKUCMrKynjppZcmfdzVV1/N//zP/0xZOzRNo7KycsrOdyEMDAyQlJTEjTfeOKnjLtQDfi567rnnuPfeewH42c9+xpYtWy5wi87NwMAACxYsAODXv/41ra2tdHZ28qtf/Yq7776bF1544QK3UIiZJ0GJEFPoN7/5DW63mxdffJGWlpYL3ZxZKxgMXugmzCq1tbUsWbIEh8Nx3ucyTXMKWiTEhSFBiYipu7ubm2++mezsbNLT07n55ptpaGgA4Etf+hJvvPEGn/3sZ0lKSuKzn/0sAMePH+e6664jIyODpUuX8tRTT4XO97GPfYy//uu/5qabbiI5OZnNmzdz+vRpAK666ioA1q5dS1JSEk8++WREeyorK9m6dSupqalkZWXx4Q9/OLRN0zS+//3vs2DBArKysviHf/gHLMsC4PTp01x77bVkZmaSlZXF3XffTU9PT+jY+vp6brvtNrKzs8nMzAzdC8BPfvITli9fTnp6Ou95z3uora0d8z175JFH+PSnP82aNWv4xS9+EbZtdE/QmeEBj8fDjTfeSFNTE0lJSSQlJdHU1ITP5+OBBx6goKCAgoICHnjgAXw+X+j4P/7xj1RUVJCWlsbll1/OwYMHQ9vKysr4j//4D9asWUNqaiof/vCH8Xq9oe3PPPMMFRUVpKSksHDhQp5//nkAmpqauOWWW8jIyGDRokU8/PDDoWOGhob42Mc+Rnp6OitWrGDXrl1h99fU1MTtt99OdnY25eXlfP/73w9t+9rXvsYdd9zBPffcQ0pKCj/72c/Cjq2uriYtLS30b/bJT36SnJyc0PaPfvSjfPe73wVGeuiOHTvGpz/9ad5++22SkpJIS0sL7d/d3R315yyaN998k8svv5y0tDSKi4sj2nbmfLF+F8DusVmwYAHJycmUl5fz2GOPAeP/zFZWVvLVr36Vf/mXf+HJJ58kKSmJH//4xxE9QOP9Xn3mM5/hve99L4mJibz66qsx71WIWU+Jea+0tFS9+OKLEa93dHSoX//618rj8ai+vj51xx13qPe///2h7Vu3blUPP/xw6PuBgQFVVFSkfvKTn6hAIKD27t2rMjMz1ZEjR5RSSt17770qIyND7dixQwUCAfWRj3xEffjDHw4dD6hTp07FbOedd96p/u3f/k2ZpqmGhobUG2+8EXbs1VdfrTo7O1Vtba1avHhxqG2nTp1SL7zwgvJ6vaqtrU1deeWV6nOf+5xSSqlgMKjWrFmjHnjgATUwMBB23qefflotXLhQHT16VAUCAfWv//qv6rLLLovZvpqaGqVpmjpy5Ij6j//4D7V69eqw7aPv795771Vf+tKXlFJKvfrqq6qwsDBs/3/+539WmzdvVq2traqtrU1ddtll6stf/rJSSqm9e/eq7Oxs9c4776hgMKh+9rOfqdLSUuX1epVS9r/pJZdcohobG1VnZ6datmyZ+u///m+llFI7duxQKSkp6oUXXlCmaaqGhgZ17NgxpZRSV155pfrMZz6jhoaG1L59+1RWVpZ6+eWXlVJKPfjgg2rLli2qs7NT1dXVqZUrV4babJqmWr9+vfr617+ufD6fOn36tCovL1fPP/+8Ukqpr371q8rhcKjf/e53yjRNNTg4GPH+FRcXq927dyullFqyZIkqLy9XR48eDW3bu3evUir85+6nP/2puuKKK8LOM97P2eh/s6SkJPXLX/5S+f1+1dHRofbt2xfx7zPW78LAwIBKTk5Wx48fV0op1dTUpA4fPqyUGv9n9szPw1e/+lV19913h7adfV8T+b1KSUlRb775Zug6QsxV0lMiYsrMzOT2228nISGB5ORkvvSlL7Ft27aY+//xj3+krKyMj3/84zgcDtatW8ftt9/Or371q9A+t956K5s2bcLhcHD33Xezf//+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", "text/plain": [ "
" ] @@ -546,7 +560,7 @@ }, { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] diff --git a/classifier_MNIST_NNonFPGA.ipynb b/classifier_MNIST_NNonFPGA.ipynb index 717a414..8c2038e 100644 --- a/classifier_MNIST_NNonFPGA.ipynb +++ b/classifier_MNIST_NNonFPGA.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -126,7 +126,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 2, "metadata": { "scrolled": true }, @@ -137,7 +137,7 @@ "dtype('uint8')" ] }, - "execution_count": 10, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -155,7 +155,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -252,7 +252,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -263,7 +263,7 @@ "_________________________________________________________________\n", "Layer (type) Output Shape Param # \n", "=================================================================\n", - "input_2 (InputLayer) [(None, 64)] 0 \n", + "input_1 (InputLayer) [(None, 64)] 0 \n", "_________________________________________________________________\n", "dense (Dense) (None, 32) 2080 \n", "_________________________________________________________________\n", @@ -282,7 +282,7 @@ ], "source": [ "#ENCODER\n", - "input = Input(shape=(X_train_flat_zoom.shape[-1],))\n", + "input = Input(shape=(X_train_flat_zoom_int.shape[-1],))\n", "encoder = Dense(32, activation='relu')(input)\n", "encoder = Dense(2, activation='relu')(encoder)\n", "\n", @@ -298,100 +298,60 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Epoch 1/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0726 - val_loss: 0.0720\n", - "Epoch 2/40\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0719 - val_loss: 0.0714\n", - "Epoch 3/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0713 - val_loss: 0.0710\n", - "Epoch 4/40\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0709 - val_loss: 0.0706\n", - "Epoch 5/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0705 - val_loss: 0.0702\n", - "Epoch 6/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0702 - val_loss: 0.0699\n", - "Epoch 7/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0699 - val_loss: 0.0696\n", - "Epoch 8/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0696 - val_loss: 0.0693\n", - "Epoch 9/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0693 - val_loss: 0.0691\n", - "Epoch 10/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0691 - val_loss: 0.0689\n", - "Epoch 11/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0688 - val_loss: 0.0687\n", - "Epoch 12/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0686 - val_loss: 0.0685\n", - "Epoch 13/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0684 - val_loss: 0.0683\n", - "Epoch 14/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0683 - val_loss: 0.0681\n", - "Epoch 15/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0681 - val_loss: 0.0680\n", - "Epoch 16/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0679 - val_loss: 0.0679\n", - "Epoch 17/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0678 - val_loss: 0.0677\n", - "Epoch 18/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0677 - val_loss: 0.0676\n", - "Epoch 19/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0675 - val_loss: 0.0676\n", - "Epoch 20/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0674 - val_loss: 0.0674\n", - "Epoch 21/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0673 - val_loss: 0.0673\n", - "Epoch 22/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0672 - val_loss: 0.0673\n", - "Epoch 23/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0671 - val_loss: 0.0672\n", - "Epoch 24/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0670 - val_loss: 0.0671\n", - "Epoch 25/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0669 - val_loss: 0.0670\n", - "Epoch 26/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0668 - val_loss: 0.0669\n", - "Epoch 27/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0668 - val_loss: 0.0668\n", - "Epoch 28/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0667 - val_loss: 0.0668\n", - "Epoch 29/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0666 - val_loss: 0.0667\n", - "Epoch 30/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0665 - val_loss: 0.0666\n", - "Epoch 31/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0664 - val_loss: 0.0665\n", - "Epoch 32/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0663 - val_loss: 0.0665\n", - "Epoch 33/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0662 - val_loss: 0.0664\n", - "Epoch 34/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0661 - val_loss: 0.0664\n", - "Epoch 35/40\n", - "235/235 [==============================] - 1s 3ms/step - loss: 0.0661 - val_loss: 0.0663\n", - "Epoch 36/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0660 - val_loss: 0.0662\n", - "Epoch 37/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0659 - val_loss: 0.0661\n", - "Epoch 38/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0658 - val_loss: 0.0661\n", - "Epoch 39/40\n", - "235/235 [==============================] - 0s 2ms/step - loss: 0.0658 - val_loss: 0.0660\n", - "Epoch 40/40\n", - "235/235 [==============================] - 1s 2ms/step - loss: 0.0657 - val_loss: 0.0660\n" + "Epoch 1/20\n", + "235/235 [==============================] - 1s 5ms/step - loss: 0.1300 - val_loss: 0.1014\n", + "Epoch 2/20\n", + "235/235 [==============================] - 1s 4ms/step - loss: 0.0979 - val_loss: 0.0946\n", + "Epoch 3/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0930 - val_loss: 0.0911\n", + "Epoch 4/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0903 - val_loss: 0.0891\n", + "Epoch 5/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0885 - val_loss: 0.0876\n", + "Epoch 6/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0871 - val_loss: 0.0862\n", + "Epoch 7/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0856 - val_loss: 0.0847\n", + "Epoch 8/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0842 - val_loss: 0.0832\n", + "Epoch 9/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0829 - val_loss: 0.0820\n", + "Epoch 10/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0817 - val_loss: 0.0810\n", + "Epoch 11/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0807 - val_loss: 0.0802\n", + "Epoch 12/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0800 - val_loss: 0.0797\n", + "Epoch 13/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0794 - val_loss: 0.0792\n", + "Epoch 14/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0790 - val_loss: 0.0788\n", + "Epoch 15/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0786 - val_loss: 0.0784\n", + "Epoch 16/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0782 - val_loss: 0.0780\n", + "Epoch 17/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0779 - val_loss: 0.0777\n", + "Epoch 18/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0776 - val_loss: 0.0774\n", + "Epoch 19/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0772 - val_loss: 0.0770\n", + "Epoch 20/20\n", + "235/235 [==============================] - 1s 3ms/step - loss: 0.0768 - val_loss: 0.0766\n" ] } ], "source": [ "history = autoencoder.fit(X_train_flat_zoom, X_train_flat_zoom,\n", " validation_data=(X_test_flat_zoom, X_test_flat_zoom),\n", - " batch_size = 256, epochs = 40,\n", + " batch_size = 256, epochs = 20,\n", " shuffle = True\n", " )" ] diff --git a/hls4ml_conversion.ipynb b/hls4ml_conversion.ipynb index 5fd22ab..f1c6f21 100644 --- a/hls4ml_conversion.ipynb +++ b/hls4ml_conversion.ipynb @@ -2,18 +2,119 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 17, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:tensorflow:No training configuration found in the save file, so the model was *not* compiled. Compile it manually.\n" + ] + } + ], "source": [ "from tensorflow import keras\n", - "ae_wo_classifier = keras.models.load_model('model/AE_model/KERAS_check_model_wo_classifier.h5')\n", + "ae_wo_classifier = keras.models.load_model('model/AE_model/KERAS_check_best_model.h5')\n", "#ae_w_classifier = keras.models.load_model('model/AE_model/KERAS_check_model_w_classifier.h5')\n", "\n", "#vae_wo_classifier = keras.models.load_model('model/VAE_model/KERAS_check_model_wo_classifier.h5')\n", "#vae_w_classifier = keras.models.load_model('model/VAE_model/KERAS_check_model_w_classifier.h5')" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Check sparsity\n", + "Make a quick check that the model was indeed trained sparse. We'll just make a histogram of the weights of the 1st layer, and hopefully observe a large peak in the bin containing '0'. Note logarithmic y axis." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "% of zeros = 0.75\n" + ] + }, + { + "data": { + "image/png": "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5wcGBuK6666LpqamaG1tTXVevu1obbzrrrvi4osvjsWLF8cVV1wRL730UhWqHJujtfFtv/rVr+IDH/hAPP300xNY3RhUeTr+Ia1bt6505513lkqlUunOO+8s3XbbbQft8+STT5ba2tpKg4ODpcHBwdJnP/vZ0u9+97uJLnXUymljqVQqfeELXyj95je/KZVKpdLu3btLb7zxxoTVOFbltrFUKpXWrl1bWrlyZenmm2+eqPIqopw2/uUvfyn99a9/LZVKpVJPT0/pvPPOK7322msTWeaIDA4OlhYsWFD629/+Vvrf//5XWrx4cenPf/7zsH3uvvvu0k033VQqlUqlzZs3l6699toqVDp65bTxscce2/fz9pOf/GRKtrFUKpX6+/tLl112Wam1tbXU3d1dhUpHblL2uDo7O2Pp0qUREbF06dJ4+OGHD9pnxowZMTAwEHv27Nn333e/+90TXOnoldPGHTt2xODgYJx33nkREXHiiSfGO9/5zoksc0zKaWNExDPPPBOvvPLKvnZmUk4b3//+98f73ve+iIgoFApxyimnxL///e8JrHJkuru7Y/bs2VFXVxezZs2K5ubm6OzsHLZPV1dXXHLJJRERsXDhwnjsscdSjXiU08Zzzz1338/bOeecEz09PdUoddTKaWNExB133BFf+tKX4h3veEcVqhydSRlcr7zySpx22mkREfGe97wnXnnllYP2+ehHPxrz5s2L888/P84///y44IIL4qyzzproUketnDbu3Lkz3vWud8XXvva1WLp0aaxbty6GhoYmutRRK6eNe/fujXXr1sWNN9440eVVRDlt3F93d3fs2bMnzjzzzIkob1R6e3ujtrZ23+NCoRC9vb0H7XP66adHRMSxxx4bNTU10dfXN6F1jkU5bdzfz3/+82hoaJiI0iqmnDb+8Y9/jJ6envjEJz4xwdWNTdVWh//iF78Y//rXvw7aft111w17PGPGjJgxY8ZB+73wwgvx/PPPx69//euIiLjqqqviiSeeiI997GPjUu9ojLWNg4OD8cQTT8R9990Xp59+elx//fVxzz33RGtr63iVPGJjbeNPf/rTaGhoGPYDNtmMtY1ve/nll+PrX/96rFu3Lo45ZlL+zcgh/OIXv4hnnnkm7r777mqXUlF79+6Nb3/723HrrbdWu5QRq1pw/fCHPzzsc6eeemq8/PLLcdppp8XLL78cp5xyykH7PPTQQ/GRj3wkTjzxxIiIuOCCC+Kpp56aVME11jbW1tbGhz70oairq4uIiAULFsQf/vCH8Sp3VMbaxqeeeiqefPLJ+NnPfhavv/567NmzJ0444YS44YYbxrHqkRlrGyPemnxyzTXXxPXXXx/nnHPO+BRaIYVCYdiwWG9vbxQKhYP2+cc//hG1tbUxODgY/f39k37B1v2V08aIiEcffTR+8IMfxN133x2zZs2ayBLH7GhtfP311+NPf/pTXH755RER8c9//jO+8pWvxIYNG6K+vn7C6x2JSflnX7FYjPvuuy8iIu67775YsGDBQfu8973vjccffzwGBwdjz5498fjjj6caKiynjfX19fGf//xn3/WQbdu2xdlnnz2RZY5JOW38zne+E4888kh0dXXFjTfeGEuXLp1UoXU05bRxYGAgvvrVr8aSJUvi05/+9ARXOHL19fWxc+fO2LVrVwwMDERHR0cUi8Vh+xSLxbj33nsj4q0Zaeeee+4Re5uTTTltfPbZZ2P16tWxYcOGOPXUU6tU6egdrY01NTWxbdu26Orqiq6urjjnnHNShFbEJA2uq6++On7729/GhRdeGI8++mhcffXVERHx9NNPxze+8Y2IeOuC8JlnnhmLFy+OJUuWxAc/+MGDTrzJrJw2zpw5M2688ca44oorYvHixVEqlSbVMOHRlNPG7Mpp4y9/+ct44okn4t57740lS5bEkiVL4rnnnqtm2Ud07LHHxurVq2P58uVx8cUXx0UXXRRz5syJO+64Y9/F/UsvvTReffXVaGpqirvuuivVHxsR5bXxtttuizfeeCOuvfbaWLJkSXz5y1+uctUjU04bs7LkEwCpTMoeFwAcjuACIBXBBUAqgguAVAQXAKkILgBSEVwApPJ/1S9gIyX8V20AAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import numpy as np\n", + "from matplotlib import pyplot as plt\n", + "\n", + "w = ae_wo_classifier.layers[1].weights[0].numpy()\n", + "h, b = np.histogram(w, bins=100)\n", + "plt.figure(figsize=(7,7))\n", + "plt.bar(b[:-1], h, width=b[1]-b[0])\n", + "plt.semilogy()\n", + "print('% of zeros = {}'.format(np.sum(w==00)/np.size(w)))" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "ename": "ImportError", + "evalue": "cannot import name 'makeRoc' from 'plotting' (C:\\Users\\loren\\miniconda3\\envs\\MLinPhysics\\lib\\site-packages\\plotting\\__init__.py)", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mImportError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mplotting\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mplotting\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mmakeRoc\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mmatplotlib\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpyplot\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mplt\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0msklearn\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmetrics\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0maccuracy_score\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mtensorflow\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mkeras\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmodels\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mload_model\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;31mImportError\u001b[0m: cannot import name 'makeRoc' from 'plotting' (C:\\Users\\loren\\miniconda3\\envs\\MLinPhysics\\lib\\site-packages\\plotting\\__init__.py)" + ] + } + ], + "source": [ + "import plotting\n", + "from plotting import makeRoc\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.metrics import accuracy_score\n", + "from tensorflow.keras.models import load_model\n", + "model_ref = load_model('model/AE_model/KERAS_check_best_model.h5')\n", + "\n", + "import MNIST_dataset as mnist\n", + "size_final = 10\n", + "\n", + "data_zoom = mnist.MNISTData(size_final=size_final, color_depth=5)\n", + "\n", + "y_ref = model_ref.predict(data_zoom.x_test)\n", + "y_prune = ae_wo_classifier.predict(data_zoom.x_test)\n", + "y_test = data_zoom.y_test\n", + "print(\"Accuracy unpruned: {}\".format(accuracy_score(np.argmax(y_test, axis=1), np.argmax(y_ref, axis=1))))\n", + "print(\"Accuracy pruned: {}\".format(accuracy_score(np.argmax(y_test, axis=1), np.argmax(y_prune, axis=1))))\n", + "\n", + "fig, ax = plt.subplots(figsize=(9, 9))\n", + "_ = makeRoc(y_test, y_ref, classes)\n", + "plt.gca().set_prop_cycle(None) # reset the colors\n", + "_ = plotting.makeRoc(y_test, y_prune, classes, linestyle='--')\n", + "\n", + "from matplotlib.lines import Line2D\n", + "lines = [Line2D([0], [0], ls='-'),\n", + " Line2D([0], [0], ls='--')]\n", + "from matplotlib.legend import Legend\n", + "leg = Legend(ax, lines, labels=['unpruned', 'pruned'],\n", + " loc='lower right', frameon=False)\n", + "ax.add_artist(leg)" + ] + }, { "cell_type": "markdown", "metadata": {}, diff --git a/images/AE/Accuracy of Autoencoder without classifier.png b/images/AE/Accuracy of Autoencoder without classifier.png index ff57445..7406459 100644 Binary files a/images/AE/Accuracy of Autoencoder without classifier.png and b/images/AE/Accuracy of Autoencoder without classifier.png differ diff --git a/images/AE/Latent dimension of Autoencoder without classifier.png b/images/AE/Latent dimension of Autoencoder without classifier.png index f8a5372..9b4398f 100644 Binary files a/images/AE/Latent dimension of Autoencoder without classifier.png and b/images/AE/Latent dimension of Autoencoder without classifier.png differ diff --git a/images/AE/reconstructed images.png b/images/AE/reconstructed images.png index c1e529c..c3fe391 100644 Binary files a/images/AE/reconstructed images.png and b/images/AE/reconstructed images.png differ diff --git a/model/AE_model/KERAS_check_model_w_classifier.h5 b/model/AE_model/KERAS_check_model_w_classifier.h5 index 3d6b50b..0d5836d 100644 Binary files a/model/AE_model/KERAS_check_model_w_classifier.h5 and b/model/AE_model/KERAS_check_model_w_classifier.h5 differ diff --git a/model/AE_model/KERAS_check_model_wo_classifier.h5 b/model/AE_model/KERAS_check_model_wo_classifier.h5 index 5c0d940..21846ac 100644 Binary files a/model/AE_model/KERAS_check_model_wo_classifier.h5 and b/model/AE_model/KERAS_check_model_wo_classifier.h5 differ diff --git a/model/AE_model/hls4ml_prj/build_lib.sh b/model/AE_model/hls4ml_prj/build_lib.sh deleted file mode 100644 index 9ee0411..0000000 --- a/model/AE_model/hls4ml_prj/build_lib.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -CC=g++ -if [[ "$OSTYPE" == "linux-gnu" ]]; then - CFLAGS="-O3 -fPIC -std=c++11 -fno-gnu-unique" -elif [[ "$OSTYPE" == "darwin"* ]]; then - CFLAGS="-O3 -fPIC -std=c++11" -fi -LDFLAGS= -INCFLAGS="-Ifirmware/ap_types/" -PROJECT=myproject -LIB_STAMP=fEe86a0b - -${CC} ${CFLAGS} ${INCFLAGS} -c firmware/${PROJECT}.cpp -o ${PROJECT}.o -${CC} ${CFLAGS} ${INCFLAGS} -c ${PROJECT}_bridge.cpp -o ${PROJECT}_bridge.o -${CC} ${CFLAGS} ${INCFLAGS} -shared ${PROJECT}.o ${PROJECT}_bridge.o -o firmware/${PROJECT}-${LIB_STAMP}.so -rm -f *.o \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/build_prj.tcl b/model/AE_model/hls4ml_prj/build_prj.tcl deleted file mode 100644 index c82ef94..0000000 --- a/model/AE_model/hls4ml_prj/build_prj.tcl +++ /dev/null @@ -1,134 +0,0 @@ -################# -# HLS4ML -################# -array set opt { - reset 0 - csim 1 - synth 1 - cosim 1 - validation 1 - export 0 - vsynth 0 -} - -foreach arg $::argv { - foreach o [lsort [array names opt]] { - regexp "$o=+(\\w+)" $arg unused opt($o) - } -} - -proc report_time { op_name time_start time_end } { - set time_taken [expr $time_end - $time_start] - set time_s [expr ($time_taken / 1000) % 60] - set time_m [expr ($time_taken / (1000*60)) % 60] - set time_h [expr ($time_taken / (1000*60*60)) % 24] - puts "***** ${op_name} COMPLETED IN ${time_h}h${time_m}m${time_s}s *****" -} - -# Compare file content: 1 = same, 0 = different -proc compare_files {file_1 file_2} { - # Check if files exist, error otherwise - if {! ([file exists $file_1] && [file exists $file_2])} { - return 0 - } - # Files with different sizes are obviously different - if {[file size $file_1] != [file size $file_2]} { - return 0 - } - - # String compare the content of the files - set fh_1 [open $file_1 r] - set fh_2 [open $file_2 r] - set equal [string equal [read $fh_1] [read $fh_2]] - close $fh_1 - close $fh_2 - return $equal -} - -file mkdir tb_data -set CSIM_RESULTS "./tb_data/csim_results.log" -set RTL_COSIM_RESULTS "./tb_data/rtl_cosim_results.log" - -if {$opt(reset)} { - open_project -reset myproject_prj -} else { - open_project myproject_prj -} -set_top myproject -add_files firmware/myproject.cpp -cflags "-std=c++0x" -add_files -tb myproject_test.cpp -cflags "-std=c++0x" -add_files -tb firmware/weights -add_files -tb tb_data -if {$opt(reset)} { - open_solution -reset "solution1" -} else { - open_solution "solution1" -} -catch {config_array_partition -maximum_size 4096} -config_compile -name_max_length 60 -set_part {xcu250-figd2104-2L-e} -create_clock -period 5 -name default - - -if {$opt(csim)} { - puts "***** C SIMULATION *****" - set time_start [clock clicks -milliseconds] - csim_design - set time_end [clock clicks -milliseconds] - report_time "C SIMULATION" $time_start $time_end -} - -if {$opt(synth)} { - puts "***** C/RTL SYNTHESIS *****" - set time_start [clock clicks -milliseconds] - csynth_design - set time_end [clock clicks -milliseconds] - report_time "C/RTL SYNTHESIS" $time_start $time_end -} - -if {$opt(cosim)} { - puts "***** C/RTL SIMULATION *****" - # TODO: This is a workaround (Xilinx defines __RTL_SIMULATION__ only for SystemC testbenches). - add_files -tb myproject_test.cpp -cflags "-std=c++0x -DRTL_SIM" - set time_start [clock clicks -milliseconds] - cosim_design -trace_level all - set time_end [clock clicks -milliseconds] - puts "INFO:" - puts [read [open myproject_prj/solution1/sim/report/myproject_cosim.rpt r]] - report_time "C/RTL SIMULATION" $time_start $time_end -} - -if {$opt(validation)} { - puts "***** C/RTL VALIDATION *****" - if {[compare_files $CSIM_RESULTS $RTL_COSIM_RESULTS]} { - puts "INFO: Test PASSED" - } else { - puts "ERROR: Test failed" - puts "ERROR: - csim log: $CSIM_RESULTS" - puts "ERROR: - RTL-cosim log: $RTL_COSIM_RESULTS" - exit 1 - } -} - -if {$opt(export)} { - puts "***** EXPORT IP *****" - set time_start [clock clicks -milliseconds] - export_design -format ip_catalog - set time_end [clock clicks -milliseconds] - report_time "EXPORT IP" $time_start $time_end -} - -if {$opt(vsynth)} { - puts "***** VIVADO SYNTHESIS *****" - if {[file exist myproject_prj/solution1/syn/vhdl]} { - set time_start [clock clicks -milliseconds] - exec vivado -mode batch -source vivado_synth.tcl >@ stdout - set time_end [clock clicks -milliseconds] - report_time "VIVADO SYNTHESIS" $time_start $time_end - } else { - puts "ERROR: Cannot find generated VHDL files. Did you run C synthesis?" - exit 1 - } -} - -exit diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_common.h b/model/AE_model/hls4ml_prj/firmware/ap_types/ap_common.h deleted file mode 100644 index 4d2886c..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_common.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright 2011-2019 Xilinx, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AP_COMMON_H__ -#define __AP_COMMON_H__ - -// ---------------------------------------------------------------------- - -// Forward declaration of all AP types. -#include - - -#ifdef __SYNTHESIS__ -#error "The open-source version of AP types does not support synthesis." -#endif // ifdef __SYNTHESIS__ -#define _AP_ENABLE_HALF_ 0 - - -#if _AP_ENABLE_HALF_ == 1 -// Before ap_private definition. -#ifdef __SYNTHESIS__ -#define _HLS_HALF_DEFINED_ -typedef __fp16 half; -#else -class half; -#endif // __SYNTHESIS__ -#endif // _AP_ENABLE_HALF_ - -// ---------------------------------------------------------------------- - -// Macro functions -#define AP_MAX(a, b) ((a) > (b) ? (a) : (b)) -#define AP_MIN(a, b) ((a) < (b) ? (a) : (b)) -#define AP_ABS(a) ((a) >= 0 ? (a) : -(a)) - -#ifndef AP_ASSERT -#ifndef __SYNTHESIS__ -#include -#define AP_ASSERT(cond, msg) assert((cond) && (msg)) -#else -#define AP_ASSERT(cond, msg) -#endif // ifndef __SYNTHESIS__ -#endif // ifndef AP_ASSERT - -#ifndef __SYNTHESIS__ -// for fprintf messages. -#include -// for exit on error. -#include -#endif - -// same disable condition as assert. -#if !defined(__SYNTHESIS__) && !defined(NDEBUG) - -#define _AP_DEBUG(cond, ...) \ - do { \ - if ((cond)) { \ - fprintf(stderr, "DEBUG: " __VA_ARGS__); \ - fprintf(stderr, "\n"); \ - } \ - } while (0) -#define _AP_WARNING(cond, ...) \ - do { \ - if ((cond)) { \ - fprintf(stderr, "WARNING: " __VA_ARGS__); \ - fprintf(stderr, "\n"); \ - } \ - } while (0) -#define _AP_ERROR(cond, ...) \ - do { \ - if ((cond)) { \ - fprintf(stderr, "ERROR: " __VA_ARGS__); \ - fprintf(stderr, "\n"); \ - abort(); \ - } \ - } while (0) - -#else // if !defined(__SYNTHESIS__) && !defined(NDEBUG) - -#define __AP_VOID_CAST static_cast -#define _AP_DEBUG(cond, ...) (__AP_VOID_CAST(0)) -#define _AP_WARNING(cond, ...) (__AP_VOID_CAST(0)) -#define _AP_ERROR(cond, ...) (__AP_VOID_CAST(0)) - -#endif // if !defined(__SYNTHESIS__) && !defined(NDEBUG) else - -// ---------------------------------------------------------------------- - -// Attribute only for synthesis -#ifdef __SYNTHESIS__ -#define INLINE inline __attribute__((always_inline)) -//#define INLINE inline __attribute__((noinline)) -#else -#define INLINE inline -#endif - -#define AP_WEAK -// __attribute__((weak)) - -#ifndef AP_INT_MAX_W -#define AP_INT_MAX_W 1024 -#endif - -#define BIT_WIDTH_UPPER_LIMIT (1 << 15) -#if AP_INT_MAX_W > BIT_WIDTH_UPPER_LIMIT -#error "Bitwidth exceeds 32768 (1 << 15), the maximum allowed value" -#endif - -#define MAX_MODE(BITS) ((BITS + 1023) / 1024) - -// ---------------------------------------------------------------------- - -// XXX apcc cannot handle global std::ios_base::Init() brought in by -#ifndef AP_AUTOCC -#ifndef __SYNTHESIS__ -// for overload operator<< -#include -#endif -#endif // ifndef AP_AUTOCC - -#ifndef __SYNTHESIS__ -// for string format. -#include -// for string. -#include -#endif - -// for detecting if char is signed. -enum { CHAR_IS_SIGNED = (char)-1 < 0 }; - -// TODO we have similar traits in x_hls_utils.h, should consider unify. -namespace _ap_type { -template -struct is_signed { - static const bool value = _Tp(-1) < _Tp(1); -}; - -template -struct is_integral { - static const bool value = false; -}; -#define DEF_IS_INTEGRAL(CTYPE) \ - template <> \ - struct is_integral { \ - static const bool value = true; \ - }; -DEF_IS_INTEGRAL(bool) -DEF_IS_INTEGRAL(char) -DEF_IS_INTEGRAL(signed char) -DEF_IS_INTEGRAL(unsigned char) -DEF_IS_INTEGRAL(short) -DEF_IS_INTEGRAL(unsigned short) -DEF_IS_INTEGRAL(int) -DEF_IS_INTEGRAL(unsigned int) -DEF_IS_INTEGRAL(long) -DEF_IS_INTEGRAL(unsigned long) -DEF_IS_INTEGRAL(ap_slong) -DEF_IS_INTEGRAL(ap_ulong) -#undef DEF_IS_INTEGRAL - -template -struct enable_if {}; -// partial specialization for true -template -struct enable_if { - typedef _Tp type; -}; - -template -struct remove_const { - typedef _Tp type; -}; - -template -struct remove_const<_Tp const> { - typedef _Tp type; -}; -} // namespace _ap_type - -// ---------------------------------------------------------------------- - -// Define ssdm_int and _ssdm_op. -// XXX deleted in open-source version - -#ifndef NON_C99STRING -#define _AP_C99 true -#else -#define _AP_C99 false -#endif - -static inline unsigned char guess_radix(const char* s) { - unsigned char rd = 10; ///< default radix - const char* p = s; - // skip neg sign if it exists - if (p[0] == '-' || p[0] == '+') ++p; - // guess based on following two bits. - if (p[0] == '0') { - if (p[1] == 'b' || p[1] == 'B') { - rd = 2; - } else if (p[1] == 'o' || p[1] == 'O') { - rd = 8; - } else if (p[1] == 'x' || p[1] == 'X') { - rd = 16; - } else if (p[1] == 'd' || p[1] == 'D') { - rd = 10; - } - } - return rd; -} - -// ---------------------------------------------------------------------- - -// Basic integral struct upon which ap_int and ap_fixed are defined. -#ifdef __SYNTHESIS__ -// Use ssdm_int, a compiler dependent, attribute constrained integeral type as -// basic data type. -#define _AP_ROOT_TYPE ssdm_int -// Basic ops. -#define _AP_ROOT_op_concat(Ret, X, Y) _ssdm_op_concat(Ret, X, Y) -#define _AP_ROOT_op_get_bit(Val, Bit) _ssdm_op_get_bit(Val, Bit) -#define _AP_ROOT_op_set_bit(Val, Bit, Repl) _ssdm_op_set_bit(Val, Bit, Repl) -#define _AP_ROOT_op_get_range(Val, Lo, Hi) _ssdm_op_get_range(Val, Lo, Hi) -#define _AP_ROOT_op_set_range(Val, Lo, Hi, Repl) \ - _ssdm_op_set_range(Val, Lo, Hi, Repl) -#define _AP_ROOT_op_reduce(Op, Val) _ssdm_op_reduce(Op, Val) -#else // ifdef __SYNTHESIS__ -// Use ap_private for compiler-independent basic data type -template -class ap_private; -/// model ssdm_int in standard C++ for simulation. -template -struct ssdm_int_sim { - /// integral type with template-specified width and signedness. - ap_private<_AP_W, _AP_S> V; - ssdm_int_sim() {} -}; -#define _AP_ROOT_TYPE ssdm_int_sim -// private's ref uses _AP_ROOT_TYPE. -#include -// XXX The C-sim model cannot use GCC-extension -// Basic ops. Ret and Val are ap_private. -template -inline _Tp1 _AP_ROOT_op_concat(const _Tp1& Ret, const _Tp2& X, const _Tp3& Y) { - _Tp1 r = (X).operator,(Y); - return r; -} -#define _AP_ROOT_op_get_bit(Val, Bit) (Val).get_bit((Bit)) -template -inline _Tp1& _AP_ROOT_op_set_bit(_Tp1& Val, const _Tp2& Bit, const _Tp3& Repl) { - (Val).set_bit((Bit), (Repl)); - return Val; -} -// notice the order of high and low index is different in ssdm call and -// ap_private.range()... -#define _AP_ROOT_op_get_range(Val, Lo, Hi) (Val).range((Hi), (Lo)) -template -inline _Tp1& _AP_ROOT_op_set_range(_Tp1& Val, const _Tp2& Lo, const _Tp3& Hi, - const _Tp4& Repl) { - (Val).range((Hi), (Lo)) = Repl; - return (Val); -} -#define _AP_ROOT_op_and_reduce(Val) (Val).and_reduce() -#define _AP_ROOT_op_nand_reduce(Val) (Val).nand_reduce() -#define _AP_ROOT_op_or_reduce(Val) (Val).or_reduce() -#define _AP_ROOT_op_xor_reduce(Val) (Val).xor_reduce() -// ## is the concatenation in preprocessor: -#define _AP_ROOT_op_reduce(Op, Val) _AP_ROOT_op_##Op##_reduce(Val) -#endif // ifdef __SYNTHESIS__ else - -// ---------------------------------------------------------------------- - -// Constants for half, single, double pricision floating points -#define HALF_MAN 10 -#define FLOAT_MAN 23 -#define DOUBLE_MAN 52 - -#define HALF_EXP 5 -#define FLOAT_EXP 8 -#define DOUBLE_EXP 11 - -#define BIAS(e) ((1L << (e - 1L)) - 1L) -#define HALF_BIAS BIAS(HALF_EXP) -#define FLOAT_BIAS BIAS(FLOAT_EXP) -#define DOUBLE_BIAS BIAS(DOUBLE_EXP) - -#define APFX_IEEE_DOUBLE_E_MAX DOUBLE_BIAS -#define APFX_IEEE_DOUBLE_E_MIN (-DOUBLE_BIAS + 1) - -INLINE ap_ulong doubleToRawBits(double pf) { - union { - ap_ulong __L; - double __D; - } LD; - LD.__D = pf; - return LD.__L; -} - -INLINE unsigned int floatToRawBits(float pf) { - union { - unsigned int __L; - float __D; - } LD; - LD.__D = pf; - return LD.__L; -} - -#if _AP_ENABLE_HALF_ == 1 -INLINE unsigned short halfToRawBits(half pf) { -#ifdef __SYNTHESIS__ - union { - unsigned short __L; - half __D; - } LD; - LD.__D = pf; - return LD.__L; -#else - return pf.get_bits(); -#endif -} -#endif - -// usigned long long is at least 64-bit -INLINE double rawBitsToDouble(ap_ulong pi) { - union { - ap_ulong __L; - double __D; - } LD; - LD.__L = pi; - return LD.__D; -} - -// long is at least 32-bit -INLINE float rawBitsToFloat(unsigned long pi) { - union { - unsigned int __L; - float __D; - } LD; - LD.__L = pi; - return LD.__D; -} - -#if _AP_ENABLE_HALF_ == 1 -// short is at least 16-bit -INLINE half rawBitsToHalf(unsigned short pi) { -#ifdef __SYNTHESIS__ - union { - unsigned short __L; - half __D; - } LD; - LD.__L = pi; - return LD.__D; -#else - // sim model of half has a non-trivial constructor - half __D; - __D.set_bits(pi); - return __D; -#endif -} -#endif - -#endif // ifndef __AP_COMMON_H__ - -// -*- cpp -*- diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_decl.h b/model/AE_model/hls4ml_prj/firmware/ap_types/ap_decl.h deleted file mode 100644 index ddd00f1..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_decl.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2011-2019 Xilinx, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AP_DECL_H__ -#define __AP_DECL_H__ - -// ---------------------------------------------------------------------- - -#if !defined(__AP_FIXED_H__) && !defined(__AP_INT_H__) && !defined(__AUTOPILOT_CBE_H__) && !defined(__HLS_HALF_H__) -#error "Only ap_fixed.h and ap_int.h can be included directly in user code." -#endif - -// Test __SYNTHESIS__ only for mode -#if !defined(__SYNTHESIS__) && (defined(AESL_SYN) || defined(__HLS_SYN__)) -//#pragma message "AESL_SYN and __HLS_SYN__ should be replaced by __SYNTHESIS__" -#define __SYNTHESIS__ -#endif - -/* for safety*/ -#if (defined(_AP_N) || defined(_AP_C)) -#error One or more of the following is defined: _AP_N, _AP_C. Definition conflicts with their usage as template parameters. -#endif - -/* for safety*/ -#if (defined(_AP_W) || defined(_AP_I) || defined(_AP_S) || defined(_AP_Q) || \ - defined(_AP_O) || defined(_AP_W2) || defined(_AP_I2) || \ - defined(_AP_S2) || defined(_AP_Q2) || defined(_AP_O2) || \ - defined(_AP_N) || defined(_AP_N2)) -#error \ - "One or more of the following is defined: _AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N, _AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2. Definition conflicts with their usage as template parameters." -#endif - -/*for safety*/ -#if (defined(_AP_W3) || defined(_AP_S3) || defined(_AP_W4) || defined(_AP_S4)) -#error \ - "One or more of the following is defined: _AP_W3, _AP_S3, _AP_W4,_AP_S4. Definition conflicts with their usage as template parameters." -#endif - -#if (defined(_AP_W1) || defined(_AP_S1) || defined(_AP_T) || \ - defined(_AP_T1) || defined(_AP_T2) || defined(_AP_T3) || defined(_AP_T4)) -#error \ - "One or more of the following is defined: _AP_W1, _AP_S1, _AP_T, _AP_T1, _AP_T2, _AP_T3, _AP_T4. Definition conflicts with their usage as template parameters." -#endif - -#ifndef __cplusplus -#error "AP data type can only be used in C++" -#endif - -// ---------------------------------------------------------------------- - -#ifndef __SC_COMPATIBLE__ -/// ap_fixed quantification mode -enum ap_q_mode { - AP_RND, //< rounding to plus infinity - AP_RND_ZERO, //< rounding to zero - AP_RND_MIN_INF, //< rounding to minus infinity - AP_RND_INF, //< rounding to infinity - AP_RND_CONV, //< convergent rounding - AP_TRN, //< truncation - AP_TRN_ZERO, //< truncation to zero -}; - -// FIXME for legacy code -#ifndef SYSTEMC_INCLUDED -#define SC_RND AP_RND -#define SC_RND_ZERO AP_RND_ZERO -#define SC_RND_MIN_INF AP_RND_MIN_INF -#define SC_RND_INF AP_RND_INF -#define SC_RND_CONV AP_RND_CONV -#define SC_TRN AP_TRN -#define SC_TRN_ZERO AP_TRN_ZERO -#endif // !defined(SYSTEMC_INCLUDED) - -/// ap_fixed saturation mode -enum ap_o_mode { - AP_SAT, //< saturation - AP_SAT_ZERO, //< saturation to zero - AP_SAT_SYM, //< symmetrical saturation - AP_WRAP, //< wrap-around (*) - AP_WRAP_SM, //< sign magnitude wrap-around (*) -}; - -// FIXME for legacy code -#ifndef SYSTEMC_INCLUDED -#define SC_SAT AP_SAT -#define SC_SAT_ZERO AP_SAT_ZERO -#define SC_SAT_SYM AP_SAT_SYM -#define SC_WRAP AP_WRAP -#define SC_WRAP_SM AP_WRAP_SM -#endif // !defined(SYSTEMC_INCLUDED) - -#else // defined(__SC_COMPATIBLE__) - -// There will not be sc_fxdefs.h, and the emu should be defined by ap_fixed. - -/// ap_fixed quantification mode -enum ap_q_mode { - SC_RND, //< rounding to plus infinity - SC_RND_ZERO, //< rounding to zero - SC_RND_MIN_INF, //< rounding to minus infinity - SC_RND_INF, //< rounding to infinity - SC_RND_CONV, //< convergent rounding - SC_TRN, //< truncation - SC_TRN_ZERO, //< truncation to zero -}; - -#define AP_RND SC_RND -#define AP_RND_ZERO SC_RND_ZERO -#define AP_RND_MIN_INF SC_RND_MIN_INF -#define AP_RND_INF SC_RND_INF -#define AP_RND_CONV SC_RND_CONV -#define AP_TRN SC_TRN -#define AP_TRN_ZERO SC_TRN_ZERO - -/// ap_fixed saturation mode -enum ap_o_mode { - SC_SAT, //< saturation - SC_SAT_ZERO, //< saturation to zero - SC_SAT_SYM, //< symmetrical saturation - SC_WRAP, //< wrap-around (*) - SC_WRAP_SM, //< sign magnitude wrap-around (*) -}; - -#define AP_SAT SC_SAT -#define AP_SAT_ZERO SC_SAT_ZERO -#define AP_SAT_SYM SC_SAT_SYM -#define AP_WRAP SC_WRAP -#define AP_WRAP_SM SC_WRAP_SM - -#endif // defined(__SC_COMPATIBLE__) - -template -struct ap_int_base; - -template -struct ap_int; - -template -struct ap_uint; - -template -struct ap_range_ref; - -template -struct ap_bit_ref; - -template -struct ap_concat_ref; - -template -struct ap_fixed_base; - -template -struct ap_fixed; - -template -struct ap_ufixed; - -template -struct af_range_ref; - -template -struct af_bit_ref; - -/// string base mode -enum BaseMode { AP_BIN = 2, AP_OCT = 8, AP_DEC = 10, AP_HEX = 16 }; - -#ifndef SYSTEMC_INCLUDED -#define SC_BIN 2 -#define SC_OCT 8 -#define SC_DEC 10 -#define SC_HEX 16 -#endif // !defined(SYSTEMC_INCLUDED) - -// Alias C data types -#ifdef _MSC_VER -typedef signed __int64 ap_slong; -typedef unsigned __int64 ap_ulong; -#else // !defined(_MSC_VER) -typedef signed long long ap_slong; -typedef unsigned long long ap_ulong; -#endif // !defined(_MSC_VER) - -enum { - _AP_SIZE_char = 8, - _AP_SIZE_short = sizeof(short) * 8, - _AP_SIZE_int = sizeof(int) * 8, - _AP_SIZE_long = sizeof(long) * 8, - _AP_SIZE_ap_slong = sizeof(ap_slong) * 8 -}; - -#endif // !defined(__AP_DECL_H__) - -// -*- cpp -*- diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_fixed.h b/model/AE_model/hls4ml_prj/firmware/ap_types/ap_fixed.h deleted file mode 100644 index cd0192b..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_fixed.h +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright 2011-2019 Xilinx, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AP_FIXED_H__ -#define __AP_FIXED_H__ - -#include -#include -#include - -//--------------------------------------------------------------- - -/// Signed Arbitrary Precision Fixed-Point Type. -// default for _AP_Q, _AP_O and _AP_N set in ap_decl.h -template -struct ap_fixed : ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> { - typedef ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> Base; - // Constructor - /// default ctor - INLINE ap_fixed() : Base() {} - - /// default copy ctor - INLINE ap_fixed(const ap_fixed& op) { Base::V = op.V; } - - /// copy ctor from ap_fixed_base. - template - INLINE ap_fixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, - _AP_O2, _AP_N2>& op) - : Base(op) {} - - template - INLINE ap_fixed(const volatile ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, - _AP_O2, _AP_N2>& op) - : Base(op) {} - - //// from ap_fixed - //template - //INLINE ap_fixed( - // const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - // : Base(ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} - - //template - //INLINE ap_fixed( - // const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - // : Base(ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} - - //// from ap_ufixed. - //template - //INLINE ap_fixed( - // const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - // : Base(ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>(op)) { - //} - - //template - //INLINE ap_fixed( - // const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - // : Base(ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>(op)) { - //} - - /// copy ctor from ap_int_base. - template - INLINE ap_fixed(const ap_int_base<_AP_W2, _AP_S2>& op) : Base(op) {} - - template - INLINE ap_fixed(const volatile ap_int_base<_AP_W2, _AP_S2>& op) : Base(op) {} - - //// from ap_int. - //template - //INLINE ap_fixed(const ap_int<_AP_W2>& op) - // : Base(ap_int_base<_AP_W2, true>(op)) {} - - //template - //INLINE ap_fixed(const volatile ap_int<_AP_W2>& op) - // : Base(ap_int_base<_AP_W2, true>(op)) {} - - //// from ap_uint. - //template - //INLINE ap_fixed(const ap_uint<_AP_W2>& op) - // : Base(ap_int_base<_AP_W2, false>(op)) {} - - //template - //INLINE ap_fixed(const volatile ap_uint<_AP_W2>& op) - // : Base(ap_int_base<_AP_W2, false>(op)) {} - - // from ap_bit_ref. - template - INLINE ap_fixed(const ap_bit_ref<_AP_W2, _AP_S2>& op) : Base(op) {} - - // from ap_range_ref. - template - INLINE ap_fixed(const ap_range_ref<_AP_W2, _AP_S2>& op) : Base(op) {} - - // from ap_concat_ref. - template - INLINE ap_fixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) - : Base(op) {} - - // from af_bit_ref. - template - INLINE ap_fixed( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base(op) {} - - // from af_range_ref. - template - INLINE ap_fixed( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base(op) {} - -// from c types. -#define CTOR(TYPE) \ - INLINE ap_fixed(TYPE v) : Base(v) {} - - CTOR(bool) - CTOR(char) - CTOR(signed char) - CTOR(unsigned char) - CTOR(short) - CTOR(unsigned short) - CTOR(int) - CTOR(unsigned int) - CTOR(long) - CTOR(unsigned long) - CTOR(ap_slong) - CTOR(ap_ulong) -#if _AP_ENABLE_HALF_ == 1 - CTOR(half) -#endif - CTOR(float) - CTOR(double) -#undef CTOR - - INLINE ap_fixed(const char* s) : Base(s) {} - - INLINE ap_fixed(const char* s, signed char rd) : Base(s, rd) {} - - // Assignment - // The assignment operator is technically inherited; however, it is always - // hidden by an explicitly or implicitly defined assignment operator for the - // derived class. - /* XXX ctor will be used when right is not of proper type. */ - INLINE ap_fixed& operator=( - const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) { - Base::V = op.V; - return *this; - } - - INLINE void operator=( - const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) volatile { - Base::V = op.V; - } - - INLINE ap_fixed& operator=( - const volatile ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) { - Base::V = op.V; - return *this; - } - - INLINE void operator=( - const volatile ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) volatile { - Base::V = op.V; - } -}; // struct ap_fixed. - -//------------------------------------------------------------------- - -// Unsigned Arbitrary Precision Fixed-Point Type. -// default for _AP_Q, _AP_O and _AP_N set in ap_decl.h -template -struct ap_ufixed : ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> { - typedef ap_fixed_base<_AP_W, _AP_I, false, _AP_Q, _AP_O, _AP_N> Base; - // Constructor - /// default ctor - INLINE ap_ufixed() : Base() {} - - /// default copy ctor - INLINE ap_ufixed(const ap_ufixed& op) { Base::V = op.V; } - - /// copy ctor from ap_fixed_base - template - INLINE ap_ufixed(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, - _AP_O2, _AP_N2>& op) - : Base(op) {} - - /// copy ctor from ap_fixed_base - template - INLINE ap_ufixed(const volatile ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, - _AP_O2, _AP_N2>& op) - : Base(op) {} - - //template - //INLINE ap_ufixed( - // const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - // : Base(ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} - - //template - //INLINE ap_ufixed( - // const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - // : Base(ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>(op)) {} - - //template - //INLINE ap_ufixed( - // const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - // : Base(ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>(op)) { - //} - - //template - //INLINE ap_ufixed( - // const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - // : Base(ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>(op)) { - //} - - /// copy ctor from ap_int_base. - template - INLINE ap_ufixed(const ap_int_base<_AP_W2, _AP_S2>& op) : Base(op) {} - - template - INLINE ap_ufixed(const volatile ap_int_base<_AP_W2, _AP_S2>& op) : Base(op) {} - - //template - //INLINE ap_ufixed(const ap_int<_AP_W2>& op) - // : Base(ap_int_base<_AP_W2, true>(op)) {} - - //template - //INLINE ap_ufixed(const volatile ap_int<_AP_W2>& op) - // : Base(ap_int_base<_AP_W2, true>(op)) {} - - //template - //INLINE ap_ufixed(const ap_uint<_AP_W2>& op) - // : Base(ap_int_base<_AP_W2, false>(op)) {} - - //template - //INLINE ap_ufixed(const volatile ap_uint<_AP_W2>& op) - // : Base(ap_int_base<_AP_W2, false>(op)) {} - - template - INLINE ap_ufixed(const ap_bit_ref<_AP_W2, _AP_S2>& op) : Base(op) {} - - template - INLINE ap_ufixed(const ap_range_ref<_AP_W2, _AP_S2>& op) : Base(op) {} - - template - INLINE ap_ufixed(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) - : Base(op) {} - - template - INLINE ap_ufixed( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base(op) {} - - template - INLINE ap_ufixed( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base(op) {} - -#define CTOR(TYPE) \ - INLINE ap_ufixed(TYPE v) : Base(v) {} - - CTOR(bool) - CTOR(char) - CTOR(signed char) - CTOR(unsigned char) - CTOR(short) - CTOR(unsigned short) - CTOR(int) - CTOR(unsigned int) - CTOR(long) - CTOR(unsigned long) - CTOR(ap_slong) - CTOR(ap_ulong) -#if _AP_ENABLE_HALF_ == 1 - CTOR(half) -#endif - CTOR(float) - CTOR(double) -#undef CTOR - - INLINE ap_ufixed(const char* s) : Base(s) {} - - INLINE ap_ufixed(const char* s, signed char rd) : Base(s, rd) {} - - // Assignment - INLINE ap_ufixed& operator=( - const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) { - Base::V = op.V; - return *this; - } - - INLINE void operator=( - const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) volatile { - Base::V = op.V; - } - - INLINE ap_ufixed& operator=( - const volatile ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op) { - Base::V = op.V; - return *this; - } - - INLINE void operator=(const volatile ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, - _AP_N>& op) volatile { - Base::V = op.V; - } -}; // struct ap_ufixed - - -#if !defined(__SYNTHESIS__) && (defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED)) -// XXX sc_trace overload for ap_fixed is already included in -// "ap_sysc/ap_sc_extras.h", so do not define in synthesis. -template -INLINE void sc_trace(sc_core::sc_trace_file* tf, - const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op, - const std::string& name) { - tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); -} - -template -INLINE void sc_trace(sc_core::sc_trace_file* tf, - const ap_ufixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N>& op, - const std::string& name) { - tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); -} -#endif // System C sim - -// Specialization of std containers, so that std::complex can have its -// image part automatically zero-initialized when only real part is provided. -#include - -#endif // ifndef __AP_FIXED_H__ - -// -*- cpp -*- diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_fixed_base.h b/model/AE_model/hls4ml_prj/firmware/ap_types/ap_fixed_base.h deleted file mode 100644 index 1d94b93..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_fixed_base.h +++ /dev/null @@ -1,2354 +0,0 @@ -/* - * Copyright 2011-2019 Xilinx, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AP_FIXED_BASE_H__ -#define __AP_FIXED_BASE_H__ - -#ifndef __AP_FIXED_H__ -#error "Only ap_fixed.h and ap_int.h can be included directly in user code." -#endif - -// for ap_int_base and its reference types. -#include -#ifndef __SYNTHESIS__ -#if _AP_ENABLE_HALF_ == 1 -// for half type -#include -#endif -// for std io -#include -#endif - -#ifndef __cplusplus -#error "C++ is required to include this header file" -#else // __cplusplus - -// for warning on unsupported rounding mode in conversion to float/double. -#if !defined(__SYNTHESIS__) && __cplusplus >= 201103L && \ - (defined(__gnu_linux__) || defined(_WIN32)) -#define AP_FIXED_ENABLE_CPP_FENV 1 -#include -#endif - -// ---------------------------------------------------------------------- - -/* Major TODO - long double support: constructor, assign and other operators. - binary operators with ap_fixed_base and const char*. - return ap_fixed/ap_ufixed when result signedness is known. -*/ - -// Helper function in conversion to floating point types. - -#ifdef __SYNTHESIS__ -#define _AP_ctype_op_get_bit(var, index) _AP_ROOT_op_get_bit(var, index) -#define _AP_ctype_op_set_bit(var, index, x) _AP_ROOT_op_set_bit(var, index, x) -#define _AP_ctype_op_get_range(var, low, high) \ - _AP_ROOT_op_get_range(var, low, high) -#define _AP_ctype_op_set_range(var, low, high, x) \ - _AP_ROOT_op_set_range(var, low, high, x) -#else // ifdef __SYNTHESIS__ -template -inline bool _AP_ctype_op_get_bit(_Tp1& var, const _Tp2& index) { - return !!(var & (1ull << (index))); -} -template -inline _Tp1 _AP_ctype_op_set_bit(_Tp1& var, const _Tp2& index, const _Tp3& x) { - var |= (((x) ? 1ull : 0ull) << (index)); - return var; -} -template -inline _Tp1 _AP_ctype_op_get_range(_Tp1& var, const _Tp2& low, - const _Tp3& high) { - _Tp1 r = var; - ap_ulong mask = -1ll; - mask >>= (sizeof(_Tp1) * 8 - ((high) - (low) + 1)); - r >>= (low); - r &= mask; - return r; -} -template -inline _Tp1 _AP_ctype_op_set_range(_Tp1& var, const _Tp2& low, const _Tp3& high, - const _Tp4& x) { - ap_ulong mask = -1ll; - mask >>= (_AP_SIZE_ap_slong - ((high) - (low) + 1)); - var &= ~(mask << (low)); - var |= ((mask & x) << (low)); - return var; -} -#endif // ifdef __SYNTHESIS__ - - -// trait for letting base class to return derived class. -// Notice that derived class template is incomplete, and we cannot use -// the member of the derived class. -template -struct _ap_fixed_factory; -template -struct _ap_fixed_factory<_AP_W2, _AP_I2, true> { - typedef ap_fixed<_AP_W2, _AP_I2> type; -}; -template -struct _ap_fixed_factory<_AP_W2, _AP_I2, false> { - typedef ap_ufixed<_AP_W2, _AP_I2> type; -}; - -/// ap_fixed_base: AutoPilot fixed point. -/** partial specialization of signed. - @tparam _AP_W width. - @tparam _AP_I integral part width. - @tparam _AP_S signed. - @tparam _AP_Q quantization mode. Default is AP_TRN. - @tparam _AP_O saturation mode. Default is AP_WRAP. - @tparam _AP_N saturation wrap value. Default is 0. - */ -// default for _AP_Q, _AP_O and _AP_N set in ap_decl.h -template -struct ap_fixed_base : _AP_ROOT_TYPE<_AP_W, _AP_S> { - public: - typedef _AP_ROOT_TYPE<_AP_W, _AP_S> Base; - static const int width = _AP_W; - static const int iwidth = _AP_I; - static const ap_q_mode qmode = _AP_Q; - static const ap_o_mode omode = _AP_O; - - /// Return type trait. - template - struct RType { - enum { - _AP_F = _AP_W - _AP_I, - F2 = _AP_W2 - _AP_I2, - mult_w = _AP_W + _AP_W2, - mult_i = _AP_I + _AP_I2, - mult_s = _AP_S || _AP_S2, - plus_w = AP_MAX(_AP_I + (_AP_S2 && !_AP_S), _AP_I2 + (_AP_S && !_AP_S2)) + - 1 + AP_MAX(_AP_F, F2), - plus_i = - AP_MAX(_AP_I + (_AP_S2 && !_AP_S), _AP_I2 + (_AP_S && !_AP_S2)) + 1, - plus_s = _AP_S || _AP_S2, - minus_w = - AP_MAX(_AP_I + (_AP_S2 && !_AP_S), _AP_I2 + (_AP_S && !_AP_S2)) + 1 + - AP_MAX(_AP_F, F2), - minus_i = - AP_MAX(_AP_I + (_AP_S2 && !_AP_S), _AP_I2 + (_AP_S && !_AP_S2)) + 1, - minus_s = true, -#ifndef __SC_COMPATIBLE__ - div_w = _AP_S2 + _AP_W + AP_MAX(F2, 0), -#else - div_w = _AP_S2 + _AP_W + AP_MAX(F2, 0) + AP_MAX(_AP_I2, 0), -#endif - div_i = _AP_S2 + _AP_I + F2, - div_s = _AP_S || _AP_S2, - logic_w = - AP_MAX(_AP_I + (_AP_S2 && !_AP_S), _AP_I2 + (_AP_S && !_AP_S2)) + - AP_MAX(_AP_F, F2), - logic_i = AP_MAX(_AP_I + (_AP_S2 && !_AP_S), _AP_I2 + (_AP_S && !_AP_S2)), - logic_s = _AP_S || _AP_S2 - }; - - typedef ap_fixed_base<_AP_W, _AP_I, _AP_S> lhs; - typedef ap_fixed_base<_AP_W2, _AP_I2, _AP_S2> rhs; - - typedef ap_fixed_base mult_base; - typedef ap_fixed_base plus_base; - typedef ap_fixed_base minus_base; - typedef ap_fixed_base logic_base; - typedef ap_fixed_base div_base; - typedef ap_fixed_base<_AP_W, _AP_I, _AP_S> arg1_base; - - typedef typename _ap_fixed_factory::type mult; - typedef typename _ap_fixed_factory::type plus; - typedef typename _ap_fixed_factory::type minus; - typedef typename _ap_fixed_factory::type logic; - typedef typename _ap_fixed_factory::type div; - typedef typename _ap_fixed_factory<_AP_W, _AP_I, _AP_S>::type arg1; - }; - - private: -#ifndef __SYNTHESIS__ - // This cannot handle hex float format string. - void fromString(const std::string& val, unsigned char radix) { - _AP_ERROR(!(radix == 2 || radix == 8 || radix == 10 || radix == 16), - "ap_fixed_base::fromString(%s, %d)", val.c_str(), radix); - - Base::V = 0; - int startPos = 0; - int endPos = val.length(); - int decPos = val.find("."); - if (decPos == -1) decPos = endPos; - - // handle sign - bool isNegative = false; - if (val[0] == '-') { - isNegative = true; - ++startPos; - } else if (val[0] == '+') - ++startPos; - - // If there are no integer bits, e.g.: - // .0000XXXX, then keep at least one bit. - // If the width is greater than the number of integer bits, e.g.: - // XXXX.XXXX, then we keep the integer bits - // if the number of integer bits is greater than the width, e.g.: - // XXX000 then we keep the integer bits. - // Always keep one bit. - ap_fixed_base - integer_bits = 0; - - // Figure out if we can shift instead of multiply - unsigned shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); - - //std::cout << "\n\n" << val << "\n"; - //std::cout << startPos << " " << decPos << " " << endPos << "\n"; - - bool sticky_int = false; - - // Traverse the integer digits from the MSD, multiplying by radix as we go. - for (int i = startPos; i < decPos; i++) { - // Get a digit - char cdigit = val[i]; - if (cdigit == '\0') continue; - unsigned digit = ap_private_ops::decode_digit(cdigit, radix); - - sticky_int |= integer_bits[AP_MAX(_AP_I, 4) + 4 - 1] | - integer_bits[AP_MAX(_AP_I, 4) + 4 - 2] | - integer_bits[AP_MAX(_AP_I, 4) + 4 - 3] | - integer_bits[AP_MAX(_AP_I, 4) + 4 - 4]; - // Shift or multiply the value by the radix - if (shift) - integer_bits <<= shift; - else - integer_bits *= radix; - - // Add in the digit we just interpreted - integer_bits += digit; - //std::cout << "idigit = " << digit << " " << integer_bits.to_string() - // << " " << sticky_int << "\n"; - } - integer_bits[AP_MAX(_AP_I, 4) + 4 - 3] = - integer_bits[AP_MAX(_AP_I, 4) + 4 - 3] | sticky_int; - - ap_fixed_base fractional_bits = 0; - bool sticky = false; - - // Traverse the fractional digits from the LSD, dividing by radix as we go. - for (int i = endPos - 1; i >= decPos + 1; i--) { - // Get a digit - char cdigit = val[i]; - if (cdigit == '\0') continue; - unsigned digit = ap_private_ops::decode_digit(cdigit, radix); - // Add in the digit we just interpreted - fractional_bits += digit; - - sticky |= fractional_bits[0] | fractional_bits[1] | fractional_bits[2] | - fractional_bits[3]; - // Shift or divide the value by the radix - if (shift) - fractional_bits >>= shift; - else - fractional_bits /= radix; - - //std::cout << "fdigit = " << digit << " " << fractional_bits.to_string() - // << " " << sticky << "\n"; - } - - //std::cout << "Int =" << integer_bits.to_string() << " " << - // fractional_bits.to_string() << "\n"; - - fractional_bits[0] = fractional_bits[0] | sticky; - - if (isNegative) - *this = -(integer_bits + fractional_bits); - else - *this = integer_bits + fractional_bits; - - //std::cout << "end = " << this->to_string(16) << "\n"; - } - - /// report invalid constrction of ap_fixed_base - INLINE void report() { - if (!_AP_S && _AP_O == AP_WRAP_SM) { - fprintf(stderr, "ap_ufxied<...> cannot support AP_WRAP_SM.\n"); - exit(1); - } - if (_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024) { - fprintf(stderr, - "[E] ap_%sfixed<%d, ...>: Bitwidth exceeds the " - "default max value %d. Please use macro " - "AP_INT_MAX_W to set a larger max value.\n", - _AP_S ? "" : "u", _AP_W, MAX_MODE(AP_INT_MAX_W) * 1024); - exit(1); - } - } -#else - INLINE void report() {} -#endif // ifdef __SYNTHESIS__ - - /// @name helper functions. - // @{ - INLINE void overflow_adjust(bool underflow, bool overflow, bool lD, - bool sign) { - if (!underflow && !overflow) return; - if (_AP_O == AP_WRAP) { - if (_AP_N == 0) return; - if (_AP_S) { - // signed AP_WRAP - // n_bits == 1 - Base::V = _AP_ROOT_op_set_bit(Base::V, _AP_W - 1, sign); - if (_AP_N > 1) { - // n_bits > 1 - ap_int_base<_AP_W, false> mask(-1); - if (sign) mask.V = 0; - Base::V = - _AP_ROOT_op_set_range(Base::V, _AP_W - _AP_N, _AP_W - 2, mask.V); - } - } else { - // unsigned AP_WRAP - ap_int_base<_AP_W, false> mask(-1); - Base::V = - _AP_ROOT_op_set_range(Base::V, _AP_W - _AP_N, _AP_W - 1, mask.V); - } - } else if (_AP_O == AP_SAT_ZERO) { - Base::V = 0; - } else if (_AP_O == AP_WRAP_SM && _AP_S) { - bool Ro = _AP_ROOT_op_get_bit(Base::V, _AP_W - 1); - if (_AP_N == 0) { - if (lD != Ro) { - Base::V = ~Base::V; - Base::V = _AP_ROOT_op_set_bit(Base::V, _AP_W - 1, lD); - } - } else { - if (_AP_N == 1 && sign != Ro) { - Base::V = ~Base::V; - } else if (_AP_N > 1) { - bool lNo = _AP_ROOT_op_get_bit(Base::V, _AP_W - _AP_N); - if (lNo == sign) Base::V = ~Base::V; - ap_int_base<_AP_W, false> mask(-1); - if (sign) mask.V = 0; - Base::V = - _AP_ROOT_op_set_range(Base::V, _AP_W - _AP_N, _AP_W - 2, mask.V); - } - Base::V = _AP_ROOT_op_set_bit(Base::V, _AP_W - 1, sign); - } - } else { - if (_AP_S) { - if (overflow) { - Base::V = 1; - Base::V <<= _AP_W - 1; - Base::V = ~Base::V; - } else if (underflow) { - Base::V = 1; - Base::V <<= _AP_W - 1; - if (_AP_O == AP_SAT_SYM) Base::V |= 1; - } - } else { - if (overflow) - Base::V = ~(ap_int_base<_AP_W, false>(0).V); - else if (underflow) - Base::V = 0; - } - } - } - - INLINE bool quantization_adjust(bool qb, bool r, bool s) { - bool carry = (bool)_AP_ROOT_op_get_bit(Base::V, _AP_W - 1); - if (_AP_Q == AP_TRN) return false; - if (_AP_Q == AP_RND_ZERO) - qb &= s || r; - else if (_AP_Q == AP_RND_MIN_INF) - qb &= r; - else if (_AP_Q == AP_RND_INF) - qb &= !s || r; - else if (_AP_Q == AP_RND_CONV) - qb &= _AP_ROOT_op_get_bit(Base::V, 0) || r; - else if (_AP_Q == AP_TRN_ZERO) - qb = s && (qb || r); - Base::V += qb; - return carry && (!(bool)_AP_ROOT_op_get_bit(Base::V, _AP_W - 1)); - } - // @} - - public: - /// @name constructors. - // @{ - /// default ctor. - INLINE ap_fixed_base() {} - - /// copy ctor. - template - INLINE ap_fixed_base( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - operator=(op); - report(); - } - - template - INLINE ap_fixed_base( - const volatile ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - operator=(op); - report(); - } - - template - INLINE ap_fixed_base(const ap_int_base<_AP_W2, _AP_S2>& op) { - ap_fixed_base<_AP_W2, _AP_W2, _AP_S2> tmp; - tmp.V = op.V; - operator=(tmp); - report(); - } - - template - INLINE ap_fixed_base(const volatile ap_int_base<_AP_W2, _AP_S2>& op) { - ap_fixed_base<_AP_W2, _AP_W2, _AP_S2> tmp; - tmp.V = op.V; - operator=(tmp); - report(); - } - -#ifndef __SYNTHESIS__ -#ifndef NON_C99STRING - INLINE ap_fixed_base(const char* s, signed char rd = 0) { - unsigned char radix = rd; - std::string str = ap_private_ops::parseString(s, radix); // will guess rd, default 10 - _AP_ERROR(radix == 0, "ap_fixed_base(const char* \"%s\", %d), str=%s, radix = %d", - s, rd, str.c_str(), radix); // TODO remove this check - fromString(str, radix); - } -#else - INLINE ap_fixed_base(const char* s, signed char rd = 10) { - ap_int_base<_AP_W, _AP_S> t(s, rd); - Base::V = t.V; - } -#endif // ifndef NON_C99STRING -#else // ifndef __SYNTHESIS__ - // XXX _ssdm_string2bits only takes const string and const radix. - // It seems XFORM will do compile time processing of the string. - INLINE ap_fixed_base(const char* s) { - typeof(Base::V) t; - _ssdm_string2bits((void*)(&t), (const char*)(s), 10, _AP_I, _AP_S, _AP_Q, - _AP_O, _AP_N, _AP_C99); - Base::V = t; - } - INLINE ap_fixed_base(const char* s, signed char rd) { - typeof(Base::V) t; - _ssdm_string2bits((void*)(&t), (const char*)(s), rd, _AP_I, _AP_S, _AP_Q, - _AP_O, _AP_N, _AP_C99); - Base::V = t; - } -#endif // ifndef __SYNTHESIS__ else - - template - INLINE ap_fixed_base(const ap_bit_ref<_AP_W2, _AP_S2>& op) { - *this = ((bool)op); - report(); - } - - template - INLINE ap_fixed_base(const ap_range_ref<_AP_W2, _AP_S2>& op) { - *this = (ap_int_base<_AP_W2, false>(op)); - report(); - } - - template - INLINE ap_fixed_base( - const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op) { - *this = (ap_int_base<_AP_W2 + _AP_W3, false>(op)); - report(); - } - - template - INLINE ap_fixed_base( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - *this = (bool(op)); - report(); - } - - template - INLINE ap_fixed_base( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - *this = (ap_int_base<_AP_W2, false>(op)); - report(); - } - - // ctors from c types. - // make a temp ap_fixed_base first, and use ap_fixed_base.operator= -#define CTOR_FROM_INT(C_TYPE, _AP_W2, _AP_S2) \ - INLINE ap_fixed_base(const C_TYPE x) { \ - ap_fixed_base<(_AP_W2), (_AP_W2), (_AP_S2)> tmp; \ - tmp.V = x; \ - *this = tmp; \ - } - - CTOR_FROM_INT(bool, 1, false) - CTOR_FROM_INT(char, 8, CHAR_IS_SIGNED) - CTOR_FROM_INT(signed char, 8, true) - CTOR_FROM_INT(unsigned char, 8, false) - CTOR_FROM_INT(short, _AP_SIZE_short, true) - CTOR_FROM_INT(unsigned short, _AP_SIZE_short, false) - CTOR_FROM_INT(int, _AP_SIZE_int, true) - CTOR_FROM_INT(unsigned int, _AP_SIZE_int, false) - CTOR_FROM_INT(long, _AP_SIZE_long, true) - CTOR_FROM_INT(unsigned long, _AP_SIZE_long, false) - CTOR_FROM_INT(ap_slong, _AP_SIZE_ap_slong, true) - CTOR_FROM_INT(ap_ulong, _AP_SIZE_ap_slong, false) -#undef CTOR_FROM_INT -/* - * TODO: - *Theere used to be several funtions which were AP_WEAK. - *Now they're all INLINE expect ap_fixed_base(double d) - *Maybe we can use '#pragma HLS inline' instead of INLINE. - */ - AP_WEAK ap_fixed_base(double d) { - ap_int_base<64, false> ireg; - ireg.V = doubleToRawBits(d); - bool isneg = _AP_ROOT_op_get_bit(ireg.V, 63); - - ap_int_base exp; - ap_int_base exp_tmp; - exp_tmp.V = - _AP_ROOT_op_get_range(ireg.V, DOUBLE_MAN, DOUBLE_MAN + DOUBLE_EXP - 1); - exp = exp_tmp - DOUBLE_BIAS; - ap_int_base man; - man.V = _AP_ROOT_op_get_range(ireg.V, 0, DOUBLE_MAN - 1); - // do not support NaN - _AP_WARNING(exp == APFX_IEEE_DOUBLE_E_MAX + 1 && man.V != 0, - "assign NaN to fixed point value"); - man.V = _AP_ROOT_op_set_bit(man.V, DOUBLE_MAN, 1); - if (isneg) man = -man; - if ((ireg.V & 0x7fffffffffffffffLL) == 0) { - Base::V = 0; - } else { - int _AP_W2 = DOUBLE_MAN + 2, _AP_I2 = exp.V + 2, _AP_F = _AP_W - _AP_I, - F2 = _AP_W2 - _AP_I2; - bool _AP_S2 = true, - QUAN_INC = F2 > _AP_F && - !(_AP_Q == AP_TRN || (_AP_Q == AP_TRN_ZERO && !_AP_S2)); - bool carry = false; - // handle quantization - unsigned sh_amt = (F2 > _AP_F) ? F2 - _AP_F : _AP_F - F2; - if (F2 == _AP_F) - Base::V = man.V; - else if (F2 > _AP_F) { - if (sh_amt < DOUBLE_MAN + 2) - Base::V = man.V >> sh_amt; - else { - Base::V = isneg ? -1 : 0; - } - if ((_AP_Q != AP_TRN) && !((_AP_Q == AP_TRN_ZERO) && !_AP_S2)) { - bool qb = (F2 - _AP_F > _AP_W2) ? isneg : (bool)_AP_ROOT_op_get_bit( - man.V, F2 - _AP_F - 1); - bool r = - (F2 > _AP_F + 1) - ? _AP_ROOT_op_get_range(man.V, 0, (F2 - _AP_F - 2 < _AP_W2) - ? (F2 - _AP_F - 2) - : (_AP_W2 - 1)) != 0 - : false; - carry = quantization_adjust(qb, r, isneg); - } - } else { // no quantization - Base::V = man.V; - if (sh_amt < _AP_W) - Base::V = Base::V << sh_amt; - else - Base::V = 0; - } - // handle overflow/underflow - if ((_AP_O != AP_WRAP || _AP_N != 0) && - ((!_AP_S && _AP_S2) || - _AP_I - _AP_S < - _AP_I2 - _AP_S2 + - (QUAN_INC || - (_AP_S2 && (_AP_O == AP_SAT_SYM))))) { // saturation - bool deleted_zeros = _AP_S2 ? true : !carry, deleted_ones = true; - bool neg_src = isneg; - bool lD = false; - int pos1 = F2 - _AP_F + _AP_W; - int pos2 = F2 - _AP_F + _AP_W + 1; - bool newsignbit = _AP_ROOT_op_get_bit(Base::V, _AP_W - 1); - if (pos1 < _AP_W2 && pos1 >= 0) - // lD = _AP_ROOT_op_get_bit(man.V, pos1); - lD = (man.V >> pos1) & 1; - if (pos1 < _AP_W2) { - bool Range1_all_ones = true; - bool Range1_all_zeros = true; - bool Range2_all_ones = true; - ap_int_base Range2; - ap_int_base all_ones(-1); - - if (pos2 >= 0 && pos2 < _AP_W2) { - // Range2.V = _AP_ROOT_op_get_range(man.V, - // pos2, _AP_W2 - 1); - Range2.V = man.V; - Range2.V >>= pos2; - Range2_all_ones = Range2 == (all_ones >> pos2); - } else if (pos2 < 0) - Range2_all_ones = false; - if (pos1 >= 0 && pos2 < _AP_W2) { - Range1_all_ones = Range2_all_ones && lD; - Range1_all_zeros = !Range2.V && !lD; - } else if (pos2 == _AP_W2) { - Range1_all_ones = lD; - Range1_all_zeros = !lD; - } else if (pos1 < 0) { - Range1_all_zeros = !man.V; - Range1_all_ones = false; - } - - deleted_zeros = - deleted_zeros && (carry ? Range1_all_ones : Range1_all_zeros); - deleted_ones = - carry ? Range2_all_ones && (pos1 < 0 || !lD) : Range1_all_ones; - neg_src = isneg && !(carry && Range1_all_ones); - } else - neg_src = isneg && newsignbit; - bool neg_trg = _AP_S && newsignbit; - bool overflow = (neg_trg || !deleted_zeros) && !isneg; - bool underflow = (!neg_trg || !deleted_ones) && neg_src; - if ((_AP_O == AP_SAT_SYM) && _AP_S2 && _AP_S) - underflow |= - neg_src && - (_AP_W > 1 ? _AP_ROOT_op_get_range(Base::V, 0, _AP_W - 2) == 0 - : true); - overflow_adjust(underflow, overflow, lD, neg_src); - } - } - report(); - } - - // TODO more optimized implementation. - INLINE ap_fixed_base(float d) { *this = ap_fixed_base(double(d)); } - -#if _AP_ENABLE_HALF_ == 1 - // TODO more optimized implementation. - INLINE ap_fixed_base(half d) { *this = ap_fixed_base(double(d)); } -#endif - // @} - - /// @name assign operator - /// assign, using another ap_fixed_base of same template parameters. - /* - INLINE ap_fixed_base& operator=( - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { - Base::V = op.V; - return *this; - } - */ - - template - INLINE ap_fixed_base& operator=( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - - const int _AP_F = _AP_W - _AP_I; - const int F2 = _AP_W2 - _AP_I2; - const int QUAN_INC = - F2 > _AP_F && !(_AP_Q == AP_TRN || (_AP_Q == AP_TRN_ZERO && !_AP_S2)); - - if (!op) Base::V = 0; - bool carry = false; - bool signbit = _AP_ROOT_op_get_bit(op.V, _AP_W2 - 1); - bool isneg = signbit && _AP_S2; - if (F2 == _AP_F) - Base::V = op.V; - else if (F2 > _AP_F) { - unsigned int sh_amt = F2 - _AP_F; - // moves bits right, handle quantization. - if (sh_amt < _AP_W2) { - Base::V = op.V >> sh_amt; - } else { - Base::V = isneg ? -1 : 0; - } - if (_AP_Q != AP_TRN && !(_AP_Q == AP_TRN_ZERO && !_AP_S2)) { - bool qbit = _AP_ROOT_op_get_bit(op.V, F2 - _AP_F - 1); - // bit after LSB. - bool qb = (F2 - _AP_F > _AP_W2) ? _AP_S2 && signbit : qbit; - enum { hi = ((F2 - _AP_F - 2) < _AP_W2) ? (F2 - _AP_F - 2) : (_AP_W2 - 1) }; - // bits after qb. - bool r = (F2 > _AP_F + 1) ? (_AP_ROOT_op_get_range(op.V, 0, hi) != 0) : false; - carry = quantization_adjust(qb, r, isneg); - } - } else { - unsigned sh_amt = _AP_F - F2; - // moves bits left, no quantization - if (sh_amt < _AP_W) { - if (_AP_W > _AP_W2) { - // extend and then shift, avoid losing bits. - Base::V = op.V; - Base::V <<= sh_amt; - } else { - // shift and truncate. - Base::V = op.V << sh_amt; - } - } else { - Base::V = 0; - } - } - // handle overflow/underflow - if ((_AP_O != AP_WRAP || _AP_N != 0) && - ((!_AP_S && _AP_S2) || - _AP_I - _AP_S < - _AP_I2 - _AP_S2 + - (QUAN_INC || (_AP_S2 && _AP_O == AP_SAT_SYM)))) { // saturation - bool deleted_zeros = _AP_S2 ? true : !carry; - bool deleted_ones = true; - bool neg_src = isneg; - bool newsignbit = _AP_ROOT_op_get_bit(Base::V, _AP_W - 1); - enum { pos1 = F2 - _AP_F + _AP_W, pos2 = F2 - _AP_F + _AP_W + 1 }; - bool lD = (pos1 < _AP_W2 && pos1 >= 0) ? _AP_ROOT_op_get_bit(op.V, pos1) - : false; - if (pos1 < _AP_W2) { - bool Range1_all_ones = true; - bool Range1_all_zeros = true; - bool Range2_all_ones = true; - ap_int_base<_AP_W2, false> all_ones(-1); - - if (pos2 < _AP_W2 && pos2 >= 0) { - ap_int_base<_AP_W2, false> Range2; - Range2.V = _AP_ROOT_op_get_range(op.V, pos2, _AP_W2 - 1); - Range2_all_ones = Range2 == (all_ones >> pos2); - } else if (pos2 < 0) { - Range2_all_ones = false; - } - - if (pos1 >= 0 && pos2 < _AP_W2) { - ap_int_base<_AP_W2, false> Range1; - Range1.V = _AP_ROOT_op_get_range(op.V, pos1, _AP_W2 - 1); - Range1_all_ones = Range1 == (all_ones >> pos1); - Range1_all_zeros = !Range1.V; - } else if (pos2 == _AP_W2) { - Range1_all_ones = lD; - Range1_all_zeros = !lD; - } else if (pos1 < 0) { - Range1_all_zeros = !op.V; - Range1_all_ones = false; - } - - deleted_zeros = - deleted_zeros && (carry ? Range1_all_ones : Range1_all_zeros); - deleted_ones = - carry ? Range2_all_ones && (pos1 < 0 || !lD) : Range1_all_ones; - neg_src = isneg && !(carry && Range1_all_ones); - } else - neg_src = isneg && newsignbit; - bool neg_trg = _AP_S && newsignbit; - bool overflow = (neg_trg || !deleted_zeros) && !isneg; - bool underflow = (!neg_trg || !deleted_ones) && neg_src; - if ((_AP_O == AP_SAT_SYM) && _AP_S2 && _AP_S) - underflow |= - neg_src && - (_AP_W > 1 ? _AP_ROOT_op_get_range(Base::V, 0, _AP_W - 2) == 0 - : true); - - overflow_adjust(underflow, overflow, lD, neg_src); - } - return *this; - } // operator= - - template - INLINE ap_fixed_base& operator=( - const volatile ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - operator=(const_cast&>(op)); - return *this; - } - - /// Set this ap_fixed_base with ULL. - INLINE ap_fixed_base& setBits(ap_ulong bv) { - // TODO when ull is not be long enough... - Base::V = bv; - return *this; - } - - /// Return a ap_fixed_base object whose this->V is assigned by bv. - static INLINE ap_fixed_base bitsToFixed(ap_ulong bv) { - // TODO fix when ull is not be long enough... - ap_fixed_base t; -#ifdef __SYNTHESIS__ - t.V = bv; -#else - t.V.set_bits(bv); -#endif - return t; - } - - // Explicit conversion functions to ap_int_base. - /** Captures all integer bits, in truncate mode. - * @param[in] Cnative follow conversion from double to int. - */ - INLINE ap_int_base to_ap_int_base( - bool Cnative = true) const { - ap_int_base ret; - if (_AP_I == 0) { - ret.V = 0; - } else if (_AP_I > 0 && _AP_I <= _AP_W) { - ret.V = _AP_ROOT_op_get_range(Base::V, _AP_W - _AP_I, _AP_W - 1); - } else if (_AP_I > _AP_W) { - ret.V = _AP_ROOT_op_get_range(Base::V, 0, _AP_W - 1); - ret.V <<= (_AP_I - _AP_W); - } - /* Consider the following case - * float f = -7.5f; - * ap_fixed<8,4> t = f; // -8 0 0 0 . 0.5 - * int i = t.to_int(); - * the result should be -7 instead of -8. - * Therefore, after truncation, the value should be increated by 1. - * For (-1, 0), carry to MSB will happen, but result 0 is still correct. - */ - if (Cnative && _AP_I < _AP_W) { - // Follow C native data type, conversion from double to int - if (_AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1) && (_AP_I < _AP_W) && - (_AP_ROOT_op_get_range( - Base::V, 0, _AP_I < 0 ? _AP_W - 1 : _AP_W - _AP_I - 1) != 0)) - ++ret; - } else { - // Follow OSCI library, conversion from sc_fixed to sc_int - } - return ret; - }; - - public: - template - INLINE operator ap_int_base<_AP_W2, _AP_S2>() const { - return ap_int_base<_AP_W2, _AP_S2>(to_ap_int_base()); - } - - // Explicit conversion function to C built-in integral type. - INLINE char to_char() const { return to_ap_int_base().to_char(); } - - INLINE int to_int() const { return to_ap_int_base().to_int(); } - - INLINE unsigned to_uint() const { return to_ap_int_base().to_uint(); } - - INLINE ap_slong to_int64() const { return to_ap_int_base().to_int64(); } - - INLINE ap_ulong to_uint64() const { return to_ap_int_base().to_uint64(); } - - /// covert function to double. - /** only round-half-to-even mode supported, does not obey FE env. */ - INLINE double to_double() const { -#if defined(AP_FIXED_ENABLE_CPP_FENV) - _AP_WARNING(std::fegetround() != FE_TONEAREST, - "Only FE_TONEAREST is supported"); -#endif - enum { BITS = DOUBLE_MAN + DOUBLE_EXP + 1 }; - if (!Base::V) return 0.0f; - bool s = _AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1); ///< sign. - ap_int_base<_AP_W, false> tmp; - if (s) - tmp.V = -Base::V; // may truncate one bit extra from neg in sim. - else - tmp.V = Base::V; - int l = tmp.countLeadingZeros(); ///< number of leading zeros. - int e = _AP_I - l - 1 + DOUBLE_BIAS; ///< exponent - int lsb_index = _AP_W - l - 1 - DOUBLE_MAN; - // more than 0.5? - bool a = (lsb_index >=2) ? - (_AP_ROOT_op_get_range(tmp.V, 0, lsb_index - 2) != 0) : 0; - // round to even - a |= (lsb_index >=0) ? _AP_ROOT_op_get_bit(tmp.V, lsb_index) : 0; - // ull is at least 64-bit - ap_ulong m; - // may actually left shift, ensure buffer is wide enough. - if (_AP_W > BITS) { - m = (lsb_index >= 1) ? (ap_ulong)(tmp.V >> (lsb_index - 1)) - : (ap_ulong)(tmp.V << (1 - lsb_index)); - } else { - m = (ap_ulong)tmp.V; - m = (lsb_index >= 1) ? (m >> (lsb_index - 1)) - : (m << (1 - lsb_index)); - } - m += a; - m >>= 1; - //std::cout << '\n' << std::hex << m << '\n'; // TODO delete this - // carry to MSB, increase exponent - if (_AP_ctype_op_get_bit(m, DOUBLE_MAN + 1)) { - e += 1; - } - // set sign and exponent - m = _AP_ctype_op_set_bit(m, BITS - 1, s); - //std::cout << m << '\n'; // TODO delete this - m = _AP_ctype_op_set_range(m, DOUBLE_MAN, DOUBLE_MAN + DOUBLE_EXP - 1, e); - //std::cout << std::hex << m << std::dec << std::endl; // TODO delete this - // cast to fp - return rawBitsToDouble(m); - } - - /// convert function to float. - /** only round-half-to-even mode supported, does not obey FE env. */ - INLINE float to_float() const { -#if defined(AP_FIXED_ENABLE_CPP_FENV) - _AP_WARNING(std::fegetround() != FE_TONEAREST, - "Only FE_TONEAREST is supported"); -#endif - enum { BITS = FLOAT_MAN + FLOAT_EXP + 1 }; - if (!Base::V) return 0.0f; - bool s = _AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1); ///< sign. - ap_int_base<_AP_W, false> tmp; - if (s) - tmp.V = -Base::V; // may truncate one bit extra from neg in sim. - else - tmp.V = Base::V; - int l = tmp.countLeadingZeros(); ///< number of leading zeros. - int e = _AP_I - l - 1 + FLOAT_BIAS; ///< exponent - int lsb_index = _AP_W - l - 1 - FLOAT_MAN; - // more than 0.5? - bool a = (lsb_index >=2) ? - (_AP_ROOT_op_get_range(tmp.V, 0, lsb_index - 2) != 0) : 0; - // round to even - a |= (lsb_index >=0) ? _AP_ROOT_op_get_bit(tmp.V, lsb_index) : 0; - // ul is at least 32-bit - unsigned long m; - // may actually left shift, ensure buffer is wide enough. - if (_AP_W > BITS) { - m = (lsb_index >= 1) ? (unsigned long)(tmp.V >> (lsb_index - 1)) - : (unsigned long)(tmp.V << (1 - lsb_index)); - } else { - m = (unsigned long)tmp.V; - m = (lsb_index >= 1) ? (m >> (lsb_index - 1)) - : (m << (1 - lsb_index)); - } - m += a; - m >>= 1; - // carry to MSB, increase exponent - if (_AP_ctype_op_get_bit(m, FLOAT_MAN + 1)) { - e += 1; - } - // set sign and exponent - m = _AP_ctype_op_set_bit(m, BITS - 1, s); - m = _AP_ctype_op_set_range(m, FLOAT_MAN, FLOAT_MAN + FLOAT_EXP - 1, e); - // cast to fp - return rawBitsToFloat(m); - } - -#if _AP_ENABLE_HALF_ == 1 - /// convert function to half. - /** only round-half-to-even mode supported, does not obey FE env. */ - INLINE half to_half() const { -#if defined(AP_FIXED_ENABLE_CPP_FENV) - _AP_WARNING(std::fegetround() != FE_TONEAREST, - "Only FE_TONEAREST is supported"); -#endif - enum { BITS = HALF_MAN + HALF_EXP + 1 }; - if (!Base::V) return 0.0f; - bool s = _AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1); ///< sign. - ap_int_base<_AP_W, false> tmp; - if (s) - tmp.V = -Base::V; // may truncate one bit extra from neg in sim. - else - tmp.V = Base::V; - int l = tmp.countLeadingZeros(); ///< number of leading zeros. - int e = _AP_I - l - 1 + HALF_BIAS; ///< exponent - int lsb_index = _AP_W - l - 1 - HALF_MAN; - // more than 0.5? - bool a = (lsb_index >=2) ? - (_AP_ROOT_op_get_range(tmp.V, 0, lsb_index - 2) != 0) : 0; - // round to even - a |= (lsb_index >=0) ? _AP_ROOT_op_get_bit(tmp.V, lsb_index) : 0; - // short is at least 16-bit - unsigned short m; - // may actually left shift, ensure buffer is wide enough. - if (_AP_W > BITS) { - m = (lsb_index >= 1) ? (unsigned short)(tmp.V >> (lsb_index - 1)) - : (unsigned short)(tmp.V << (1 - lsb_index)); - } else { - m = (unsigned short)tmp.V; - m = (lsb_index >= 1) ? (m >> (lsb_index - 1)) - : (m << (1 - lsb_index)); - } - m += a; - m >>= 1; - // carry to MSB, increase exponent - if (_AP_ctype_op_get_bit(m, HALF_MAN + 1)) { - e += 1; - } - // set sign and exponent - m = _AP_ctype_op_set_bit(m, BITS - 1, s); - m = _AP_ctype_op_set_range(m, HALF_MAN, HALF_MAN + HALF_EXP - 1, e); - // cast to fp - return rawBitsToHalf(m); - } -#endif - - // FIXME inherited from old code, this may loose precision! - INLINE operator long double() const { return (long double)to_double(); } - - INLINE operator double() const { return to_double(); } - - INLINE operator float() const { return to_float(); } - -#if _AP_ENABLE_HALF_ == 1 - INLINE operator half() const { return to_half(); } -#endif - - INLINE operator bool() const { return (bool)Base::V != 0; } - - INLINE operator char() const { return (char)to_int(); } - - INLINE operator signed char() const { return (signed char)to_int(); } - - INLINE operator unsigned char() const { return (unsigned char)to_uint(); } - - INLINE operator short() const { return (short)to_int(); } - - INLINE operator unsigned short() const { return (unsigned short)to_uint(); } - - INLINE operator int() const { return to_int(); } - - INLINE operator unsigned int() const { return to_uint(); } - -// FIXME don't assume data width... -#ifdef __x86_64__ - INLINE operator long() const { return (long)to_int64(); } - - INLINE operator unsigned long() const { return (unsigned long)to_uint64(); } -#else - INLINE operator long() const { return (long)to_int(); } - - INLINE operator unsigned long() const { return (unsigned long)to_uint(); } -#endif // ifdef __x86_64__ else - - INLINE operator ap_ulong() const { return to_uint64(); } - - INLINE operator ap_slong() const { return to_int64(); } - - INLINE int length() const { return _AP_W; }; - - // bits_to_int64 deleted. -#ifndef __SYNTHESIS__ - // Used in autowrap, when _AP_W < 64. - INLINE ap_ulong bits_to_uint64() const { - return (Base::V).to_uint64(); - } -#endif - - // Count the number of zeros from the most significant bit - // to the first one bit. Note this is only for ap_fixed_base whose - // _AP_W <= 64, otherwise will incur assertion. - INLINE int countLeadingZeros() { -#ifdef __SYNTHESIS__ - // TODO: used llvm.ctlz intrinsic ? - if (_AP_W <= 32) { - ap_int_base<32, false> t(-1ULL); - t.range(_AP_W - 1, 0) = this->range(0, _AP_W - 1); - return __builtin_ctz(t.V); - } else if (_AP_W <= 64) { - ap_int_base<64, false> t(-1ULL); - t.range(_AP_W - 1, 0) = this->range(0, _AP_W - 1); - return __builtin_ctzll(t.V); - } else { - enum {__N = (_AP_W + 63) / 64}; - int NZeros = 0; - int i = 0; - bool hitNonZero = false; - for (i = 0; i < __N - 1; ++i) { - ap_int_base<64, false> t; - t.range(0, 63) = this->range(_AP_W - i * 64 - 64, _AP_W - i * 64 - 1); - NZeros += hitNonZero ? 0 : __builtin_clzll(t.V); - hitNonZero |= (t != 0); - } - if (!hitNonZero) { - ap_int_base<64, false> t(-1ULL); - t.range(63 - (_AP_W - 1) % 64, 63) = this->range(0, (_AP_W - 1) % 64); - NZeros += __builtin_clzll(t.V); - } - return NZeros; - } -#else - return Base::V.countLeadingZeros(); -#endif - } - - // Arithmetic : Binary - // ------------------------------------------------------------------------- - template - INLINE typename RType<_AP_W2, _AP_I2, _AP_S2>::mult operator*( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) - const { - typename RType<_AP_W2, _AP_I2, _AP_S2>::mult_base r, t; - r.V = Base::V; - t.V = op2.V; - r.V *= op2.V; - return r; - } - - // multiply function deleted. - - template - INLINE typename RType<_AP_W2, _AP_I2, _AP_S2>::div operator/( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) - const { - typename RType<_AP_W2, _AP_I2, _AP_S2>::div_base r; -#ifndef __SYNTHESIS__ - enum {F2 = _AP_W2-_AP_I2, - _W1=AP_MAX(_AP_W + AP_MAX(F2, 0) + ((_AP_S2 && !_AP_S) ? 1 : 0), _AP_W2 + ((_AP_S && !_AP_S2) ? 1 : 0))}; - ap_int_base<_W1,_AP_S||_AP_S2> dividend,divisior; - ap_int_base<_W1,_AP_S> tmp1; - ap_int_base<_W1,_AP_S2> tmp2; - tmp1.V = Base::V; - tmp1.V <<= AP_MAX(F2,0); - tmp2.V = op2.V; - dividend = tmp1; - divisior = tmp2; - r.V = ((_AP_S||_AP_S2) ? dividend.V.sdiv(divisior.V): dividend.V.udiv(divisior.V)); -#else - #ifndef __SC_COMPATIBLE__ - ap_fixed_base<_AP_W + AP_MAX(_AP_W2 - _AP_I2, 0),_AP_I, _AP_S> t(*this); - #else - ap_fixed_base<_AP_W + AP_MAX(_AP_W2 - _AP_I2, 0) + AP_MAX(_AP_I2, 0),_AP_I, _AP_S> t(*this); - #endif - r.V = t.V / op2.V; -#endif -/* - enum { - F2 = _AP_W2 - _AP_I2, - shl = AP_MAX(F2, 0) + AP_MAX(_AP_I2, 0), -#ifndef __SC_COMPATIBLE__ - shr = AP_MAX(_AP_I2, 0), -#else - shr = 0, -#endif - W3 = _AP_S2 + _AP_W + shl, - S3 = _AP_S || _AP_S2, - }; - ap_int_base dividend, t; - dividend.V = Base::V; - // multiply both by (1 << F2), and than do integer division. - dividend.V <<= (int) shl; -#ifdef __SYNTHESIS__ - // .V's have right signedness, and will have right extending. - t.V = dividend.V / op2.V; -#else - // XXX op2 may be wider than dividend, and sdiv and udiv takes the same with - // as left hand operand, so data might be truncated by mistake if not - // handled here. - t.V = S3 ? dividend.V.sdiv(op2.V) : dividend.V.udiv(op2.V); -#endif - r.V = t.V >> (int) shr; -*/ - return r; - } - -#define OP_BIN_AF(Sym, Rty) \ - template \ - INLINE typename RType<_AP_W2, _AP_I2, _AP_S2>::Rty operator Sym( \ - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& \ - op2) const { \ - typename RType<_AP_W2, _AP_I2, _AP_S2>::Rty##_base ret, lhs(*this), \ - rhs(op2); \ - ret.V = lhs.V Sym rhs.V; \ - return ret; \ - } - - OP_BIN_AF(+, plus) - OP_BIN_AF(-, minus) - OP_BIN_AF(&, logic) - OP_BIN_AF(|, logic) - OP_BIN_AF(^, logic) - -// Arithmetic : assign -// ------------------------------------------------------------------------- -#define OP_ASSIGN_AF(Sym) \ - template \ - INLINE ap_fixed_base& operator Sym##=( \ - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& \ - op2) { \ - *this = operator Sym(op2); \ - return *this; \ - } - - OP_ASSIGN_AF(*) - OP_ASSIGN_AF(/) - OP_ASSIGN_AF(+) - OP_ASSIGN_AF(-) - OP_ASSIGN_AF(&) - OP_ASSIGN_AF(|) - OP_ASSIGN_AF(^) - - // Prefix and postfix increment and decrement. - // ------------------------------------------------------------------------- - - /// Prefix increment - INLINE ap_fixed_base& operator++() { - operator+=(ap_fixed_base<_AP_W - _AP_I + 1, 1, false>(1)); - return *this; - } - - /// Prefix decrement. - INLINE ap_fixed_base& operator--() { - operator-=(ap_fixed_base<_AP_W - _AP_I + 1, 1, false>(1)); - return *this; - } - - /// Postfix increment - INLINE const ap_fixed_base operator++(int) { - ap_fixed_base r(*this); - operator++(); - return r; - } - - /// Postfix decrement - INLINE const ap_fixed_base operator--(int) { - ap_fixed_base r(*this); - operator--(); - return r; - } - - // Unary arithmetic. - // ------------------------------------------------------------------------- - INLINE ap_fixed_base operator+() { return *this; } - - INLINE ap_fixed_base<_AP_W + 1, _AP_I + 1, true> operator-() const { - ap_fixed_base<_AP_W + 1, _AP_I + 1, true> r(*this); - r.V = -r.V; - return r; - } - - INLINE ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> getNeg() { - ap_fixed_base<_AP_W, _AP_I, true, _AP_Q, _AP_O, _AP_N> r(*this); - r.V = -r.V; - return r; - } - - // Not (!) - // ------------------------------------------------------------------------- - INLINE bool operator!() const { return Base::V == 0; } - - // Bitwise complement - // ------------------------------------------------------------------------- - // XXX different from Mentor's ac_fixed. - INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S> operator~() const { - ap_fixed_base<_AP_W, _AP_I, _AP_S> r; - r.V = ~Base::V; - return r; - } - - // Shift - // ------------------------------------------------------------------------- - // left shift is the same as moving point right, i.e. increate I. - template - INLINE ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> lshift() const { - ap_fixed_base<_AP_W, _AP_I + _AP_SHIFT, _AP_S> r; - r.V = Base::V; - return r; - } - - template - INLINE ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> rshift() const { - ap_fixed_base<_AP_W, _AP_I - _AP_SHIFT, _AP_S> r; - r.V = Base::V; - return r; - } - - // Because the return type is the type of the the first operand, shift assign - // operators do not carry out any quantization or overflow - // While systemc, shift assigns for sc_fixed/sc_ufixed will result in - // quantization or overflow (depending on the mode of the first operand) - INLINE ap_fixed_base operator<<(unsigned int sh) const { - ap_fixed_base r; - r.V = Base::V << sh; -// TODO check shift overflow? -#ifdef __SC_COMPATIBLE__ - if (sh == 0) return r; - if (_AP_O != AP_WRAP || _AP_N != 0) { - bool neg_src = _AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1); - bool allones, allzeros; - ap_int_base<_AP_W, false> ones(-1); - if (sh <= _AP_W) { - ap_int_base<_AP_W, false> range1; - range1.V = _AP_ROOT_op_get_range( - const_cast(this)->Base::V, _AP_W - sh, _AP_W - 1); - allones = range1 == (ones >> (_AP_W - sh)); - allzeros = range1 == 0; - } else { - allones = false; - allzeros = Base::V == 0; - } - bool overflow = !allzeros && !neg_src; - bool underflow = !allones && neg_src; - if ((_AP_O == AP_SAT_SYM) && _AP_S) - underflow |= - neg_src && - (_AP_W > 1 ? _AP_ROOT_op_get_range(r.V, 0, _AP_W - 2) == 0 : true); - bool lD = false; - if (sh < _AP_W) lD = _AP_ROOT_op_get_bit(Base::V, _AP_W - sh - 1); - r.overflow_adjust(underflow, overflow, lD, neg_src); - } -#endif - return r; - } - - INLINE ap_fixed_base operator>>(unsigned int sh) const { - ap_fixed_base r; - r.V = Base::V >> sh; -// TODO check shift overflow? -#ifdef __SC_COMPATIBLE__ - if (sh == 0) return r; - if (_AP_Q != AP_TRN) { - bool qb = false; - if (sh <= _AP_W) qb = _AP_ROOT_op_get_bit(Base::V, sh - 1); - bool rb = false; - if (sh > 1 && sh <= _AP_W) - rb = _AP_ROOT_op_get_range(const_cast(this)->Base::V, 0, - sh - 2) != 0; - else if (sh > _AP_W) - rb = Base::V != 0; - r.quantization_adjust(qb, rb, - _AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1)); - } -#endif - return r; - } - - // left and right shift for int - INLINE ap_fixed_base operator<<(int sh) const { - ap_fixed_base r; - bool isNeg = sh < 0; - unsigned int ush = isNeg ? -sh : sh; - if (isNeg) { - return operator>>(ush); - } else { - return operator<<(ush); - } - } - - INLINE ap_fixed_base operator>>(int sh) const { - bool isNeg = sh < 0; - unsigned int ush = isNeg ? -sh : sh; - if (isNeg) { - return operator<<(ush); - } else { - return operator>>(ush); - } - } - - // left and right shift for ap_int. - template - INLINE ap_fixed_base operator<<(const ap_int_base<_AP_W2, true>& op2) const { - // TODO the code seems not optimal. ap_fixed<8,8> << ap_int<2> needs only a - // small mux, but integer need a big one! - int sh = op2.to_int(); - return operator<<(sh); - } - - template - INLINE ap_fixed_base operator>>(const ap_int_base<_AP_W2, true>& op2) const { - int sh = op2.to_int(); - return operator>>(sh); - } - - // left and right shift for ap_uint. - template - INLINE ap_fixed_base operator<<(const ap_int_base<_AP_W2, false>& op2) const { - unsigned int sh = op2.to_uint(); - return operator<<(sh); - } - - template - INLINE ap_fixed_base operator>>(const ap_int_base<_AP_W2, false>& op2) const { - unsigned int sh = op2.to_uint(); - return operator>>(sh); - } - - // left and right shift for ap_fixed - template - INLINE ap_fixed_base operator<<( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& - op2) { - return operator<<(op2.to_ap_int_base()); - } - - template - INLINE ap_fixed_base operator>>( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& - op2) { - return operator>>(op2.to_ap_int_base()); - } - - // Shift assign. - // ------------------------------------------------------------------------- - - // left shift assign. - INLINE ap_fixed_base& operator<<=(const int sh) { - *this = operator<<(sh); - return *this; - } - - INLINE ap_fixed_base& operator<<=(const unsigned int sh) { - *this = operator<<(sh); - return *this; - } - - template - INLINE ap_fixed_base& operator<<=(const ap_int_base<_AP_W2, _AP_S2>& sh) { - *this = operator<<(sh.to_int()); - return *this; - } - - template - INLINE ap_fixed_base& operator<<=( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& - sh) { - *this = operator<<(sh.to_int()); - return *this; - } - - // right shift assign. - INLINE ap_fixed_base& operator>>=(const int sh) { - *this = operator>>(sh); - return *this; - } - - INLINE ap_fixed_base& operator>>=(const unsigned int sh) { - *this = operator>>(sh); - return *this; - } - - template - INLINE ap_fixed_base& operator>>=(const ap_int_base<_AP_W2, _AP_S2>& sh) { - *this = operator>>(sh.to_int()); - return *this; - } - - template - INLINE ap_fixed_base& operator>>=( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& - sh) { - *this = operator>>(sh.to_int()); - return *this; - } - -// Comparisons. -// ------------------------------------------------------------------------- -#define OP_CMP_AF(Sym) \ - template \ - INLINE bool operator Sym(const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, \ - _AP_O2, _AP_N2>& op2) const { \ - enum { _AP_F = _AP_W - _AP_I, F2 = _AP_W2 - _AP_I2 }; \ - if (_AP_F == F2) \ - return Base::V Sym op2.V; \ - else if (_AP_F > F2) \ - return Base::V Sym ap_fixed_base(op2).V; \ - else \ - return ap_fixed_base(*this).V Sym op2.V; \ - return false; \ - } - - OP_CMP_AF(>) - OP_CMP_AF(<) - OP_CMP_AF(>=) - OP_CMP_AF(<=) - OP_CMP_AF(==) - OP_CMP_AF(!=) -// FIXME: Move compare with double out of struct ap_fixed_base defination -// and combine it with compare operator(double, ap_fixed_base) -#define DOUBLE_CMP_AF(Sym) \ - INLINE bool operator Sym(double d) const { return to_double() Sym d; } - - DOUBLE_CMP_AF(>) - DOUBLE_CMP_AF(<) - DOUBLE_CMP_AF(>=) - DOUBLE_CMP_AF(<=) - DOUBLE_CMP_AF(==) - DOUBLE_CMP_AF(!=) - - // Bit and Slice Select - INLINE af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> operator[]( - unsigned index) { - _AP_WARNING(index >= _AP_W, "Attempting to read bit beyond MSB"); - return af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, index); - } - - template - INLINE af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> operator[]( - const ap_int_base<_AP_W2, _AP_S2>& index) { - _AP_WARNING(index < 0, "Attempting to read bit with negative index"); - _AP_WARNING(index >= _AP_W, "Attempting to read bit beyond MSB"); - return af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, - index.to_int()); - } - - INLINE bool operator[](unsigned index) const { - _AP_WARNING(index >= _AP_W, "Attempting to read bit beyond MSB"); - return _AP_ROOT_op_get_bit(const_cast(this)->V, index); - } - - INLINE af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> bit( - unsigned index) { - _AP_WARNING(index >= _AP_W, "Attempting to read bit beyond MSB"); - return af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, index); - } - - template - INLINE af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> bit( - const ap_int_base<_AP_W2, _AP_S2>& index) { - _AP_WARNING(index < 0, "Attempting to read bit with negative index"); - _AP_WARNING(index >= _AP_W, "Attempting to read bit beyond MSB"); - return af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, - index.to_int()); - } - - INLINE bool bit(unsigned index) const { - _AP_WARNING(index >= _AP_W, "Attempting to read bit beyond MSB"); - return _AP_ROOT_op_get_bit(const_cast(this)->V, index); - } - - template - INLINE af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> get_bit( - const ap_int_base<_AP_W2, true>& index) { - _AP_WARNING(index < _AP_I - _AP_W, - "Attempting to read bit with negative index"); - _AP_WARNING(index >= _AP_I, "Attempting to read bit beyond MSB"); - return af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>( - this, index.to_int() + _AP_W - _AP_I); - } - - INLINE bool get_bit(int index) const { - _AP_WARNING(index >= _AP_I, "Attempting to read bit beyond MSB"); - _AP_WARNING(index < _AP_I - _AP_W, "Attempting to read bit beyond MSB"); - return _AP_ROOT_op_get_bit(const_cast(this)->V, - index + _AP_W - _AP_I); - } -#if 0 - INLINE af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> get_bit( - int index) { - _AP_WARNING(index < _AP_I - _AP_W, - "Attempting to read bit with negative index"); - _AP_WARNING(index >= _AP_I, "Attempting to read bit beyond MSB"); - return af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>( - this, index + _AP_W - _AP_I); - } -#endif - - template - INLINE bool get_bit(const ap_int_base<_AP_W2, true>& index) const { - _AP_WARNING(index >= _AP_I, "Attempting to read bit beyond MSB"); - _AP_WARNING(index < _AP_I - _AP_W, "Attempting to read bit beyond MSB"); - return _AP_ROOT_op_get_bit(const_cast(this)->V, - index.to_int() + _AP_W - _AP_I); - } - - INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> range(int Hi, - int Lo) { - _AP_WARNING((Hi >= _AP_W) || (Lo >= _AP_W), "Out of bounds in range()"); - return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(this, Hi, Lo); - } - - // This is a must to strip constness to produce reference type. - INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> range( - int Hi, int Lo) const { - _AP_WARNING((Hi >= _AP_W) || (Lo >= _AP_W), "Out of bounds in range()"); - return af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>( - const_cast(this), Hi, Lo); - } - - template - INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> range( - const ap_int_base<_AP_W2, _AP_S2>& HiIdx, - const ap_int_base<_AP_W3, _AP_S3>& LoIdx) { - int Hi = HiIdx.to_int(); - int Lo = LoIdx.to_int(); - return this->range(Hi, Lo); - } - - template - INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> range( - const ap_int_base<_AP_W2, _AP_S2>& HiIdx, - const ap_int_base<_AP_W3, _AP_S3>& LoIdx) const { - int Hi = HiIdx.to_int(); - int Lo = LoIdx.to_int(); - return this->range(Hi, Lo); - } - - INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> range() { - return this->range(_AP_W - 1, 0); - } - - INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> range() const { - return this->range(_AP_W - 1, 0); - } - - INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> operator()( - int Hi, int Lo) { - return this->range(Hi, Lo); - } - - INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> operator()( - int Hi, int Lo) const { - return this->range(Hi, Lo); - } - - template - INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> operator()( - const ap_int_base<_AP_W2, _AP_S2>& HiIdx, - const ap_int_base<_AP_W3, _AP_S3>& LoIdx) { - int Hi = HiIdx.to_int(); - int Lo = LoIdx.to_int(); - return this->range(Hi, Lo); - } - - template - INLINE af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> operator()( - const ap_int_base<_AP_W2, _AP_S2>& HiIdx, - const ap_int_base<_AP_W3, _AP_S3>& LoIdx) const { - int Hi = HiIdx.to_int(); - int Lo = LoIdx.to_int(); - return this->range(Hi, Lo); - } - - INLINE bool is_zero() const { return Base::V == 0; } - - INLINE bool is_neg() const { - if (_AP_S && _AP_ROOT_op_get_bit(Base::V, _AP_W - 1)) return true; - return false; - } - - INLINE int wl() const { return _AP_W; } - - INLINE int iwl() const { return _AP_I; } - - INLINE ap_q_mode q_mode() const { return _AP_Q; } - - INLINE ap_o_mode o_mode() const { return _AP_O; } - - INLINE int n_bits() const { return _AP_N; } - - // print a string representation of this number in the given radix. - // Radix support is 2, 8, 10, or 16. - // The result will include a prefix indicating the radix, except for decimal, - // where no prefix is needed. The default is to output a signed representation - // of signed numbers, or an unsigned representation of unsigned numbers. For - // non-decimal formats, this can be changed by the 'sign' argument. -#ifndef __SYNTHESIS__ - std::string to_string(unsigned char radix = 2, bool sign = _AP_S) const { - // XXX in autosim/autowrap.tcl "(${name}).to_string(2).c_str()" is used to - // initialize sc_lv, which seems incapable of handling format "-0b". - if (radix == 2) sign = false; - - std::string str; - str.clear(); - char step = 0; - bool isNeg = sign && (Base::V < 0); - - // Extend to take care of the -MAX case. - ap_fixed_base<_AP_W + 1, _AP_I + 1> tmp(*this); - if (isNeg) { - tmp = -tmp; - str += '-'; - } - std::string prefix; - switch (radix) { - case 2: - prefix = "0b"; - step = 1; - break; - case 8: - prefix = "0o"; - step = 3; - break; - case 16: - prefix = "0x"; - step = 4; - break; - default: - break; - } - - if (_AP_I > 0) { - // Note we drop the quantization and rounding flags here. The - // integer part is always in range, and the fractional part we - // want to drop. Also, the number is always positive, because - // of the absolute value above. - ap_int_base int_part; - // [1] [ I ] d [ W - I ] - // | | | - // | W-I 0 - // W - int_part.V = _AP_ROOT_op_get_range( - tmp.V, _AP_W - _AP_I, _AP_W); - str += int_part.to_string(radix, false); - } else { - str += prefix; - str += '0'; - } - - ap_fixed_base frac_part = tmp; - - if (radix == 10) { - if (frac_part != 0) { - str += "."; - while (frac_part != 0) { - char digit = (frac_part * radix).to_char(); - str += static_cast(digit + '0'); - frac_part *= radix; - } - } - } else { - if (frac_part != 0) { - str += "."; - for (signed i = _AP_W - _AP_I - 1; i >= 0; i -= step) { - char digit = frac_part.range(i, AP_MAX(0, i - step + 1)).to_char(); - // If we have a partial bit pattern at the end, then we need - // to put it in the high-order bits of 'digit'. - int offset = AP_MIN(0, i - step + 1); - digit <<= -offset; - str += digit < 10 ? static_cast(digit + '0') - : static_cast(digit - 10 + 'a'); - } - if (radix == 16) - str += "p0"; // C99 Hex constants are required to have an exponent. - } - } - return str; - } -#else - // XXX HLS will delete this in synthesis - INLINE char* to_string(unsigned char radix = 2, bool sign = _AP_S) const { - return 0; - } -#endif -}; // struct ap_fixed_base. - -template -INLINE void b_not( - ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { - ret.V = ~op.V; -} - -template -INLINE void b_and( - ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { - ret.V = op1.V & op2.V; -} - -template -INLINE void b_or( - ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { - ret.V = op1.V | op2.V; -} - -template -INLINE void b_xor( - ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op1, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { - ret.V = op1.V ^ op2.V; -} - -template -INLINE void neg( - ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - ap_fixed_base<_AP_W2 + !_AP_S2, _AP_I2 + !_AP_S2, true, _AP_Q2, _AP_O2, - _AP_N2> - t; - t.V = -op.V; - ret = t; -} - -template -INLINE void lshift( - ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, - int i) { - enum { - F2 = _AP_W2 - _AP_I2, - _AP_I3 = AP_MAX(_AP_I, _AP_I2), - _AP_W3 = _AP_I3 + F2, - }; - // wide buffer - ap_fixed_base<_AP_W3, _AP_I3, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> t; - t.V = op.V; - t.V <<= i; // FIXME overflow? - // handle quantization and overflow - ret = t; -} - -template -INLINE void rshift( - ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ret, - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op, - int i) { - enum { - F = _AP_W - _AP_I, - F2 = _AP_W2 - _AP_I2, - F3 = AP_MAX(F, F2), - _AP_W3 = _AP_I2 + F3, - sh = F - F2, - }; - // wide buffer - ap_fixed_base<_AP_W3, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> t; - t.V = op.V; - if (sh >= 0) - t.V <<= (int) sh; - t.V >>= i; - // handle quantization and overflow - ret = t; -} - -//// FIXME -//// These partial specialization ctors allow code like -//// char c = 'a'; -//// ap_fixed_base<8, 8, true> x(c); -//// but what bout ap_fixed_base<9, 9, true> y(c) ? -// - -#ifndef __SYNTHESIS__ -INLINE std::string scientificFormat(std::string& input) { - if (input.length() == 0) return input; - - size_t decPosition = input.find('.'); - if (decPosition == std::string::npos) decPosition = input.length(); - - size_t firstNonZeroPos = 0; - for (; input[firstNonZeroPos] > '9' || input[firstNonZeroPos] < '1'; - firstNonZeroPos++) - ; - - int exp; - if (firstNonZeroPos > decPosition) - exp = decPosition - firstNonZeroPos; - else - exp = decPosition - firstNonZeroPos - 1; - std::string expString = ""; - if (exp == 0) - ; - else if (exp < 0) { - expString += "e-"; - exp = -exp; - } else - expString += "e+"; - - if (exp < 10 && exp > 0) { - expString += '0'; - expString += (char)('0' + exp); - } else if (exp != 0) { - std::string tmp; - - std::ostringstream oss; - oss << exp; - - tmp = oss.str(); - expString += tmp; - } - - int lastNonZeroPos = (int)(input.length() - 1); - for (; lastNonZeroPos >= 0; --lastNonZeroPos) - if (input[lastNonZeroPos] <= '9' && input[lastNonZeroPos] > '0') break; - - std::string ans = ""; - ans += input[firstNonZeroPos]; - if (firstNonZeroPos != (size_t)lastNonZeroPos) { - ans += '.'; - for (int i = firstNonZeroPos + 1; i <= lastNonZeroPos; i++) - if (input[i] != '.') ans += input[i]; - } - - ans += expString; - return ans; -} - -INLINE std::string reduceToPrecision(std::string& input, int precision) { - bool isZero = true; - size_t inputLen = input.length(); - for (size_t i = 0; i < inputLen && isZero; i++) - if (input[i] != '.' && input[i] != '0') isZero = false; - if (isZero) return "0"; - - // Find the first valid number, skip '-' - int FirstNonZeroPos = 0; - int LastNonZeroPos = (int)inputLen - 1; - int truncBitPosition = 0; - size_t decPosition = input.find('.'); - for (; input[FirstNonZeroPos] < '1' || input[FirstNonZeroPos] > '9'; - FirstNonZeroPos++) - ; - - for (; input[LastNonZeroPos] < '1' || input[LastNonZeroPos] > '9'; - LastNonZeroPos--) - ; - - if (decPosition == std::string::npos) decPosition = inputLen; - // Count the valid number, to decide whether we need to truncate - if ((int)decPosition > LastNonZeroPos) { - if (LastNonZeroPos - FirstNonZeroPos + 1 <= precision) return input; - truncBitPosition = FirstNonZeroPos + precision; - } else if ((int)decPosition < FirstNonZeroPos) { // This is pure decimal - if (LastNonZeroPos - FirstNonZeroPos + 1 <= precision) { - if (FirstNonZeroPos - decPosition - 1 < 4) { - return input; - } else { - if (input[0] == '-') { - std::string tmp = input.substr(1, inputLen - 1); - return std::string("-") + scientificFormat(tmp); - } else - return scientificFormat(input); - } - } - truncBitPosition = FirstNonZeroPos + precision; - } else { - if (LastNonZeroPos - FirstNonZeroPos <= precision) return input; - truncBitPosition = FirstNonZeroPos + precision + 1; - } - - // duplicate the input string, we want to add "0" before the valid numbers - // This is easy for quantization, since we may change 9999 to 10000 - std::string ans = ""; - std::string dupInput = "0"; - if (input[0] == '-') { - ans += '-'; - dupInput += input.substr(1, inputLen - 1); - } else { - dupInput += input.substr(0, inputLen); - ++truncBitPosition; - } - - // Add 'carry' after truncation, if necessary - bool carry = dupInput[truncBitPosition] > '4'; - for (int i = truncBitPosition - 1; i >= 0 && carry; i--) { - if (dupInput[i] == '.') continue; - if (dupInput[i] == '9') - dupInput[i] = '0'; - else { - ++dupInput[i]; - carry = false; - } - } - - // bits outside precision range should be set to 0 - if (dupInput[0] == '1') - FirstNonZeroPos = 0; - else { - FirstNonZeroPos = 0; - while (dupInput[FirstNonZeroPos] < '1' || dupInput[FirstNonZeroPos] > '9') - ++FirstNonZeroPos; - } - - unsigned it = FirstNonZeroPos; - int NValidNumber = 0; - while (it < dupInput.length()) { - if (dupInput[it] == '.') { - ++it; - continue; - } - ++NValidNumber; - if (NValidNumber > precision) dupInput[it] = '0'; - ++it; - } - - // Here we wanted to adjust the truncate position and the value - decPosition = dupInput.find('.'); - if (decPosition == std::string::npos) // When this is integer - truncBitPosition = (int)dupInput.length(); - else - for (truncBitPosition = (int)(dupInput.length() - 1); truncBitPosition >= 0; - --truncBitPosition) { - if (dupInput[truncBitPosition] == '.') break; - if (dupInput[truncBitPosition] != '0') { - truncBitPosition++; - break; - } - } - - if (dupInput[0] == '1') - dupInput = dupInput.substr(0, truncBitPosition); - else - dupInput = dupInput.substr(1, truncBitPosition - 1); - - decPosition = dupInput.find('.'); - if (decPosition != std::string::npos) { - size_t it = 0; - for (it = decPosition + 1; dupInput[it] == '0'; it++) - ; - if (it - decPosition - 1 < 4) { - ans += dupInput; - return ans; - } else { - ans += scientificFormat(dupInput); - return ans; - } - } else if ((int)(dupInput.length()) <= precision) { - ans += dupInput; - return ans; - } - - ans += scientificFormat(dupInput); - return ans; -} - -template -INLINE void print( - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& x) { - if (_AP_I > 0) { - ap_int_base<_AP_I, _AP_S> p1; - p1.V = x.V >> (_AP_W - _AP_I); - print(p1.V); // print overlaod for .V should exit - } else { - printf("0"); - } - printf("."); - if (_AP_I < _AP_W) { - ap_int_base<_AP_W - _AP_I, false> p2; - p2.V = _AP_ROOT_op_get_range(x.V, 0, _AP_W - _AP_I); - print(p2.V, false); // print overlaod for .V should exit - } -} -#endif // ifndef __SYNTHESIS__ - -// XXX the following two functions have to exist in synthesis, -// as some old HLS Video Library code uses the ostream overload, -// although HLS will later delete I/O function call. - -/// Output streaming -//----------------------------------------------------------------------------- -// XXX apcc cannot handle global std::ios_base::Init() brought in by -#ifndef AP_AUTOCC -#ifndef __SYNTHESIS__ -template -INLINE std::ostream& operator<<( - std::ostream& out, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& x) { - // TODO support std::ios_base::fmtflags - unsigned width = out.width(); - unsigned precision = out.precision(); - char fill = out.fill(); - std::string str = x.to_string(10, _AP_S); - str = reduceToPrecision(str, precision); - if (width > str.length()) { - for (unsigned i = 0; i < width - str.length(); ++i) - out << fill; - } - out << str; - return out; -} -#endif // ifndef __SYNTHESIS__ - -/// Input streaming -// ----------------------------------------------------------------------------- -#ifndef __SYNTHESIS__ -template -INLINE std::istream& operator>>( - std::istream& in, - ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& x) { - double d; - in >> d; - x = ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>(d); - return in; -} -#endif -#endif // ifndef AP_AUTOCC - -/// Operators mixing Integers with ap_fixed_base -// ----------------------------------------------------------------------------- -#define AF_BIN_OP_WITH_INT_SF(BIN_OP, C_TYPE, _AP_W2, _AP_S2, RTYPE) \ - template \ - INLINE typename ap_fixed_base<_AP_W, _AP_I, _AP_S>::template RType< \ - _AP_W2, _AP_W2, _AP_S2>::RTYPE \ - operator BIN_OP( \ - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ - C_TYPE i_op) { \ - return op.operator BIN_OP(ap_int_base<_AP_W2, _AP_S2>(i_op)); \ - } - -#define AF_BIN_OP_WITH_INT(BIN_OP, C_TYPE, _AP_W2, _AP_S2, RTYPE) \ - template \ - INLINE typename ap_fixed_base<_AP_W, _AP_I, _AP_S>::template RType< \ - _AP_W2, _AP_W2, _AP_S2>::RTYPE \ - operator BIN_OP( \ - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ - C_TYPE i_op) { \ - return op.operator BIN_OP(ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op)); \ - } \ - template \ - INLINE typename ap_fixed_base<_AP_W, _AP_I, _AP_S>::template RType< \ - _AP_W2, _AP_W2, _AP_S2>::RTYPE \ - operator BIN_OP( \ - C_TYPE i_op, \ - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ - return ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op).operator BIN_OP(op); \ - } - -#define AF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE bool operator REL_OP( \ - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ - C_TYPE i_op) { \ - return op.operator REL_OP(ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op)); \ - } \ - template \ - INLINE bool operator REL_OP( \ - C_TYPE i_op, \ - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ - return ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op).operator REL_OP(op); \ - } - -#define AF_ASSIGN_OP_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& \ - operator ASSIGN_OP( \ - ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ - C_TYPE i_op) { \ - return op.operator ASSIGN_OP(ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op)); \ - } - -#define AF_ASSIGN_OP_WITH_INT_SF(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& \ - operator ASSIGN_OP( \ - ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ - C_TYPE i_op) { \ - return op.operator ASSIGN_OP(ap_int_base<_AP_W2, _AP_S2>(i_op)); \ - } - -#define ALL_AF_OP_WITH_INT(C_TYPE, BITS, SIGN) \ - AF_BIN_OP_WITH_INT(+, C_TYPE, (BITS), (SIGN), plus) \ - AF_BIN_OP_WITH_INT(-, C_TYPE, (BITS), (SIGN), minus) \ - AF_BIN_OP_WITH_INT(*, C_TYPE, (BITS), (SIGN), mult) \ - AF_BIN_OP_WITH_INT(/, C_TYPE, (BITS), (SIGN), div) \ - AF_BIN_OP_WITH_INT(&, C_TYPE, (BITS), (SIGN), logic) \ - AF_BIN_OP_WITH_INT(|, C_TYPE, (BITS), (SIGN), logic) \ - AF_BIN_OP_WITH_INT(^, C_TYPE, (BITS), (SIGN), logic) \ - AF_BIN_OP_WITH_INT_SF(>>, C_TYPE, (BITS), (SIGN), lhs) \ - AF_BIN_OP_WITH_INT_SF(<<, C_TYPE, (BITS), (SIGN), lhs) \ - \ - AF_ASSIGN_OP_WITH_INT(+=, C_TYPE, (BITS), (SIGN)) \ - AF_ASSIGN_OP_WITH_INT(-=, C_TYPE, (BITS), (SIGN)) \ - AF_ASSIGN_OP_WITH_INT(*=, C_TYPE, (BITS), (SIGN)) \ - AF_ASSIGN_OP_WITH_INT(/=, C_TYPE, (BITS), (SIGN)) \ - AF_ASSIGN_OP_WITH_INT(&=, C_TYPE, (BITS), (SIGN)) \ - AF_ASSIGN_OP_WITH_INT(|=, C_TYPE, (BITS), (SIGN)) \ - AF_ASSIGN_OP_WITH_INT(^=, C_TYPE, (BITS), (SIGN)) \ - AF_ASSIGN_OP_WITH_INT_SF(>>=, C_TYPE, (BITS), (SIGN)) \ - AF_ASSIGN_OP_WITH_INT_SF(<<=, C_TYPE, (BITS), (SIGN)) \ - \ - AF_REL_OP_WITH_INT(>, C_TYPE, (BITS), (SIGN)) \ - AF_REL_OP_WITH_INT(<, C_TYPE, (BITS), (SIGN)) \ - AF_REL_OP_WITH_INT(>=, C_TYPE, (BITS), (SIGN)) \ - AF_REL_OP_WITH_INT(<=, C_TYPE, (BITS), (SIGN)) \ - AF_REL_OP_WITH_INT(==, C_TYPE, (BITS), (SIGN)) \ - AF_REL_OP_WITH_INT(!=, C_TYPE, (BITS), (SIGN)) - -ALL_AF_OP_WITH_INT(bool, 1, false) -ALL_AF_OP_WITH_INT(char, 8, CHAR_IS_SIGNED) -ALL_AF_OP_WITH_INT(signed char, 8, true) -ALL_AF_OP_WITH_INT(unsigned char, 8, false) -ALL_AF_OP_WITH_INT(short, _AP_SIZE_short, true) -ALL_AF_OP_WITH_INT(unsigned short, _AP_SIZE_short, false) -ALL_AF_OP_WITH_INT(int, _AP_SIZE_int, true) -ALL_AF_OP_WITH_INT(unsigned int, _AP_SIZE_int, false) -ALL_AF_OP_WITH_INT(long, _AP_SIZE_long, true) -ALL_AF_OP_WITH_INT(unsigned long, _AP_SIZE_long, false) -ALL_AF_OP_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true) -ALL_AF_OP_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false) - -#undef ALL_AF_OP_WITH_INT -#undef AF_BIN_OP_WITH_INT -#undef AF_BIN_OP_WITH_INT_SF -#undef AF_ASSIGN_OP_WITH_INT -#undef AF_ASSIGN_OP_WITH_INT_SF -#undef AF_REL_OP_WITH_INT - -/* - * ********************************************************************** - * TODO - * There is no operator defined with float/double/long double, so that - * code like - * ap_fixed<8,4> a = 1.5f; - * a += 0.5f; - * will fail in compilation. - * Operator with warning about conversion might be wanted. - * ********************************************************************** - */ - -#define AF_BIN_OP_WITH_AP_INT(BIN_OP, RTYPE) \ - template \ - INLINE typename ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>::template RType< \ - _AP_W, _AP_I, _AP_S>::RTYPE \ - operator BIN_OP( \ - const ap_int_base<_AP_W2, _AP_S2>& i_op, \ - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ - return ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op).operator BIN_OP(op); \ - } \ - \ - template \ - INLINE typename ap_fixed_base<_AP_W, _AP_I, _AP_S>::template RType< \ - _AP_W2, _AP_W2, _AP_S2>::RTYPE \ - operator BIN_OP( \ - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ - const ap_int_base<_AP_W2, _AP_S2>& i_op) { \ - return op.operator BIN_OP(ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op)); \ - } - -#define AF_REL_OP_WITH_AP_INT(REL_OP) \ - template \ - INLINE bool operator REL_OP( \ - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ - const ap_int_base<_AP_W2, _AP_S2>& i_op) { \ - return op.operator REL_OP(ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op)); \ - } \ - \ - template \ - INLINE bool operator REL_OP( \ - const ap_int_base<_AP_W2, _AP_S2>& i_op, \ - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ - return ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op).operator REL_OP(op); \ - } - -#define AF_ASSIGN_OP_WITH_AP_INT(ASSIGN_OP) \ - template \ - INLINE ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& \ - operator ASSIGN_OP( \ - ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ - const ap_int_base<_AP_W2, _AP_S2>& i_op) { \ - return op.operator ASSIGN_OP(ap_fixed_base<_AP_W2, _AP_W2, _AP_S2>(i_op)); \ - } \ - \ - template \ - INLINE ap_int_base<_AP_W2, _AP_S2>& operator ASSIGN_OP( \ - ap_int_base<_AP_W2, _AP_S2>& i_op, \ - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ - return i_op.operator ASSIGN_OP(op.to_ap_int_base()); \ - } - -AF_BIN_OP_WITH_AP_INT(+, plus) -AF_BIN_OP_WITH_AP_INT(-, minus) -AF_BIN_OP_WITH_AP_INT(*, mult) -AF_BIN_OP_WITH_AP_INT(/, div) -AF_BIN_OP_WITH_AP_INT(&, logic) -AF_BIN_OP_WITH_AP_INT(|, logic) -AF_BIN_OP_WITH_AP_INT(^, logic) - -#undef AF_BIN_OP_WITH_AP_INT - -AF_ASSIGN_OP_WITH_AP_INT(+=) -AF_ASSIGN_OP_WITH_AP_INT(-=) -AF_ASSIGN_OP_WITH_AP_INT(*=) -AF_ASSIGN_OP_WITH_AP_INT(/=) -AF_ASSIGN_OP_WITH_AP_INT(&=) -AF_ASSIGN_OP_WITH_AP_INT(|=) -AF_ASSIGN_OP_WITH_AP_INT(^=) - -#undef AF_ASSIGN_OP_WITH_AP_INT - -AF_REL_OP_WITH_AP_INT(==) -AF_REL_OP_WITH_AP_INT(!=) -AF_REL_OP_WITH_AP_INT(>) -AF_REL_OP_WITH_AP_INT(>=) -AF_REL_OP_WITH_AP_INT(<) -AF_REL_OP_WITH_AP_INT(<=) - -#undef AF_REL_OP_WITH_AP_INT - -// Relational Operators with double -template -INLINE bool operator==( - double op1, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { - return op2.operator==(op1); -} - -template -INLINE bool operator!=( - double op1, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { - return op2.operator!=(op1); -} - -template -INLINE bool operator>( - double op1, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { - return op2.operator<(op1); -} - -template -INLINE bool operator>=( - double op1, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { - return op2.operator<=(op1); -} - -template -INLINE bool operator<( - double op1, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { - return op2.operator>(op1); -} - -template -INLINE bool operator<=( - double op1, - const ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op2) { - return op2.operator>=(op1); -} - -#endif // ifndef __cplusplus else - -#endif // ifndef __AP_FIXED_BASE_H__ else - -// -*- cpp -*- diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_fixed_ref.h b/model/AE_model/hls4ml_prj/firmware/ap_types/ap_fixed_ref.h deleted file mode 100644 index aefda0a..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_fixed_ref.h +++ /dev/null @@ -1,718 +0,0 @@ -/* - * Copyright 2011-2019 Xilinx, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AP_FIXED_REF_H__ -#define __AP_FIXED_REF_H__ - -#ifndef __AP_FIXED_H__ -#error "Only ap_fixed.h and ap_int.h can be included directly in user code." -#endif - -#ifndef __cplusplus -#error "C++ is required to include this header file" - -#else -#ifndef __SYNTHESIS__ -#include -#endif -/// Proxy class, which allows bit selection to be used as both rvalue (for -/// reading) and lvalue (for writing) -template -struct af_bit_ref { -#ifdef _MSC_VER -#pragma warning(disable : 4521 4522) -#endif - typedef ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> ref_type; - ref_type& d_bv; - int d_index; - - public: - INLINE af_bit_ref( - const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ref) - : d_bv(ref.d_bv), d_index(ref.d_index) { -#ifndef __SYNTHESIS__ - _AP_WARNING(d_index < 0, "Index of bit vector (%d) cannot be negative.", - d_index); - _AP_WARNING(d_index >= _AP_W, "Index of bit vector (%d) out of range (%d).", - d_index, _AP_W); -#endif - } - - INLINE af_bit_ref(ref_type* bv, int index = 0) : d_bv(*bv), d_index(index) {} - - INLINE af_bit_ref(const ref_type* bv, int index = 0) - : d_bv(*const_cast(bv)), d_index(index) {} - - /// convert operators. - INLINE operator bool() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); } - - /// @name assign operators - // @{ - INLINE af_bit_ref& operator=(bool val) { - d_bv.V = _AP_ROOT_op_set_bit(d_bv.V, d_index, val); - return *this; - } - - // Be explicit to prevent it from being deleted, as field d_bv - // is of reference type. - INLINE af_bit_ref& operator=(const af_bit_ref& val) { - return operator=(bool(val)); - } - - template - INLINE af_bit_ref& operator=( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - return operator=(bool(val)); - } - - template - INLINE af_bit_ref& operator=(const ap_bit_ref<_AP_W2, _AP_S2>& val) { - return operator=(bool(val)); - } - - template - INLINE af_bit_ref& operator=(const ap_int_base<_AP_W2, _AP_S2>& val) { - return operator=(val != 0); - } - - template - INLINE af_bit_ref& operator=(const ap_range_ref<_AP_W2, _AP_S2>& val) { - return operator=(ap_int_base<_AP_W2, false>(val)); - } - - template - INLINE af_bit_ref& operator=( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - return operator=(ap_int_base<_AP_W2, false>(val)); - } - - template - INLINE af_bit_ref& operator=( - const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { - return operator=(ap_int_base<_AP_W2 + _AP_W3, false>(val)); - } - // @} - - /// @name concatenate operators - // @{ - template - INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(ap_int_base<_AP_W2, _AP_S2> &op) { - return ap_concat_ref<1, af_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> >( - *this, op); - } - - template - INLINE ap_concat_ref<1, af_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > operator,( - const ap_bit_ref<_AP_W2, _AP_S2> &op) { - return ap_concat_ref<1, af_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> >(*this, - op); - } - - template - INLINE ap_concat_ref<1, af_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > - operator,(const ap_range_ref<_AP_W2, _AP_S2> &op) { - return ap_concat_ref<1, af_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> >( - *this, op); - } - - template - INLINE ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, - ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > - operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { - return ap_concat_ref<1, af_bit_ref, _AP_W2 + _AP_W3, - ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, - op); - } - - template - INLINE ap_concat_ref< - 1, af_bit_ref, _AP_W2, - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > - operator,( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &op) { - return ap_concat_ref< - 1, af_bit_ref, _AP_W2, - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, - op); - } - - template - INLINE ap_concat_ref<1, af_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, - _AP_Q2, _AP_O2, _AP_N2> > - operator,( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &op) { - return ap_concat_ref<1, af_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, - _AP_Q2, _AP_O2, _AP_N2> >( - *this, - const_cast&>( - op)); - } - // @} - - /// @name comparison - // @{ - template - INLINE bool operator==( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - return get() == op.get(); - } - - template - INLINE bool operator!=( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - return get() != op.get(); - } - // @} - - INLINE bool operator~() const { - bool bit = _AP_ROOT_op_get_bit(d_bv.V, d_index); - return bit ? false : true; - } - - INLINE bool get() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); } - - INLINE int length() const { return 1; } - -#ifndef __SYNTHESIS__ - std::string to_string() const { return get() ? "1" : "0"; } -#else - // XXX HLS will delete this in synthesis - INLINE char* to_string() const { return 0; } -#endif -}; // struct af_bit_ref - -// XXX apcc cannot handle global std::ios_base::Init() brought in by -#ifndef AP_AUTOCC -#ifndef __SYNTHESIS__ -template -INLINE std::ostream& operator<<( - std::ostream& os, - const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& x) { - os << x.to_string(); - return os; -} -#endif // ifndef __SYNTHESIS__ -#endif // ifndef AP_AUTOCC - -/// Range (slice) reference. -template -struct af_range_ref { -#ifdef _MSC_VER -#pragma warning(disable : 4521 4522) -#endif - typedef ap_fixed_base<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> ref_type; - ref_type& d_bv; - int l_index; - int h_index; - - public: - /// copy ctor - INLINE af_range_ref( - const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& ref) - : d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} - - /// ctor from ap_fixed_base, higher and lower bound. - /** if h is less than l, the bits selected will be returned in reverse order. - */ - INLINE af_range_ref(ref_type* bv, int h, int l) - : d_bv(*bv), l_index(l), h_index(h) { -#ifndef __SYNTHESIS__ - _AP_WARNING(h < 0 || l < 0, - "Higher bound(%d) and lower(%d) bound cannot be negative.", h, - l); - _AP_WARNING(h >= _AP_W || l >= _AP_W, - "Higher bound(%d) or lower(%d) bound out of range.", h, l); - _AP_WARNING(h < l, "The bits selected will be returned in reverse order."); -#endif - } - - INLINE af_range_ref(const ref_type* bv, int h, int l) - : d_bv(*const_cast(bv)), l_index(l), h_index(h) { -#ifndef __SYNTHESIS__ - _AP_WARNING(h < 0 || l < 0, - "Higher bound(%d) and lower(%d) bound cannot be negative.", h, - l); - _AP_WARNING(h >= _AP_W || l >= _AP_W, - "Higher bound(%d) or lower(%d) bound out of range.", h, l); - _AP_WARNING(h < l, "The bits selected will be returned in reverse order."); -#endif - } - - /// @name assign operators - // @{ - -#define ASSIGN_CTYPE_TO_AF_RANGE(DATA_TYPE) \ - INLINE af_range_ref& operator=(const DATA_TYPE val) { \ - ap_int_base<_AP_W, false> loc(val); \ - d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, loc.V); \ - return *this; \ - } - - ASSIGN_CTYPE_TO_AF_RANGE(bool) - ASSIGN_CTYPE_TO_AF_RANGE(char) - ASSIGN_CTYPE_TO_AF_RANGE(signed char) - ASSIGN_CTYPE_TO_AF_RANGE(unsigned char) - ASSIGN_CTYPE_TO_AF_RANGE(short) - ASSIGN_CTYPE_TO_AF_RANGE(unsigned short) - ASSIGN_CTYPE_TO_AF_RANGE(int) - ASSIGN_CTYPE_TO_AF_RANGE(unsigned int) - ASSIGN_CTYPE_TO_AF_RANGE(long) - ASSIGN_CTYPE_TO_AF_RANGE(unsigned long) - ASSIGN_CTYPE_TO_AF_RANGE(ap_slong) - ASSIGN_CTYPE_TO_AF_RANGE(ap_ulong) -#if _AP_ENABLE_HALF_ == 1 - ASSIGN_CTYPE_TO_AF_RANGE(half) -#endif - ASSIGN_CTYPE_TO_AF_RANGE(float) - ASSIGN_CTYPE_TO_AF_RANGE(double) -#undef ASSIGN_CTYPE_TO_AF_RANGE - - /// assgin using a string. XXX crucial for cosim. - INLINE af_range_ref& operator=(const char* val) { - const ap_int_base<_AP_W, false> tmp(val); // XXX figure out radix - d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V); - return *this; - } - - /// assign from ap_int_base. - // NOTE Base of other assgin operators. - template - INLINE af_range_ref& operator=(const ap_int_base<_AP_W3, _AP_S3>& val) { - d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, val.V); - return *this; - } - - /// assign from range reference to ap_int_base. - template - INLINE af_range_ref& operator=(const ap_range_ref<_AP_W2, _AP_S2>& val) { - const ap_int_base<_AP_W2, false> tmp(val); - return operator=(tmp); - } - - /// assign from bit reference to ap_int_base.. - template - INLINE af_range_ref& operator=(const ap_bit_ref<_AP_W2, _AP_S2>& val) { - const ap_int_base<1, false> tmp((bool)val); - return operator=(tmp); - } - - /// assgin from ap_fixed_base. - template - INLINE af_range_ref& operator=( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& - val) { - d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, val.V); - return *this; - } - - /// copy assgin. - // XXX This has to be explicit, otherwise it will be deleted, as d_bv is - // of reference type. - INLINE af_range_ref& operator=(const af_range_ref& val) { - ap_int_base<_AP_W, false> tmp(val); - return operator=(tmp); - } - - /// assign from range reference to ap_fixed_base. - template - INLINE af_range_ref& operator=( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - ap_int_base<_AP_W2, false> tmp(val); - return operator=(tmp); - } - - /// assign from bit reference to ap_fixed_base. - template - INLINE af_range_ref& operator=( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - ap_int_base<1, false> tmp((bool)val); - return operator=(tmp); - } - - /// assign from compound reference. - template - INLINE af_range_ref& operator=( - const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { - const ap_int_base<_AP_W2 + _AP_W3, false> tmp(val); - return operator=(tmp); - } - // @} - - /// @name comparison operators with ap_range_ref. - // @{ - template - INLINE bool operator==(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - ap_int_base<_AP_W, false> lop(*this); - ap_int_base<_AP_W2, false> rop(op2); - return lop == rop; - } - - template - INLINE bool operator!=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - return !(operator==(op2)); - } - - template - INLINE bool operator<(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - ap_int_base<_AP_W, false> lop(*this); - ap_int_base<_AP_W2, false> rop(op2); - return lop < rop; - } - - template - INLINE bool operator>(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - ap_int_base<_AP_W, false> lop(*this); - ap_int_base<_AP_W2, false> rop(op2); - return lop > rop; - } - - template - INLINE bool operator<=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - return !(operator>(op2)); - } - - template - INLINE bool operator>=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - return !(operator<(op2)); - } - // @} - - /// @name comparison operators with af_range_ref. - // @{ - template - INLINE bool operator==( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { - ap_int_base<_AP_W, false> lop(*this); - ap_int_base<_AP_W2, false> rop(op2); - return lop == rop; - } - - template - INLINE bool operator!=( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { - return !(operator==(op2)); - } - - template - INLINE bool operator<( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { - ap_int_base<_AP_W, false> lop(*this); - ap_int_base<_AP_W2, false> rop(op2); - return lop < rop; - } - - template - INLINE bool operator>( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { - ap_int_base<_AP_W, false> lop(*this); - ap_int_base<_AP_W2, false> rop(op2); - return lop > rop; - } - - template - INLINE bool operator<=( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { - return !(operator>(op2)); - } - - template - INLINE bool operator>=( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op2) { - return !(operator<(op2)); - } - // @} - - /// @name concatenate operators. - /// @{ - /// concatenate with ap_int_base. - template - INLINE - ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(ap_int_base<_AP_W2, _AP_S2> &op) { - return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, - ap_int_base<_AP_W2, _AP_S2> >(*this, op); - } - - /// concatenate with ap_bit_ref. - template - INLINE ap_concat_ref<_AP_W, af_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > - operator,(const ap_bit_ref<_AP_W2, _AP_S2> &op) { - return ap_concat_ref<_AP_W, af_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> >( - *this, const_cast&>(op)); - } - - /// concatenate with ap_bit_ref. - template - INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > - operator,(const ap_range_ref<_AP_W2, _AP_S2> &op) { - return ap_concat_ref<_AP_W, af_range_ref, _AP_W2, - ap_range_ref<_AP_W2, _AP_S2> >( - *this, const_cast&>(op)); - } - - /// concatenate with ap_concat_ref. - template - INLINE ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, - ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > - operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &op) { - return ap_concat_ref<_AP_W, af_range_ref, _AP_W2 + _AP_W3, - ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >( - *this, const_cast&>(op)); - } - - /// concatenate with another af_range_ref. - template - INLINE - ap_concat_ref<_AP_W, af_range_ref, _AP_W2, - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > - operator,(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> - &op) { - return ap_concat_ref< - _AP_W, af_range_ref, _AP_W2, - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( - *this, - const_cast&>( - op)); - } - - /// concatenate with another af_bit_ref. - template - INLINE - ap_concat_ref<_AP_W, af_range_ref, 1, - af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > - operator,( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &op) { - return ap_concat_ref< - _AP_W, af_range_ref, 1, - af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( - *this, - const_cast&>( - op)); - } - // @} - - INLINE operator ap_ulong() const { - ap_int_base<_AP_W, false> ret; - ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); - return ret.to_uint64(); - } - - INLINE operator ap_int_base<_AP_W, false>() const { - ap_int_base<_AP_W, false> ret; - ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); - return ret; - } - - INLINE ap_int_base<_AP_W, false> to_ap_int_base() const { - ap_int_base<_AP_W, false> ret; - ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); - return ret; - } - - // used in ap_fixed_base::to_string() - INLINE char to_char() const { - return (char)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE int to_int() const { - return (int)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE unsigned to_uint() const { - return (unsigned)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE long to_long() const { - return (long)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE unsigned long to_ulong() const { - return (unsigned long)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE ap_slong to_int64() const { - return (ap_slong)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE ap_ulong to_uint64() const { - return (ap_ulong)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE ap_int_base<_AP_W, false> get() const { - ap_int_base<_AP_W, false> ret; - ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); - return ret; - } - - template - INLINE void set(const ap_int_base<_AP_W2, false>& val) { - d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, val.V); - } - - INLINE int length() const { - return h_index >= l_index ? h_index - l_index + 1 : l_index - h_index + 1; - } - -#ifndef __SYNTHESIS__ - std::string to_string(signed char rd = 2) const { - ap_int_base<_AP_W, false> ret; - ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); - return ret.to_string(rd); - } -#else - // XXX HLS will delete this in synthesis - INLINE char* to_string(signed char rd = 2) const { - return 0; - } -#endif -}; // struct af_range_ref - -// XXX apcc cannot handle global std::ios_base::Init() brought in by -#ifndef AP_AUTOCC -#ifndef __SYNTHESIS__ -template -INLINE std::ostream& operator<<( - std::ostream& os, - const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& x) { - os << x.to_string(); - return os; -} -#endif -#endif // ifndef AP_AUTOCC - -#define AF_REF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE bool operator REL_OP( \ - const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ - C_TYPE op2) { \ - return ap_int_base<_AP_W, false>(op) \ - REL_OP ap_int_base<_AP_W2, _AP_S2>(op2); \ - } \ - \ - template \ - INLINE bool operator REL_OP( \ - C_TYPE op2, \ - const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ - return ap_int_base<_AP_W2, _AP_S2>(op2) \ - REL_OP ap_int_base<_AP_W, false>(op); \ - } \ - \ - template \ - INLINE bool operator REL_OP( \ - const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ - C_TYPE op2) { \ - return bool(op) REL_OP op2; \ - } \ - \ - template \ - INLINE bool operator REL_OP( \ - C_TYPE op2, \ - const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ - return op2 REL_OP bool(op); \ - } - -#define AF_REF_REL_OPS_WITH_INT(C_TYPE, _AP_W2, _AP_S2) \ - AF_REF_REL_OP_WITH_INT(>, C_TYPE, (_AP_W2), (_AP_S2)) \ - AF_REF_REL_OP_WITH_INT(<, C_TYPE, (_AP_W2), (_AP_S2)) \ - AF_REF_REL_OP_WITH_INT(>=, C_TYPE, (_AP_W2), (_AP_S2)) \ - AF_REF_REL_OP_WITH_INT(<=, C_TYPE, (_AP_W2), (_AP_S2)) \ - AF_REF_REL_OP_WITH_INT(==, C_TYPE, (_AP_W2), (_AP_S2)) \ - AF_REF_REL_OP_WITH_INT(!=, C_TYPE, (_AP_W2), (_AP_S2)) - -AF_REF_REL_OPS_WITH_INT(bool, 1, false) -AF_REF_REL_OPS_WITH_INT(char, 8, CHAR_IS_SIGNED) -AF_REF_REL_OPS_WITH_INT(signed char, 8, true) -AF_REF_REL_OPS_WITH_INT(unsigned char, 8, false) -AF_REF_REL_OPS_WITH_INT(short, _AP_SIZE_short, true) -AF_REF_REL_OPS_WITH_INT(unsigned short, _AP_SIZE_short, false) -AF_REF_REL_OPS_WITH_INT(int, _AP_SIZE_int, true) -AF_REF_REL_OPS_WITH_INT(unsigned int, _AP_SIZE_int, false) -AF_REF_REL_OPS_WITH_INT(long, _AP_SIZE_long, true) -AF_REF_REL_OPS_WITH_INT(unsigned long, _AP_SIZE_long, false) -AF_REF_REL_OPS_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true) -AF_REF_REL_OPS_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false) - -#undef AF_REF_REL_OP_INT -#undef AF_REF_REL_OPS_WITH_INT - -#define AF_REF_REL_OP_WITH_AP_INT(REL_OP) \ - template \ - INLINE bool operator REL_OP( \ - const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ - const ap_int_base<_AP_W2, _AP_S>& op2) { \ - return ap_int_base<_AP_W, false>(op) REL_OP op2; \ - } \ - template \ - INLINE bool operator REL_OP( \ - const ap_int_base<_AP_W2, _AP_S2>& op2, \ - const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ - return op2 REL_OP ap_int_base<_AP_W, false>(op); \ - } \ - template \ - INLINE bool operator REL_OP( \ - const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op, \ - const ap_int_base<_AP_W2, _AP_S2>& op2) { \ - return ap_int_base<1, false>(op) REL_OP op2; \ - } \ - template \ - INLINE bool operator REL_OP( \ - const ap_int_base<_AP_W2, _AP_S2>& op2, \ - const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N>& op) { \ - return op2 REL_OP ap_int_base<1, false>(op); \ - } - -AF_REF_REL_OP_WITH_AP_INT(>) -AF_REF_REL_OP_WITH_AP_INT(<) -AF_REF_REL_OP_WITH_AP_INT(>=) -AF_REF_REL_OP_WITH_AP_INT(<=) -AF_REF_REL_OP_WITH_AP_INT(==) -AF_REF_REL_OP_WITH_AP_INT(!=) - -#endif // ifndef __cplusplus - -#endif // ifndef __AP_FIXED_REF_H__ - -// -*- cpp -*- diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_fixed_special.h b/model/AE_model/hls4ml_prj/firmware/ap_types/ap_fixed_special.h deleted file mode 100644 index 0f7a9f7..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_fixed_special.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright 2011-2019 Xilinx, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AP_FIXED_SPECIAL_H__ -#define __AP_FIXED_SPECIAL_H__ - -#ifndef __AP_FIXED_H__ -#error "Only ap_fixed.h and ap_int.h can be included directly in user code." -#endif - -#ifndef __SYNTHESIS__ -#include -#include -#endif -// FIXME AP_AUTOCC cannot handle many standard headers, so declare instead of -// include. -// #include -namespace std { -template class complex; -} - -/* - TODO: Modernize the code using C++11/C++14 - 1. constexpr http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0415r0.html - 2. move constructor -*/ - -namespace std { -/* - Specialize std::complex to zero initialization ap_fixed. - - To reduce the area cost, ap_fixed is not zero initialized, just like basic - types float or double. However, libstdc++ provides specialization for float, - double and long double, initializing image part to 0 when not specified. - - This has become a difficulty in switching legacy code from these C types to - ap_fixed. To ease the tranform of legacy code, we have to implement - specialization of std::complex<> for our type. - - As ap_fixed is a template, it is impossible to specialize only the methods - that causes default initialization of value type in std::complex<>. An - explicit full specialization of the template class has to be done, covering - all the member functions and operators of std::complex<> as specified - in standard 26.2.4 and 26.2.5. -*/ -template -class complex > { - public: - typedef ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N> _Tp; - typedef _Tp value_type; - - // 26.2.4/1 - // Constructor without argument - // Default initialize, so that in dataflow, the variable is only written once. - complex() : _M_real(_Tp()), _M_imag(_Tp()) {} - // Constructor with ap_fixed. - // Zero initialize image part when not specified, so that `C(1) == C(1,0)` - complex(const _Tp &__r, const _Tp &__i = _Tp(0)) - : _M_real(__r), _M_imag(__i) {} - - // Constructor with another complex number - template - complex(const complex<_Up> &__z) : _M_real(__z.real()), _M_imag(__z.imag()) {} - -#if __cplusplus >= 201103L - const _Tp& real() const { return _M_real; } - const _Tp& imag() const { return _M_imag; } -#else - _Tp& real() { return _M_real; } - const _Tp& real() const { return _M_real; } - _Tp& imag() { return _M_imag; } - const _Tp& imag() const { return _M_imag; } -#endif - - void real(_Tp __val) { _M_real = __val; } - - void imag(_Tp __val) { _M_imag = __val; } - - // Assign this complex number with ap_fixed. - // Zero initialize image poarrt, so that `C c; c = 1; c == C(1,0);` - complex<_Tp> &operator=(const _Tp __t) { - _M_real = __t; - _M_imag = _Tp(0); - return *this; - } - - // 26.2.5/1 - // Add ap_fixed to this complex number. - complex<_Tp> &operator+=(const _Tp &__t) { - _M_real += __t; - return *this; - } - - // 26.2.5/3 - // Subtract ap_fixed from this complex number. - complex<_Tp> &operator-=(const _Tp &__t) { - _M_real -= __t; - return *this; - } - - // 26.2.5/5 - // Multiply this complex number by ap_fixed. - complex<_Tp> &operator*=(const _Tp &__t) { - _M_real *= __t; - _M_imag *= __t; - return *this; - } - - // 26.2.5/7 - // Divide this complex number by ap_fixed. - complex<_Tp> &operator/=(const _Tp &__t) { - _M_real /= __t; - _M_imag /= __t; - return *this; - } - - // Assign complex number to this complex number. - template - complex<_Tp> &operator=(const complex<_Up> &__z) { - _M_real = __z.real(); - _M_imag = __z.imag(); - return *this; - } - - // 26.2.5/9 - // Add complex number to this. - template - complex<_Tp> &operator+=(const complex<_Up> &__z) { - _M_real += __z.real(); - _M_imag += __z.imag(); - return *this; - } - - // 26.2.5/11 - // Subtract complex number from this. - template - complex<_Tp> &operator-=(const complex<_Up> &__z) { - _M_real -= __z.real(); - _M_imag -= __z.imag(); - return *this; - } - - // 26.2.5/13 - // Multiply this by complex number. - template - complex<_Tp> &operator*=(const complex<_Up> &__z) { - const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag(); - _M_imag = _M_real * __z.imag() + _M_imag * __z.real(); - _M_real = __r; - return *this; - } - - // 26.2.5/15 - // Divide this by complex number. - template - complex<_Tp> &operator/=(const complex<_Up> &__z) { - complex<_Tp> cj (__z.real(), -__z.imag()); - complex<_Tp> a = (*this) * cj; - complex<_Tp> b = cj * __z; - _M_real = a.real() / b.real(); - _M_imag = a.imag() / b.real(); - return *this; - } - - private: - _Tp _M_real; - _Tp _M_imag; - -}; // class complex > - -/* - Non-member operations - These operations are not required by standard in 26.2.6, but libstdc++ - defines them for - float, double or long double's specialization. -*/ -// Compare complex number with ap_fixed. -template -inline bool operator==( - const complex > &__x, - const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N> &__y) { - return __x.real() == __y && - __x.imag() == 0; -} - -// Compare ap_fixed with complex number. -template -inline bool operator==( - const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N> &__x, - const complex > &__y) { - return __x == __y.real() && - 0 == __y.imag(); -} - -// Compare complex number with ap_fixed. -template -inline bool operator!=( - const complex > &__x, - const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N> &__y) { - return __x.real() != __y || - __x.imag() != 0; -} - -// Compare ap_fixed with complex number. -template -inline bool operator!=( - const ap_fixed<_AP_W, _AP_I, _AP_Q, _AP_O, _AP_N> &__x, - const complex > &__y) { - return __x != __y.real() || - 0 != __y.imag(); -} - -} // namespace std - -#endif // ifndef __AP_FIXED_SPECIAL_H__ - -// -*- cpp -*- diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_int.h b/model/AE_model/hls4ml_prj/firmware/ap_types/ap_int.h deleted file mode 100644 index db3044d..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_int.h +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright 2011-2019 Xilinx, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AP_INT_H__ -#define __AP_INT_H__ - -#include -#include -#include - -//--------------------------------------------------------------- - -/// Sign Arbitrary Precision Type. -template -struct ap_int : ap_int_base<_AP_W, true> { - typedef ap_int_base<_AP_W, true> Base; - // Constructor - INLINE ap_int() : Base() {} - - // Copy ctor - INLINE ap_int(const ap_int& op) { Base::V = op.V; } - - template - INLINE ap_int(const ap_int<_AP_W2>& op) { - Base::V = op.V; - } - - template - INLINE ap_int(const volatile ap_int<_AP_W2>& op) { - Base::V = op.V; - } - - template - INLINE ap_int(const ap_uint<_AP_W2>& op) { - Base::V = op.V; - } - - template - INLINE ap_int(const volatile ap_uint<_AP_W2>& op) { - Base::V = op.V; - } - - template - INLINE ap_int(const ap_range_ref<_AP_W2, _AP_S2>& ref) : Base(ref) {} - - template - INLINE ap_int(const ap_bit_ref<_AP_W2, _AP_S2>& ref) : Base(ref) {} - - template - INLINE ap_int(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref) - : Base(ref) {} - - template - INLINE ap_int(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base((ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>)op) {} - - template - INLINE ap_int(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base((ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>)op) { - } - - template - INLINE ap_int( - const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base((ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>)op) {} - - template - INLINE ap_int( - const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base((ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>)op) { - } - - template - INLINE ap_int(const ap_int_base<_AP_W2, _AP_S2>& op) { - Base::V = op.V; - } - - template - INLINE ap_int( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base(op) {} - - template - INLINE ap_int( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base(op) {} - - template - INLINE ap_int( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base(op) {} - -#define CTOR(TYPE) \ - INLINE ap_int(TYPE val) { Base::V = val; } - CTOR(bool) - CTOR(char) - CTOR(signed char) - CTOR(unsigned char) - CTOR(short) - CTOR(unsigned short) - CTOR(int) - CTOR(unsigned int) - CTOR(long) - CTOR(unsigned long) - CTOR(ap_slong) - CTOR(ap_ulong) -#undef CTOR - ap_int(double val) : Base(val) {} - ap_int(float val) : Base(val) {} -#if _AP_ENABLE_HALF_ == 1 - ap_int(half val) : Base(val) {} -#endif - - // ap_int_base will guess radix if radix is not provided. - INLINE ap_int(const char* s) : Base(s) {} - - INLINE ap_int(const char* s, signed char rd) : Base(s, rd) {} - - // Assignment - /* ctor will be used when right is not of proper type. */ - - INLINE ap_int& operator=(const ap_int<_AP_W>& op2) { - Base::V = op2.V; - return *this; - } - - /* cannot bind volatile reference to non-volatile type. */ - INLINE ap_int& operator=(const volatile ap_int<_AP_W>& op2) { - Base::V = op2.V; - return *this; - } - - /* cannot return volatile *this. */ - INLINE void operator=(const ap_int<_AP_W>& op2) volatile { Base::V = op2.V; } - - INLINE void operator=(const volatile ap_int<_AP_W>& op2) volatile { - Base::V = op2.V; - } - -}; // struct ap_int. - -//--------------------------------------------------------------- - -/// Unsigned Arbitrary Precision Type. -template -struct ap_uint : ap_int_base<_AP_W, false> { - typedef ap_int_base<_AP_W, false> Base; - // Constructor - INLINE ap_uint() : Base() {} - - // Copy ctor - INLINE ap_uint(const ap_uint& op) { Base::V = op.V; } - - template - INLINE ap_uint(const ap_uint<_AP_W2>& op) { - Base::V = op.V; - } - - template - INLINE ap_uint(const ap_int<_AP_W2>& op) { - Base::V = op.V; - } - - template - INLINE ap_uint(const volatile ap_uint<_AP_W2>& op) { - Base::V = op.V; - } - - template - INLINE ap_uint(const volatile ap_int<_AP_W2>& op) { - Base::V = op.V; - } - - template - INLINE ap_uint(const ap_range_ref<_AP_W2, _AP_S2>& ref) : Base(ref) {} - - template - INLINE ap_uint(const ap_bit_ref<_AP_W2, _AP_S2>& ref) : Base(ref) {} - - template - INLINE ap_uint(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref) - : Base(ref) {} - - template - INLINE ap_uint(const ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base((ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>)op) {} - - template - INLINE ap_uint(const ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base((ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>)op) { - } - - template - INLINE ap_uint( - const volatile ap_fixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base((ap_fixed_base<_AP_W2, _AP_I2, true, _AP_Q2, _AP_O2, _AP_N2>)op) {} - - template - INLINE ap_uint( - const volatile ap_ufixed<_AP_W2, _AP_I2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base((ap_fixed_base<_AP_W2, _AP_I2, false, _AP_Q2, _AP_O2, _AP_N2>)op) { - } - - template - INLINE ap_uint(const ap_int_base<_AP_W2, _AP_S2>& op) { - Base::V = op.V; - } - - template - INLINE ap_uint( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base(op) {} - - template - INLINE ap_uint( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base(op) {} - - template - INLINE ap_uint( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) - : Base(op) {} - -#define CTOR(TYPE) \ - INLINE ap_uint(TYPE val) { Base::V = val; } - CTOR(bool) - CTOR(char) - CTOR(signed char) - CTOR(unsigned char) - CTOR(short) - CTOR(unsigned short) - CTOR(int) - CTOR(unsigned int) - CTOR(long) - CTOR(unsigned long) - CTOR(ap_slong) - CTOR(ap_ulong) -#undef CTOR - ap_uint(double val) : Base(val) {} - ap_uint(float val) : Base(val) {} -#if _AP_ENABLE_HALF_ == 1 - ap_uint(half val) : Base(val) {} -#endif - - // ap_int_base will guess radix if radix is not provided. - INLINE ap_uint(const char* s) : Base(s) {} - - INLINE ap_uint(const char* s, signed char rd) : Base(s, rd) {} - - // Assignment - /* XXX ctor will be used when right is not of proper type. */ - - INLINE ap_uint& operator=(const ap_uint<_AP_W>& op2) { - Base::V = op2.V; - return *this; - } - - /* cannot bind volatile reference to non-volatile type. */ - INLINE ap_uint& operator=(const volatile ap_uint<_AP_W>& op2) { - Base::V = op2.V; - return *this; - } - - /* cannot return volatile *this. */ - INLINE void operator=(const ap_uint<_AP_W>& op2) volatile { Base::V = op2.V; } - - INLINE void operator=(const volatile ap_uint<_AP_W>& op2) volatile { - Base::V = op2.V; - } - -}; // struct ap_uint. - -#define ap_bigint ap_int -#define ap_biguint ap_uint - -#if !defined(__SYNTHESIS__) && (defined(SYSTEMC_H) || defined(SYSTEMC_INCLUDED)) -// XXX sc_trace overload for ap_fixed is already included in -// "ap_sysc/ap_sc_extras.h", so do not define in synthesis. -template -INLINE void sc_trace(sc_core::sc_trace_file* tf, const ap_int<_AP_W>& op, - const std::string& name) { - if (tf) tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); -} - -template -INLINE void sc_trace(sc_core::sc_trace_file* tf, const ap_uint<_AP_W>& op, - const std::string& name) { - if (tf) tf->trace(sc_dt::sc_lv<_AP_W>(op.to_string(2).c_str()), name); -} -#endif // System C sim - -#include - -#endif // ifndef __AP_INT_H__ else - -// FIXME user should include ap_fixed.h when using ap_fixed. -// to avoid circular inclusion, must check whether this is required by -// ap_fixed.h -#ifndef __AP_FIXED_H__ -#include -#endif - -// -*- cpp -*- diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_int_base.h b/model/AE_model/hls4ml_prj/firmware/ap_types/ap_int_base.h deleted file mode 100644 index 091552a..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_int_base.h +++ /dev/null @@ -1,1885 +0,0 @@ -/* - * Copyright 2011-2019 Xilinx, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AP_INT_BASE_H__ -#define __AP_INT_BASE_H__ - -#ifndef __AP_INT_H__ -#error "Only ap_fixed.h and ap_int.h can be included directly in user code." -#endif - -#ifndef __cplusplus -#error "C++ is required to include this header file" -#else - -#include -#ifndef __SYNTHESIS__ -#if _AP_ENABLE_HALF_ == 1 -#include -#endif -#include -#include -#endif - -/* ---------------------------------------------------------------- - * ap_int_base: AutoPilot integer/Arbitrary precision integer. - * ---------------------------------------------------------------- - */ - -/* helper trait. Selecting the smallest C type that can hold the value, - * return 64 bit C type if not possible. - */ -template -struct retval; - -// at least 64 bit -template -struct retval<_AP_N, true> { - typedef ap_slong Type; -}; - -template -struct retval<_AP_N, false> { - typedef ap_ulong Type; -}; - -// at least 8 bit -template <> -struct retval<1, true> { - typedef signed char Type; -}; - -template <> -struct retval<1, false> { - typedef unsigned char Type; -}; - -// at least 16 bit -template <> -struct retval<2, true> { - typedef short Type; -}; - -template <> -struct retval<2, false> { - typedef unsigned short Type; -}; - -// at least 32 bit -template <> -struct retval<3, true> { - typedef long Type; -}; - -template <> -struct retval<3, false> { - typedef unsigned long Type; -}; - -template <> -struct retval<4, true> { - typedef long Type; -}; - -template <> -struct retval<4, false> { - typedef unsigned long Type; -}; - -// trait for letting base class to return derived class. -// Notice that derived class template is incomplete, and we cannot use -// the member of the derived class. -template -struct _ap_int_factory; -template -struct _ap_int_factory<_AP_W2,true> { typedef ap_int<_AP_W2> type; }; -template -struct _ap_int_factory<_AP_W2,false> { typedef ap_uint<_AP_W2> type; }; - -template -struct ap_int_base : public _AP_ROOT_TYPE<_AP_W, _AP_S> { - public: - typedef _AP_ROOT_TYPE<_AP_W, _AP_S> Base; - - /* ap_int_base<_AP_W, _AP_S, true> - * typedef typename retval<(_AP_W + 7) / 8, _AP_S>::Type RetType; - * - * ap_int_base<_AP_W, _AP_S, false> - * typedef typename retval<8, _AP_S>::Type RetType; - */ - typedef typename retval::Type RetType; - - static const int width = _AP_W; - - template - struct RType { - enum { - mult_w = _AP_W + _AP_W2, - mult_s = _AP_S || _AP_S2, - plus_w = - AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1, - plus_s = _AP_S || _AP_S2, - minus_w = - AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1, - minus_s = true, - div_w = _AP_W + _AP_S2, - div_s = _AP_S || _AP_S2, - mod_w = AP_MIN(_AP_W, _AP_W2 + (!_AP_S2 && _AP_S)), - mod_s = _AP_S, - logic_w = AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)), - logic_s = _AP_S || _AP_S2 - }; - - - typedef ap_int_base mult_base; - typedef ap_int_base plus_base; - typedef ap_int_base minus_base; - typedef ap_int_base logic_base; - typedef ap_int_base div_base; - typedef ap_int_base mod_base; - typedef ap_int_base<_AP_W, _AP_S> arg1_base; - - typedef typename _ap_int_factory::type mult; - typedef typename _ap_int_factory::type plus; - typedef typename _ap_int_factory::type minus; - typedef typename _ap_int_factory::type logic; - typedef typename _ap_int_factory::type div; - typedef typename _ap_int_factory::type mod; - typedef typename _ap_int_factory<_AP_W, _AP_S>::type arg1; - typedef bool reduce; - }; - - /* Constructors. - * ---------------------------------------------------------------- - */ - /// default ctor - INLINE ap_int_base() { - /* - #ifdef __SC_COMPATIBLE__ - Base::V = 0; - #endif - */ - } - - /// copy ctor - template - INLINE ap_int_base(const ap_int_base<_AP_W2, _AP_S2>& op) { - Base::V = op.V; - } - - /// volatile copy ctor - template - INLINE ap_int_base(const volatile ap_int_base<_AP_W2, _AP_S2>& op) { - Base::V = op.V; - } - -// XXX C++11 feature. -// The explicit specifier specifies that a constructor or conversion function -// (since C++11) doesn't allow implicit conversions or copy-initialization. -// ap_int_base x = 1; -// ap_int_base foo() { return 1; } -// but allows -// ap_int_base x(1); -// ap_int_base y {1}; - -/// from all c types. -#define CTOR_FROM_INT(Type, Size, Signed) \ - INLINE ap_int_base(const Type op) { Base::V = op; } - - CTOR_FROM_INT(bool, 1, false) - CTOR_FROM_INT(char, 8, CHAR_IS_SIGNED) - CTOR_FROM_INT(signed char, 8, true) - CTOR_FROM_INT(unsigned char, 8, false) - CTOR_FROM_INT(short, _AP_SIZE_short, true) - CTOR_FROM_INT(unsigned short, _AP_SIZE_short, false) - CTOR_FROM_INT(int, _AP_SIZE_int, true) - CTOR_FROM_INT(unsigned int, _AP_SIZE_int, false) - CTOR_FROM_INT(long, _AP_SIZE_long, true) - CTOR_FROM_INT(unsigned long, _AP_SIZE_long, false) - CTOR_FROM_INT(ap_slong, _AP_SIZE_ap_slong, true) - CTOR_FROM_INT(ap_ulong, _AP_SIZE_ap_slong, false) -#undef CTOR_FROM_INT - -#if _AP_ENABLE_HALF_ == 1 - /// ctor from half. - // TODO optimize - INLINE ap_int_base(half op) { - ap_int_base<_AP_W, _AP_S> t((float)op); - Base::V = t.V; - } -#endif - - /// ctor from float. - INLINE ap_int_base(float op) { - const int BITS = FLOAT_MAN + FLOAT_EXP + 1; - ap_int_base reg; - reg.V = floatToRawBits(op); - bool is_neg = _AP_ROOT_op_get_bit(reg.V, BITS - 1); - - ap_int_base exp = 0; - exp.V = _AP_ROOT_op_get_range(reg.V, FLOAT_MAN, BITS - 2); - exp = exp - FLOAT_BIAS; - - ap_int_base man; - man.V = _AP_ROOT_op_get_range(reg.V, 0, FLOAT_MAN - 1); - // check for NaN - _AP_WARNING(exp == ((unsigned char)(FLOAT_BIAS + 1)) && man.V != 0, - "assign NaN to ap integer value"); - // set leading 1. - man.V = _AP_ROOT_op_set_bit(man.V, FLOAT_MAN, 1); - //if (is_neg) man = -man; - - if ((reg.V & 0x7ffffffful) == 0) { - Base::V = 0; - } else { - int sh_amt = FLOAT_MAN - exp.V; - if (sh_amt == 0) { - Base::V = man.V; - } else if (sh_amt > 0) { - if (sh_amt < FLOAT_MAN + 2) { - Base::V = man.V >> sh_amt; - } else { - if (is_neg) - Base::V = -1; - else - Base::V = 0; - } - } else { - sh_amt = -sh_amt; - if (sh_amt < _AP_W) { - Base::V = man.V; - Base::V <<= sh_amt; - } else { - Base::V = 0; - } - } - } - if (is_neg) *this = -(*this); - } - - /// ctor from double. - INLINE ap_int_base(double op) { - const int BITS = DOUBLE_MAN + DOUBLE_EXP + 1; - ap_int_base reg; - reg.V = doubleToRawBits(op); - bool is_neg = _AP_ROOT_op_get_bit(reg.V, BITS - 1); - - ap_int_base exp = 0; - exp.V = _AP_ROOT_op_get_range(reg.V, DOUBLE_MAN, BITS - 2); - exp = exp - DOUBLE_BIAS; - - ap_int_base man; - man.V = _AP_ROOT_op_get_range(reg.V, 0, DOUBLE_MAN - 1); - // check for NaN - _AP_WARNING(exp == ((unsigned char)(DOUBLE_BIAS + 1)) && man.V != 0, - "assign NaN to ap integer value"); - // set leading 1. - man.V = _AP_ROOT_op_set_bit(man.V, DOUBLE_MAN, 1); - //if (is_neg) man = -man; - - if ((reg.V & 0x7fffffffffffffffull) == 0) { - Base::V = 0; - } else { - int sh_amt = DOUBLE_MAN - exp.V; - if (sh_amt == 0) { - Base::V = man.V; - } else if (sh_amt > 0) { - if (sh_amt < DOUBLE_MAN + 2) { - Base::V = man.V >> sh_amt; - } else { - if (is_neg) - Base::V = -1; - else - Base::V = 0; - } - } else { - sh_amt = -sh_amt; - if (sh_amt < _AP_W) { - Base::V = man.V; - Base::V <<= sh_amt; - } else { - Base::V = 0; - } - } - } - if (is_neg) *this = -(*this); - } - - /// from higer rank type. - template - INLINE ap_int_base( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - Base::V = op.to_ap_int_base().V; - } - - template - INLINE ap_int_base(const ap_range_ref<_AP_W2, _AP_S2>& ref) { - Base::V = (ref.get()).V; - } - - template - INLINE ap_int_base(const ap_bit_ref<_AP_W2, _AP_S2>& ref) { - Base::V = ref.operator bool(); - } - - template - INLINE ap_int_base(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref) { - const ap_int_base::_AP_WR, - false> - tmp = ref.get(); - Base::V = tmp.V; - } - - /* radix has default value in set */ - -#ifndef __SYNTHESIS__ - INLINE ap_int_base(const char* s, signed char rd = 0) { - if (rd == 0) - rd = guess_radix(s); - unsigned int length = strlen(s); - Base::V.fromString(s, length, rd); - } -#else - // XXX __builtin_bit_from_string(...) requires const C string and radix. - INLINE ap_int_base(const char* s) { - typeof(Base::V) t; - _ssdm_string2bits((void*)(&t), (const char*)(s), 10, _AP_W, _AP_S, - AP_TRN, AP_WRAP, 0, _AP_C99); - Base::V = t; - } - INLINE ap_int_base(const char* s, signed char rd) { - typeof(Base::V) t; - _ssdm_string2bits((void*)(&t), (const char*)(s), rd, _AP_W, _AP_S, - AP_TRN, AP_WRAP, 0, _AP_C99); - Base::V = t; - } -#endif - - template - INLINE ap_int_base( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - Base::V = (val.get()).V; - } - - template - INLINE ap_int_base( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - Base::V = val.operator bool(); - } - - INLINE ap_int_base read() volatile { - /*AP_DEBUG(printf("call read %d\n", Base::V););*/ - ap_int_base ret; - ret.V = Base::V; - return ret; - } - - INLINE void write(const ap_int_base<_AP_W, _AP_S>& op2) volatile { - /*AP_DEBUG(printf("call write %d\n", op2.V););*/ - Base::V = op2.V; - } - - /* Another form of "write".*/ - template - INLINE void operator=( - const volatile ap_int_base<_AP_W2, _AP_S2>& op2) volatile { - Base::V = op2.V; - } - - INLINE void operator=( - const volatile ap_int_base<_AP_W, _AP_S>& op2) volatile { - Base::V = op2.V; - } - - template - INLINE void operator=(const ap_int_base<_AP_W2, _AP_S2>& op2) volatile { - Base::V = op2.V; - } - - INLINE void operator=(const ap_int_base<_AP_W, _AP_S>& op2) volatile { - Base::V = op2.V; - } - - template - INLINE ap_int_base& operator=( - const volatile ap_int_base<_AP_W2, _AP_S2>& op2) { - Base::V = op2.V; - return *this; - } - - template - INLINE ap_int_base& operator=(const ap_int_base<_AP_W2, _AP_S2>& op2) { - Base::V = op2.V; - return *this; - } - - INLINE ap_int_base& operator=(const volatile ap_int_base<_AP_W, _AP_S>& op2) { - Base::V = op2.V; - return *this; - } - - INLINE ap_int_base& operator=(const ap_int_base<_AP_W, _AP_S>& op2) { - Base::V = op2.V; - return *this; - } - - -#define ASSIGN_OP_FROM_INT(Type, Size, Signed) \ - INLINE ap_int_base& operator=(Type op) { \ - Base::V = op; \ - return *this; \ - } - - ASSIGN_OP_FROM_INT(bool, 1, false) - ASSIGN_OP_FROM_INT(char, 8, CHAR_IS_SIGNED) - ASSIGN_OP_FROM_INT(signed char, 8, true) - ASSIGN_OP_FROM_INT(unsigned char, 8, false) - ASSIGN_OP_FROM_INT(short, _AP_SIZE_short, true) - ASSIGN_OP_FROM_INT(unsigned short, _AP_SIZE_short, false) - ASSIGN_OP_FROM_INT(int, _AP_SIZE_int, true) - ASSIGN_OP_FROM_INT(unsigned int, _AP_SIZE_int, false) - ASSIGN_OP_FROM_INT(long, _AP_SIZE_long, true) - ASSIGN_OP_FROM_INT(unsigned long, _AP_SIZE_long, false) - ASSIGN_OP_FROM_INT(ap_slong, _AP_SIZE_ap_slong, true) - ASSIGN_OP_FROM_INT(ap_ulong, _AP_SIZE_ap_slong, false) - -#undef ASSIGN_OP_FROM_INT - - template - INLINE ap_int_base& operator=(const ap_bit_ref<_AP_W2, _AP_S2>& op2) { - Base::V = (bool)op2; - return *this; - } - - template - INLINE ap_int_base& operator=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - Base::V = (ap_int_base<_AP_W2, false>(op2)).V; - return *this; - } - - template - INLINE ap_int_base& operator=( - const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& op2) { - Base::V = op2.get().V; - return *this; - } - - template - INLINE ap_int_base& operator=( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - Base::V = op.to_ap_int_base().V; - return *this; - } - - template - INLINE ap_int_base& operator=( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - Base::V = (bool)op; - return *this; - } - - template - INLINE ap_int_base& operator=( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& op) { - Base::V = ((const ap_int_base<_AP_W2, false>)(op)).V; - return *this; - } - - // FIXME: UG902 has clearly required user to use to_int() to convert to built-in - // types, but this implicit conversion is relied on in hls_cordic.h and hls_rsr.h. - // For example: - // int d_exp = fps_x.exp - fps_y.exp; - INLINE operator RetType() const { return (RetType)(Base::V); } - - /* Explicit conversions to C types. - * ---------------------------------------------------------------- - */ - INLINE bool to_bool() const { return (bool)(Base::V); } - INLINE char to_char() const { return (char)(Base::V); } - INLINE signed char to_schar() const { return (signed char)(Base::V); } - INLINE unsigned char to_uchar() const { return (unsigned char)(Base::V); } - INLINE short to_short() const { return (short)(Base::V); } - INLINE unsigned short to_ushort() const { return (unsigned short)(Base::V); } - INLINE int to_int() const { return (int)(Base::V); } - INLINE unsigned to_uint() const { return (unsigned)(Base::V); } - INLINE long to_long() const { return (long)(Base::V); } - INLINE unsigned long to_ulong() const { return (unsigned long)(Base::V); } - INLINE ap_slong to_int64() const { return (ap_slong)(Base::V); } - INLINE ap_ulong to_uint64() const { return (ap_ulong)(Base::V); } - INLINE float to_float() const { return (float)(Base::V); } - INLINE double to_double() const { return (double)(Base::V); } - - // TODO decide if user-defined conversion should be provided. -#if 0 - INLINE operator char() const { return (char)(Base::V); } - INLINE operator signed char() const { return (signed char)(Base::V); } - INLINE operator unsigned char() const { return (unsigned char)(Base::V); } - INLINE operator short() const { return (short)(Base::V); } - INLINE operator unsigned short() const { return (unsigned short)(Base::V); } - INLINE operator int() const { return (int)(Base::V); } - INLINE operator unsigned int () const { return (unsigned)(Base::V); } - INLINE operator long () const { return (long)(Base::V); } - INLINE operator unsigned long () const { return (unsigned long)(Base::V); } - INLINE operator ap_slong () { return (ap_slong)(Base::V); } - INLINE operator ap_ulong () { return (ap_ulong)(Base::V); } -#endif - - /* Helper methods. - ---------------------------------------------------------------- - */ - /* we cannot call a non-volatile function on a volatile instance. - * but calling a volatile function is ok. - * XXX deleted non-volatile version. - */ - INLINE int length() const volatile { return _AP_W; } - - /*Return true if the value of ap_int_base instance is zero*/ - INLINE bool iszero() const { return Base::V == 0; } - - /*Return true if the value of ap_int_base instance is zero*/ - INLINE bool is_zero() const { return Base::V == 0; } - - /* x < 0 */ - INLINE bool sign() const { - if (_AP_S && - _AP_ROOT_op_get_bit(Base::V, _AP_W - 1)) - return true; - else - return false; - } - - /* x[i] = 0 */ - INLINE void clear(int i) { - AP_ASSERT(i >= 0 && i < _AP_W, "position out of range"); - Base::V = _AP_ROOT_op_set_bit(Base::V, i, 0); - } - - /* x[i] = !x[i]*/ - INLINE void invert(int i) { - AP_ASSERT(i >= 0 && i < _AP_W, "position out of range"); - bool val = _AP_ROOT_op_get_bit(Base::V, i); - if (val) - Base::V = _AP_ROOT_op_set_bit(Base::V, i, 0); - else - Base::V = _AP_ROOT_op_set_bit(Base::V, i, 1); - } - - INLINE bool test(int i) const { - AP_ASSERT(i >= 0 && i < _AP_W, "position out of range"); - return _AP_ROOT_op_get_bit(Base::V, i); - } - - // Get self. For ap_concat_ref expansion. - INLINE ap_int_base& get() { return *this; } - - // Set the ith bit into 1 - INLINE void set(int i) { - AP_ASSERT(i >= 0 && i < _AP_W, "position out of range"); - Base::V = _AP_ROOT_op_set_bit(Base::V, i, 1); - } - - // Set the ith bit into v - INLINE void set(int i, bool v) { - AP_ASSERT(i >= 0 && i < _AP_W, "position out of range"); - Base::V = _AP_ROOT_op_set_bit(Base::V, i, v); - } - - // This is used for sc_lv and sc_bv, which is implemented by sc_uint - // Rotate an ap_int_base object n places to the left - INLINE ap_int_base& lrotate(int n) { - AP_ASSERT(n >= 0 && n < _AP_W, "shift value out of range"); - // TODO unify this. -#ifdef __SYNTHESIS__ - typeof(Base::V) l_p = Base::V << n; - typeof(Base::V) r_p = Base::V >> (_AP_W - n); - Base::V = l_p | r_p; -#else - Base::V.lrotate(n); -#endif - return *this; - } - - // This is used for sc_lv and sc_bv, which is implemented by sc_uint - // Rotate an ap_int_base object n places to the right - INLINE ap_int_base& rrotate(int n) { - AP_ASSERT(n >= 0 && n < _AP_W, "shift value out of range"); - // TODO unify this. -#ifdef __SYNTHESIS__ - typeof(Base::V) l_p = Base::V << (_AP_W - n); - typeof(Base::V) r_p = Base::V >> n; - Base::V = l_p | r_p; -#else - Base::V.rrotate(n); -#endif - return *this; - } - - // Reverse the contents of ap_int_base instance. - // I.e. LSB becomes MSB and vise versa. - INLINE ap_int_base& reverse() { - Base::V = _AP_ROOT_op_get_range(Base::V, _AP_W - 1, 0); - return *this; - } - - // Set the ith bit into v - INLINE void set_bit(int i, bool v) { - Base::V = _AP_ROOT_op_set_bit(Base::V, i, v); - } - - // Get the value of ith bit - INLINE bool get_bit(int i) const { - return (bool)_AP_ROOT_op_get_bit(Base::V, i); - } - - // complements every bit - INLINE void b_not() { Base::V = ~Base::V; } - -#define OP_ASSIGN_AP(Sym) \ - template \ - INLINE ap_int_base& operator Sym(const ap_int_base<_AP_W2, _AP_S2>& op2) { \ - Base::V Sym op2.V; \ - return *this; \ - } - - /* Arithmetic assign. - * ---------------------------------------------------------------- - */ - OP_ASSIGN_AP(*=) - OP_ASSIGN_AP(+=) - OP_ASSIGN_AP(-=) - OP_ASSIGN_AP(/=) - OP_ASSIGN_AP(%=) -#undef OP_ASSIGN_AP - - /* Bitwise assign: and, or, xor. - * ---------------------------------------------------------------- - */ -#define OP_ASSIGN_AP_CHK(Sym) \ - template \ - INLINE ap_int_base& operator Sym(const ap_int_base<_AP_W2, _AP_S2>& op2) { \ - _AP_WARNING((_AP_W != _AP_W2), \ - "Bitsize mismatch for ap_[u]int" #Sym "ap_[u]int."); \ - Base::V Sym op2.V; \ - return *this; \ - } - OP_ASSIGN_AP_CHK(&=) - OP_ASSIGN_AP_CHK(|=) - OP_ASSIGN_AP_CHK(^=) -#undef OP_ASSIGN_AP_CHK - - /* Prefix increment, decrement. - * ---------------------------------------------------------------- - */ - INLINE ap_int_base& operator++() { - operator+=((ap_int_base<1, false>)1); - return *this; - } - INLINE ap_int_base& operator--() { - operator-=((ap_int_base<1, false>)1); - return *this; - } - - /* Postfix increment, decrement - * ---------------------------------------------------------------- - */ - INLINE const typename RType<_AP_W,_AP_S>::arg1 operator++(int) { - ap_int_base t = *this; - operator+=((ap_int_base<1, false>)1); - return t; - } - INLINE const typename RType<_AP_W,_AP_S>::arg1 operator--(int) { - ap_int_base t = *this; - operator-=((ap_int_base<1, false>)1); - return t; - } - - /* Unary arithmetic. - * ---------------------------------------------------------------- - */ - INLINE typename RType<_AP_W,_AP_S>::arg1 operator+() const { return *this; } - - // TODO used to be W>64 only... need check. - INLINE typename RType<1, false>::minus operator-() const { - return ap_int_base<1, false>(0) - *this; - } - - /* Not (!) - * ---------------------------------------------------------------- - */ - INLINE bool operator!() const { return Base::V == 0; } - - /* Bitwise (arithmetic) unary: complement - ---------------------------------------------------------------- - */ - // XXX different from Mentor's ac_int! - INLINE typename RType<_AP_W,_AP_S>::arg1 operator~() const { - ap_int_base<_AP_W, _AP_S> r; - r.V = ~Base::V; - return r; - } - - /* Shift (result constrained by left operand). - * ---------------------------------------------------------------- - */ - template - INLINE typename RType<_AP_W,_AP_S>::arg1 operator<<(const ap_int_base<_AP_W2, true>& op2) const { - bool isNeg = _AP_ROOT_op_get_bit(op2.V, _AP_W2 - 1); - ap_int_base<_AP_W2, false> sh = op2; - if (isNeg) { - sh = -op2; - return operator>>(sh); - } else - return operator<<(sh); - } - - template - INLINE typename RType<_AP_W,_AP_S>::arg1 operator<<(const ap_int_base<_AP_W2, false>& op2) const { - ap_int_base r; - r.V = Base::V << op2.to_uint(); - return r; - } - - template - INLINE typename RType<_AP_W,_AP_S>::arg1 operator>>(const ap_int_base<_AP_W2, true>& op2) const { - bool isNeg = _AP_ROOT_op_get_bit(op2.V, _AP_W2 - 1); - ap_int_base<_AP_W2, false> sh = op2; - if (isNeg) { - sh = -op2; - return operator<<(sh); - } - return operator>>(sh); - } - - template - INLINE typename RType<_AP_W,_AP_S>::arg1 operator>>(const ap_int_base<_AP_W2, false>& op2) const { - ap_int_base r; - r.V = Base::V >> op2.to_uint(); - return r; - } - - // FIXME we standalone operator>> for ap_int_base and ap_range_ref. -#if 0 - template - INLINE ap_int_base operator<<(const ap_range_ref<_AP_W2, _AP_S2>& op2) const { - return *this << (op2.operator ap_int_base<_AP_W2, false>()); - } - - template - INLINE ap_int_base operator>>(const ap_range_ref<_AP_W2, _AP_S2>& op2) const { - return *this >> (op2.operator ap_int_base<_AP_W2, false>()); - } -#endif - - /* Shift assign - * ---------------------------------------------------------------- - */ - template - INLINE ap_int_base& operator<<=(const ap_int_base<_AP_W2, true>& op2) { - bool isNeg = _AP_ROOT_op_get_bit(op2.V, _AP_W2 - 1); - ap_int_base<_AP_W2, false> sh = op2; - if (isNeg) { - sh = -op2; - return operator>>=(sh); - } else - return operator<<=(sh); - } - - template - INLINE ap_int_base& operator<<=(const ap_int_base<_AP_W2, false>& op2) { - Base::V <<= op2.to_uint(); - return *this; - } - - template - INLINE ap_int_base& operator>>=(const ap_int_base<_AP_W2, true>& op2) { - bool isNeg = _AP_ROOT_op_get_bit(op2.V, _AP_W2 - 1); - ap_int_base<_AP_W2, false> sh = op2; - if (isNeg) { - sh = -op2; - return operator<<=(sh); - } - return operator>>=(sh); - } - - template - INLINE ap_int_base& operator>>=(const ap_int_base<_AP_W2, false>& op2) { - Base::V >>= op2.to_uint(); - return *this; - } - - // FIXME we standalone operator>> for ap_int_base and ap_range_ref. -#if 0 - template - INLINE ap_int_base& operator<<=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - return *this <<= (op2.operator ap_int_base<_AP_W2, false>()); - } - template - INLINE ap_int_base& operator>>=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - return *this >>= (op2.operator ap_int_base<_AP_W2, false>()); - } -#endif - - /* Equality and Relational. - * ---------------------------------------------------------------- - */ - template - INLINE bool operator==(const ap_int_base<_AP_W2, _AP_S2>& op2) const { - return Base::V == op2.V; - } - template - INLINE bool operator!=(const ap_int_base<_AP_W2, _AP_S2>& op2) const { - return !(Base::V == op2.V); - } - template - INLINE bool operator<(const ap_int_base<_AP_W2, _AP_S2>& op2) const { - return Base::V < op2.V; - } - template - INLINE bool operator>=(const ap_int_base<_AP_W2, _AP_S2>& op2) const { - return Base::V >= op2.V; - } - template - INLINE bool operator>(const ap_int_base<_AP_W2, _AP_S2>& op2) const { - return Base::V > op2.V; - } - template - INLINE bool operator<=(const ap_int_base<_AP_W2, _AP_S2>& op2) const { - return Base::V <= op2.V; - } - - /* Bit and Part Select - * ---------------------------------------------------------------- - */ - INLINE ap_range_ref<_AP_W, _AP_S> range(int Hi, int Lo) { - _AP_ERROR(Hi >= _AP_W, "Hi(%d)out of bound(%d) in range()", Hi, _AP_W); - _AP_ERROR(Lo >= _AP_W, "Lo(%d)out of bound(%d) in range()", Lo, _AP_W); - return ap_range_ref<_AP_W, _AP_S>(this, Hi, Lo); - } - - // This is a must to strip constness to produce reference type. - INLINE ap_range_ref<_AP_W, _AP_S> range(int Hi, int Lo) const { - _AP_ERROR(Hi >= _AP_W, "Hi(%d)out of bound(%d) in range()", Hi, _AP_W); - _AP_ERROR(Lo >= _AP_W, "Lo(%d)out of bound(%d) in range()", Lo, _AP_W); - return ap_range_ref<_AP_W, _AP_S>(const_cast(this), Hi, Lo); - } - - template - INLINE ap_range_ref<_AP_W, _AP_S> range( - const ap_int_base<_AP_W2, _AP_S2>& HiIdx, - const ap_int_base<_AP_W3, _AP_S3>& LoIdx) { - int Hi = HiIdx.to_int(); - int Lo = LoIdx.to_int(); - return this->range(Hi, Lo); - } - - template - INLINE ap_range_ref<_AP_W, _AP_S> range( - const ap_int_base<_AP_W2, _AP_S2>& HiIdx, - const ap_int_base<_AP_W3, _AP_S3>& LoIdx) const { - int Hi = HiIdx.to_int(); - int Lo = LoIdx.to_int(); - return this->range(Hi, Lo); - } - - INLINE ap_range_ref<_AP_W, _AP_S> range() { - return this->range(_AP_W - 1, 0); - } - - INLINE ap_range_ref<_AP_W, _AP_S> range() const { - return this->range(_AP_W - 1, 0); - } - - INLINE ap_range_ref<_AP_W, _AP_S> operator()(int Hi, int Lo) { - return this->range(Hi, Lo); - } - - INLINE ap_range_ref<_AP_W, _AP_S> operator()(int Hi, int Lo) const { - return this->range(Hi, Lo); - } - - template - INLINE ap_range_ref<_AP_W, _AP_S> operator()( - const ap_int_base<_AP_W2, _AP_S2>& HiIdx, - const ap_int_base<_AP_W3, _AP_S3>& LoIdx) { - int Hi = HiIdx.to_int(); - int Lo = LoIdx.to_int(); - return this->range(Hi, Lo); - } - - template - INLINE ap_range_ref<_AP_W, _AP_S> operator()( - const ap_int_base<_AP_W2, _AP_S2>& HiIdx, - const ap_int_base<_AP_W3, _AP_S3>& LoIdx) const { - int Hi = HiIdx.to_int(); - int Lo = LoIdx.to_int(); - return this->range(Hi, Lo); - } - -#if 0 - template - INLINE ap_int_base slice() const { - AP_ASSERT(Hi >= Lo && Hi < _AP_W && Lo < _AP_W, "Out of bounds in slice()"); - ap_int_base tmp ; - tmp.V = _AP_ROOT_op_get_range(Base::V, Lo, Hi); - return tmp; - } - - INLINE ap_bit_ref<_AP_W,_AP_S> operator [] ( unsigned int uindex) { - AP_ASSERT(uindex < _AP_W, "Attempting to read bit beyond MSB"); - ap_bit_ref<_AP_W,_AP_S> bvh( this, uindex ); - return bvh; - } -#endif - - INLINE ap_bit_ref<_AP_W, _AP_S> operator[](int index) { - AP_ASSERT(index >= 0, "Attempting to read bit with negative index"); - AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB"); - ap_bit_ref<_AP_W, _AP_S> bvh(this, index); - return bvh; - } - - template - INLINE ap_bit_ref<_AP_W, _AP_S> operator[]( - const ap_int_base<_AP_W2, _AP_S2>& index) { - AP_ASSERT(index >= 0, "Attempting to read bit with negative index"); - AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB"); - ap_bit_ref<_AP_W, _AP_S> bvh(this, index.to_int()); - return bvh; - } - - INLINE bool operator[](int index) const { - AP_ASSERT(index >= 0, "Attempting to read bit with negative index"); - AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB"); - ap_bit_ref<_AP_W, _AP_S> br(this, index); - return br.to_bool(); - } - template - INLINE bool operator[](const ap_int_base<_AP_W2, _AP_S2>& index) const { - AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB"); - ap_bit_ref<_AP_W, _AP_S> br(this, index.to_int()); - return br.to_bool(); - } - - INLINE ap_bit_ref<_AP_W, _AP_S> bit(int index) { - AP_ASSERT(index >= 0, "Attempting to read bit with negative index"); - AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB"); - ap_bit_ref<_AP_W, _AP_S> bvh(this, index); - return bvh; - } - template - INLINE ap_bit_ref<_AP_W, _AP_S> bit( - const ap_int_base<_AP_W2, _AP_S2>& index) { - AP_ASSERT(index >= 0, "Attempting to read bit with negative index"); - AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB"); - ap_bit_ref<_AP_W, _AP_S> bvh(this, index.to_int()); - return bvh; - } - - INLINE bool bit(int index) const { - AP_ASSERT(index >= 0, "Attempting to read bit with negative index"); - AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB"); - ap_bit_ref<_AP_W, _AP_S> br(this, index); - return br.to_bool(); - } - - template - INLINE bool bit(const ap_int_base<_AP_W2, _AP_S2>& index) const { - return bit(index.to_int()); - } - -#if 0 - template - INLINE bool operator[](_AP_T index) const { - AP_ASSERT(index < _AP_W, "Attempting to read bit beyond MSB"); - ap_bit_ref<_AP_W,_AP_S> br = operator[](index); - return br.to_bool(); - } -#endif - - // Count the number of zeros from the most significant bit - // to the first one bit. - INLINE int countLeadingZeros() { -#ifdef __SYNTHESIS__ - if (_AP_W <= 32) { - ap_int_base<32, false> t(-1UL), x; - x.V = _AP_ROOT_op_get_range(this->V, _AP_W - 1, 0); // reverse - t.V = _AP_ROOT_op_set_range(t.V, 0, _AP_W - 1, x.V); - return __builtin_ctz(t.V); // count trailing zeros. - } else if (_AP_W <= 64) { - ap_int_base<64, false> t(-1ULL); - ap_int_base<64, false> x; - x.V = _AP_ROOT_op_get_range(this->V, _AP_W - 1, 0); // reverse - t.V = _AP_ROOT_op_set_range(t.V, 0, _AP_W - 1, x.V); - return __builtin_ctzll(t.V); // count trailing zeros. - } else { - enum { __N = (_AP_W + 63) / 64 }; - int NZeros = 0; - int i = 0; - bool hitNonZero = false; - for (i = 0; i < __N - 1; ++i) { - ap_int_base<64, false> t; - t.V = _AP_ROOT_op_get_range(this->V, _AP_W - i * 64 - 64, _AP_W - i * 64 - 1); - NZeros += hitNonZero ? 0 : __builtin_clzll(t.V); // count leading zeros. - hitNonZero |= (t.V != 0); - } - if (!hitNonZero) { - ap_int_base<64, false> t(-1ULL); - enum { REST = (_AP_W - 1) % 64 }; - ap_int_base<64, false> x; - x.V = _AP_ROOT_op_get_range(this->V, 0, REST); - t.V = _AP_ROOT_op_set_range(t.V, 63 - REST, 63, x.V); - NZeros += __builtin_clzll(t.V); - } - return NZeros; - } -#else - return (Base::V).countLeadingZeros(); -#endif - } // countLeadingZeros - - template - INLINE ap_concat_ref<_AP_W, ap_int_base, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - concat(const ap_int_base<_AP_W2, _AP_S2>& a2) const { - return ap_concat_ref<_AP_W, ap_int_base, _AP_W2, - ap_int_base<_AP_W2, _AP_S2> >( - const_cast&>(*this), - const_cast&>(a2)); - } - - template - INLINE ap_concat_ref<_AP_W, ap_int_base, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - concat(ap_int_base<_AP_W2, _AP_S2>& a2) { - return ap_concat_ref<_AP_W, ap_int_base, _AP_W2, - ap_int_base<_AP_W2, _AP_S2> >(*this, a2); - } - - template - INLINE - ap_concat_ref<_AP_W, ap_int_base, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > - operator,(const ap_range_ref<_AP_W2, _AP_S2> &a2) const { - return ap_concat_ref<_AP_W, ap_int_base, _AP_W2, - ap_range_ref<_AP_W2, _AP_S2> >( - const_cast&>(*this), - const_cast&>(a2)); - } - - template - INLINE - ap_concat_ref<_AP_W, ap_int_base, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > - operator,(ap_range_ref<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<_AP_W, ap_int_base, _AP_W2, - ap_range_ref<_AP_W2, _AP_S2> >(*this, a2); - } - - template - INLINE ap_concat_ref<_AP_W, ap_int_base, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(const ap_int_base<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<_AP_W, ap_int_base, _AP_W2, - ap_int_base<_AP_W2, _AP_S2> >( - *this, const_cast&>(a2)); - } - - template - INLINE ap_concat_ref<_AP_W, ap_int_base, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(ap_int_base<_AP_W2, _AP_S2> &a2) const { - return ap_concat_ref<_AP_W, ap_int_base, _AP_W2, - ap_int_base<_AP_W2, _AP_S2> >( - const_cast&>(*this), a2); - } - - template - INLINE ap_concat_ref<_AP_W, ap_int_base, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(const ap_int_base<_AP_W2, _AP_S2> &a2) const { - return ap_concat_ref<_AP_W, ap_int_base, _AP_W2, - ap_int_base<_AP_W2, _AP_S2> >( - const_cast&>(*this), - const_cast&>(a2)); - } - - template - INLINE ap_concat_ref<_AP_W, ap_int_base, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(ap_int_base<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<_AP_W, ap_int_base, _AP_W2, - ap_int_base<_AP_W2, _AP_S2> >(*this, a2); - } - - template - INLINE ap_concat_ref<_AP_W, ap_int_base, 1, ap_bit_ref<_AP_W2, _AP_S2> > - operator,(const ap_bit_ref<_AP_W2, _AP_S2> &a2) const { - return ap_concat_ref<_AP_W, ap_int_base, 1, ap_bit_ref<_AP_W2, _AP_S2> >( - const_cast&>(*this), - const_cast&>(a2)); - } - - template - INLINE ap_concat_ref<_AP_W, ap_int_base, 1, ap_bit_ref<_AP_W2, _AP_S2> > - operator,(ap_bit_ref<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<_AP_W, ap_int_base, 1, ap_bit_ref<_AP_W2, _AP_S2> >( - *this, a2); - } - - template - INLINE ap_concat_ref<_AP_W, ap_int_base, _AP_W2 + _AP_W3, - ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > - operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { - return ap_concat_ref<_AP_W, ap_int_base, _AP_W2 + _AP_W3, - ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >( - const_cast&>(*this), - const_cast&>(a2)); - } - - template - INLINE ap_concat_ref<_AP_W, ap_int_base, _AP_W2 + _AP_W3, - ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > - operator,(ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { - return ap_concat_ref<_AP_W, ap_int_base, _AP_W2 + _AP_W3, - ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, - a2); - } - - template - INLINE ap_concat_ref< - _AP_W, ap_int_base, _AP_W2, - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > - operator,(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> - &a2) const { - return ap_concat_ref< - _AP_W, ap_int_base, _AP_W2, - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( - const_cast&>(*this), - const_cast< - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>&>(a2)); - } - - template - INLINE ap_concat_ref< - _AP_W, ap_int_base, _AP_W2, - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > - operator,(af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) { - return ap_concat_ref< - _AP_W, ap_int_base, _AP_W2, - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, - a2); - } - - template - INLINE - ap_concat_ref<_AP_W, ap_int_base, 1, - af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > - operator,(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> - &a2) const { - return ap_concat_ref< - _AP_W, ap_int_base, 1, - af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( - const_cast&>(*this), - const_cast&>( - a2)); - } - - template - INLINE - ap_concat_ref<_AP_W, ap_int_base, 1, - af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > - operator,( - af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) { - return ap_concat_ref< - _AP_W, ap_int_base, 1, - af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); - } - - template - INLINE ap_int_base operator&( - const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { - return *this & a2.get(); - } - - template - INLINE ap_int_base operator|( - const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { - return *this | a2.get(); - } - - template - INLINE ap_int_base operator^( - const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { - return *this ^ a2.get(); - } - - template - INLINE void set(const ap_int_base<_AP_W3, false>& val) { - Base::V = val.V; - } - - /* Reduce operations. - * ---------------------------------------------------------------- - */ - // XXX non-const version deleted. - INLINE bool and_reduce() const { return _AP_ROOT_op_reduce(and, Base::V); } - INLINE bool nand_reduce() const { return _AP_ROOT_op_reduce(nand, Base::V); } - INLINE bool or_reduce() const { return _AP_ROOT_op_reduce(or, Base::V); } - INLINE bool nor_reduce() const { return !(_AP_ROOT_op_reduce(or, Base::V)); } - INLINE bool xor_reduce() const { return _AP_ROOT_op_reduce (xor, Base::V); } - INLINE bool xnor_reduce() const { - return !(_AP_ROOT_op_reduce (xor, Base::V)); - } - - /* Output as a string. - * ---------------------------------------------------------------- - */ -#ifndef __SYNTHESIS__ - std::string to_string(signed char rd = 2, bool sign = _AP_S) const { - // XXX in autosim/autowrap.tcl "(${name}).to_string(2).c_str()" is used to - // initialize sc_lv, which seems incapable of handling format "-0b". - if (rd == 2) sign = false; - return (Base::V).to_string(rd, sign); - } -#else - INLINE char* to_string(signed char rd = 2, bool sign = _AP_S) const { - return 0; - } -#endif -}; // struct ap_int_base - -// XXX apcc cannot handle global std::ios_base::Init() brought in by -#ifndef AP_AUTOCC -#ifndef __SYNTHESIS__ -template -INLINE std::ostream& operator<<(std::ostream& os, - const ap_int_base<_AP_W, _AP_S>& x) { - std::ios_base::fmtflags ff = std::cout.flags(); - if (ff & std::cout.hex) { - os << x.to_string(16); // don't print sign - } else if (ff & std::cout.oct) { - os << x.to_string(8); // don't print sign - } else { - os << x.to_string(10); - } - return os; -} -#endif // ifndef __SYNTHESIS__ - -#ifndef __SYNTHESIS__ -template -INLINE std::istream& operator>>(std::istream& in, - ap_int_base<_AP_W, _AP_S>& op) { - std::string str; - in >> str; - const std::ios_base::fmtflags basefield = in.flags() & std::ios_base::basefield; - unsigned radix = (basefield == std::ios_base::dec) ? 0 : ( - (basefield == std::ios_base::oct) ? 8 : ( - (basefield == std::ios_base::hex) ? 16 : 0)); - op = ap_int_base<_AP_W, _AP_S>(str.c_str(), radix); - return in; -} -#endif // ifndef __SYNTHESIS__ -#endif // ifndef AP_AUTOCC - -/* Operators with another ap_int_base. - * ---------------------------------------------------------------- - */ -#define OP_BIN_AP(Sym, Rty) \ - template \ - INLINE \ - typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W2, _AP_S2>::Rty \ - operator Sym(const ap_int_base<_AP_W, _AP_S>& op, \ - const ap_int_base<_AP_W2, _AP_S2>& op2) { \ - typename ap_int_base<_AP_W, _AP_S>::template RType< \ - _AP_W2, _AP_S2>::Rty##_base lhs(op); \ - typename ap_int_base<_AP_W, _AP_S>::template RType< \ - _AP_W2, _AP_S2>::Rty##_base rhs(op2); \ - typename ap_int_base<_AP_W, _AP_S>::template RType< \ - _AP_W2, _AP_S2>::Rty##_base ret; \ - ret.V = lhs.V Sym rhs.V; \ - return ret; \ - } - -OP_BIN_AP(*, mult) -OP_BIN_AP(+, plus) -OP_BIN_AP(-, minus) -OP_BIN_AP(&, logic) -OP_BIN_AP(|, logic) -OP_BIN_AP(^, logic) - -#define OP_BIN_AP2(Sym, Rty) \ - template \ - INLINE \ - typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W2, _AP_S2>::Rty \ - operator Sym(const ap_int_base<_AP_W, _AP_S>& op, \ - const ap_int_base<_AP_W2, _AP_S2>& op2) { \ - typename ap_int_base<_AP_W, _AP_S>::template RType< \ - _AP_W2, _AP_S2>::Rty##_base ret; \ - ret.V = op.V Sym op2.V; \ - return ret; \ - } - -OP_BIN_AP2(/, div) -OP_BIN_AP2(%, mod) - -// shift operators are defined inside class. -// compound assignment operators are defined inside class. - -/* Operators with a pointer type. - * ---------------------------------------------------------------- - * char a[100]; - * char* ptr = a; - * ap_int<2> n = 3; - * char* ptr2 = ptr + n*2; - * avoid ambiguous errors. - */ -#define OP_BIN_WITH_PTR(BIN_OP) \ - template \ - INLINE PTR_TYPE* operator BIN_OP(PTR_TYPE* i_op, \ - const ap_int_base<_AP_W, _AP_S>& op) { \ - ap_slong op2 = op.to_int64(); /* Not all implementation */ \ - return i_op BIN_OP op2; \ - } \ - template \ - INLINE PTR_TYPE* operator BIN_OP(const ap_int_base<_AP_W, _AP_S>& op, \ - PTR_TYPE* i_op) { \ - ap_slong op2 = op.to_int64(); /* Not all implementation */ \ - return op2 BIN_OP i_op; \ - } - -OP_BIN_WITH_PTR(+) -OP_BIN_WITH_PTR(-) - -/* Operators with a native floating point types. - * ---------------------------------------------------------------- - */ -// float OP ap_int -// when ap_int's width > 64, then trunc ap_int to ap_int<64> -#define OP_BIN_WITH_FLOAT(BIN_OP, C_TYPE) \ - template \ - INLINE C_TYPE operator BIN_OP(C_TYPE i_op, \ - const ap_int_base<_AP_W, _AP_S>& op) { \ - typename ap_int_base<_AP_W, _AP_S>::RetType op2 = op; \ - return i_op BIN_OP op2; \ - } \ - template \ - INLINE C_TYPE operator BIN_OP(const ap_int_base<_AP_W, _AP_S>& op, \ - C_TYPE i_op) { \ - typename ap_int_base<_AP_W, _AP_S>::RetType op2 = op; \ - return op2 BIN_OP i_op; \ - } - -#define ALL_OP_WITH_FLOAT(C_TYPE) \ - OP_BIN_WITH_FLOAT(*, C_TYPE) \ - OP_BIN_WITH_FLOAT(/, C_TYPE) \ - OP_BIN_WITH_FLOAT(+, C_TYPE) \ - OP_BIN_WITH_FLOAT(-, C_TYPE) - -#if _AP_ENABLE_HALF_ == 1 -ALL_OP_WITH_FLOAT(half) -#endif -ALL_OP_WITH_FLOAT(float) -ALL_OP_WITH_FLOAT(double) - -// TODO no shift? - -/* Operators with a native integral types. - * ---------------------------------------------------------------- - */ -// arithmetic and bitwise operators. -#define OP_BIN_WITH_INT(BIN_OP, C_TYPE, _AP_W2, _AP_S2, RTYPE) \ - template \ - INLINE typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W2, \ - _AP_S2>::RTYPE \ - operator BIN_OP(C_TYPE i_op, const ap_int_base<_AP_W, _AP_S>& op) { \ - return ap_int_base<_AP_W2, _AP_S2>(i_op) BIN_OP(op); \ - } \ - template \ - INLINE typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W2, \ - _AP_S2>::RTYPE \ - operator BIN_OP(const ap_int_base<_AP_W, _AP_S>& op, C_TYPE i_op) { \ - return op BIN_OP ap_int_base<_AP_W2, _AP_S2>(i_op); \ - } - -#define ALL_OP_BIN_WITH_INT(C_TYPE, _AP_W2, _AP_S2) \ - OP_BIN_WITH_INT(*, C_TYPE, _AP_W2, _AP_S2, mult) \ - OP_BIN_WITH_INT(+, C_TYPE, _AP_W2, _AP_S2, plus) \ - OP_BIN_WITH_INT(-, C_TYPE, _AP_W2, _AP_S2, minus) \ - OP_BIN_WITH_INT(/, C_TYPE, _AP_W2, _AP_S2, div) \ - OP_BIN_WITH_INT(%, C_TYPE, _AP_W2, _AP_S2, mod) \ - OP_BIN_WITH_INT(&, C_TYPE, _AP_W2, _AP_S2, logic) \ - OP_BIN_WITH_INT(|, C_TYPE, _AP_W2, _AP_S2, logic) \ - OP_BIN_WITH_INT(^, C_TYPE, _AP_W2, _AP_S2, logic) - -ALL_OP_BIN_WITH_INT(bool, 1, false) -ALL_OP_BIN_WITH_INT(char, 8, CHAR_IS_SIGNED) -ALL_OP_BIN_WITH_INT(signed char, 8, true) -ALL_OP_BIN_WITH_INT(unsigned char, 8, false) -ALL_OP_BIN_WITH_INT(short, _AP_SIZE_short, true) -ALL_OP_BIN_WITH_INT(unsigned short, _AP_SIZE_short, false) -ALL_OP_BIN_WITH_INT(int, _AP_SIZE_int, true) -ALL_OP_BIN_WITH_INT(unsigned int, _AP_SIZE_int, false) -ALL_OP_BIN_WITH_INT(long, _AP_SIZE_long, true) -ALL_OP_BIN_WITH_INT(unsigned long, _AP_SIZE_long, false) -ALL_OP_BIN_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true) -ALL_OP_BIN_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false) - -#undef OP_BIN_WITH_INT -#undef ALL_OP_BIN_WITH_INT - -// shift operators. -#define ALL_OP_SHIFT_WITH_INT(C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W,_AP_S>::arg1 operator<<( \ - const ap_int_base<_AP_W, _AP_S>& op, C_TYPE op2) { \ - ap_int_base<_AP_W, _AP_S> r; \ - if (_AP_S2) \ - r.V = op2 >= 0 ? (op.V << op2) : (op.V >> (-op2)); \ - else \ - r.V = op.V << op2; \ - return r; \ - } \ - template \ - INLINE typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W,_AP_S>::arg1 operator>>( \ - const ap_int_base<_AP_W, _AP_S>& op, C_TYPE op2) { \ - ap_int_base<_AP_W, _AP_S> r; \ - if (_AP_S2) \ - r.V = op2 >= 0 ? (op.V >> op2) : (op.V << (-op2)); \ - else \ - r.V = op.V >> op2; \ - return r; \ - } - -ALL_OP_SHIFT_WITH_INT(char, 8, CHAR_IS_SIGNED) -ALL_OP_SHIFT_WITH_INT(signed char, 8, true) -ALL_OP_SHIFT_WITH_INT(short, _AP_SIZE_short, true) -ALL_OP_SHIFT_WITH_INT(int, _AP_SIZE_int, true) -ALL_OP_SHIFT_WITH_INT(long, _AP_SIZE_long, true) -ALL_OP_SHIFT_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true) - -#undef ALL_OP_SHIFT_WITH_INT - -#define ALL_OP_SHIFT_WITH_INT(C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W,_AP_S>::arg1 operator<<( \ - const ap_int_base<_AP_W, _AP_S>& op, C_TYPE op2) { \ - ap_int_base<_AP_W, _AP_S> r; \ - r.V = op.V << op2; \ - return r; \ - } \ - template \ - INLINE typename ap_int_base<_AP_W, _AP_S>::template RType<_AP_W,_AP_S>::arg1 operator>>( \ - const ap_int_base<_AP_W, _AP_S>& op, C_TYPE op2) { \ - ap_int_base<_AP_W, _AP_S> r; \ - r.V = op.V >> op2; \ - return r; \ - } -ALL_OP_SHIFT_WITH_INT(bool, 1, false) -ALL_OP_SHIFT_WITH_INT(unsigned char, 8, false) -ALL_OP_SHIFT_WITH_INT(unsigned short, _AP_SIZE_short, false) -ALL_OP_SHIFT_WITH_INT(unsigned int, _AP_SIZE_int, false) -ALL_OP_SHIFT_WITH_INT(unsigned long, _AP_SIZE_long, false) -ALL_OP_SHIFT_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false) - -#undef ALL_OP_SHIFT_WITH_INT - -// compound assign operators. -#define OP_ASSIGN_WITH_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE ap_int_base<_AP_W, _AP_S>& operator ASSIGN_OP( \ - ap_int_base<_AP_W, _AP_S>& op, C_TYPE op2) { \ - return op ASSIGN_OP ap_int_base<_AP_W2, _AP_S2>(op2); \ - } - -// TODO int a; ap_int<16> b; a += b; - -#define ALL_OP_ASSIGN_WITH_INT(C_TYPE, _AP_W2, _AP_S2) \ - OP_ASSIGN_WITH_INT(+=, C_TYPE, _AP_W2, _AP_S2) \ - OP_ASSIGN_WITH_INT(-=, C_TYPE, _AP_W2, _AP_S2) \ - OP_ASSIGN_WITH_INT(*=, C_TYPE, _AP_W2, _AP_S2) \ - OP_ASSIGN_WITH_INT(/=, C_TYPE, _AP_W2, _AP_S2) \ - OP_ASSIGN_WITH_INT(%=, C_TYPE, _AP_W2, _AP_S2) \ - OP_ASSIGN_WITH_INT(&=, C_TYPE, _AP_W2, _AP_S2) \ - OP_ASSIGN_WITH_INT(|=, C_TYPE, _AP_W2, _AP_S2) \ - OP_ASSIGN_WITH_INT(^=, C_TYPE, _AP_W2, _AP_S2) \ - OP_ASSIGN_WITH_INT(>>=, C_TYPE, _AP_W2, _AP_S2) \ - OP_ASSIGN_WITH_INT(<<=, C_TYPE, _AP_W2, _AP_S2) - -ALL_OP_ASSIGN_WITH_INT(bool, 1, false) -ALL_OP_ASSIGN_WITH_INT(char, 8, CHAR_IS_SIGNED) -ALL_OP_ASSIGN_WITH_INT(signed char, 8, true) -ALL_OP_ASSIGN_WITH_INT(unsigned char, 8, false) -ALL_OP_ASSIGN_WITH_INT(short, _AP_SIZE_short, true) -ALL_OP_ASSIGN_WITH_INT(unsigned short, _AP_SIZE_short, false) -ALL_OP_ASSIGN_WITH_INT(int, _AP_SIZE_int, true) -ALL_OP_ASSIGN_WITH_INT(unsigned int, _AP_SIZE_int, false) -ALL_OP_ASSIGN_WITH_INT(long, _AP_SIZE_long, true) -ALL_OP_ASSIGN_WITH_INT(unsigned long, _AP_SIZE_long, false) -ALL_OP_ASSIGN_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true) -ALL_OP_ASSIGN_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false) - -#undef OP_ASSIGN_WITH_INT -#undef ALL_OP_ASSIGN_WITH_INT - -// equality and relational operators. -#define OP_REL_WITH_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE bool operator REL_OP(C_TYPE i_op, \ - const ap_int_base<_AP_W, _AP_S>& op) { \ - return ap_int_base<_AP_W2, _AP_S2>(i_op) REL_OP op; \ - } \ - template \ - INLINE bool operator REL_OP(const ap_int_base<_AP_W, _AP_S>& op, \ - C_TYPE op2) { \ - return op REL_OP ap_int_base<_AP_W2, _AP_S2>(op2); \ - } - -#define ALL_OP_REL_WITH_INT(C_TYPE, _AP_W2, _AP_S2) \ - OP_REL_WITH_INT(>, C_TYPE, _AP_W2, _AP_S2) \ - OP_REL_WITH_INT(<, C_TYPE, _AP_W2, _AP_S2) \ - OP_REL_WITH_INT(>=, C_TYPE, _AP_W2, _AP_S2) \ - OP_REL_WITH_INT(<=, C_TYPE, _AP_W2, _AP_S2) \ - OP_REL_WITH_INT(==, C_TYPE, _AP_W2, _AP_S2) \ - OP_REL_WITH_INT(!=, C_TYPE, _AP_W2, _AP_S2) - -ALL_OP_REL_WITH_INT(bool, 1, false) -ALL_OP_REL_WITH_INT(char, 8, CHAR_IS_SIGNED) -ALL_OP_REL_WITH_INT(signed char, 8, true) -ALL_OP_REL_WITH_INT(unsigned char, 8, false) -ALL_OP_REL_WITH_INT(short, _AP_SIZE_short, true) -ALL_OP_REL_WITH_INT(unsigned short, _AP_SIZE_short, false) -ALL_OP_REL_WITH_INT(int, _AP_SIZE_int, true) -ALL_OP_REL_WITH_INT(unsigned int, _AP_SIZE_int, false) -ALL_OP_REL_WITH_INT(long, _AP_SIZE_long, true) -ALL_OP_REL_WITH_INT(unsigned long, _AP_SIZE_long, false) -ALL_OP_REL_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true) -ALL_OP_REL_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false) - -#undef OP_REL_WITH_INT -#undef ALL_OP_BIN_WITH_INT - -#define OP_REL_WITH_DOUBLE_OR_FLOAT(Sym) \ - template \ - INLINE bool operator Sym(const ap_int_base<_AP_W, _AP_S>& op1, \ - double op2) { \ - return op1.to_double() Sym op2 ; \ - } \ - template \ - INLINE bool operator Sym(double op1, \ - const ap_int_base<_AP_W, _AP_S>& op2) { \ - return op1 Sym op2.to_double() ; \ - } \ - template \ - INLINE bool operator Sym(const ap_int_base<_AP_W, _AP_S>& op1, \ - float op2) { \ - return op1.to_double() Sym op2 ; \ - } \ - template \ - INLINE bool operator Sym(float op1, \ - const ap_int_base<_AP_W, _AP_S>& op2) { \ - return op1 Sym op2.to_double() ; \ - } - OP_REL_WITH_DOUBLE_OR_FLOAT(>) - OP_REL_WITH_DOUBLE_OR_FLOAT(<) - OP_REL_WITH_DOUBLE_OR_FLOAT(>=) - OP_REL_WITH_DOUBLE_OR_FLOAT(<=) - OP_REL_WITH_DOUBLE_OR_FLOAT(==) - OP_REL_WITH_DOUBLE_OR_FLOAT(!=) - -#undef OP_REL_WITH_DOUBLE_OR_FLOAT - - -/* Operators with ap_bit_ref. - * ------------------------------------------------------------ - */ -// arithmetic, bitwise and shift operators. -#define OP_BIN_WITH_RANGE(BIN_OP, RTYPE) \ - template \ - INLINE typename ap_int_base<_AP_W1, _AP_S1>::template RType<_AP_W2, \ - _AP_S2>::RTYPE \ - operator BIN_OP(const ap_range_ref<_AP_W1, _AP_S1>& op1, \ - const ap_int_base<_AP_W2, _AP_S2>& op2) { \ - return ap_int_base<_AP_W1, false>(op1) BIN_OP op2; \ - } \ - template \ - INLINE typename ap_int_base<_AP_W1, _AP_S1>::template RType<_AP_W2, \ - _AP_S2>::RTYPE \ - operator BIN_OP(const ap_int_base<_AP_W1, _AP_S1>& op1, \ - const ap_range_ref<_AP_W2, _AP_S2>& op2) { \ - return op1 BIN_OP ap_int_base<_AP_W2, false>(op2); \ - } - -OP_BIN_WITH_RANGE(+, plus) -OP_BIN_WITH_RANGE(-, minus) -OP_BIN_WITH_RANGE(*, mult) -OP_BIN_WITH_RANGE(/, div) -OP_BIN_WITH_RANGE(%, mod) -OP_BIN_WITH_RANGE(&, logic) -OP_BIN_WITH_RANGE(|, logic) -OP_BIN_WITH_RANGE(^, logic) -OP_BIN_WITH_RANGE(>>, arg1) -OP_BIN_WITH_RANGE(<<, arg1) - -#undef OP_BIN_WITH_RANGE - -// compound assignment operators. -#define OP_ASSIGN_WITH_RANGE(ASSIGN_OP) \ - template \ - INLINE ap_int_base<_AP_W1, _AP_S1>& operator ASSIGN_OP( \ - ap_int_base<_AP_W1, _AP_S1>& op1, ap_range_ref<_AP_W2, _AP_S2>& op2) { \ - return op1 ASSIGN_OP ap_int_base<_AP_W2, false>(op2); \ - } \ - template \ - INLINE ap_range_ref<_AP_W1, _AP_S1>& operator ASSIGN_OP( \ - ap_range_ref<_AP_W1, _AP_S1>& op1, ap_int_base<_AP_W2, _AP_S2>& op2) { \ - ap_int_base<_AP_W1, false> tmp(op1); \ - tmp ASSIGN_OP op2; \ - op1 = tmp; \ - return op1; \ - } - -OP_ASSIGN_WITH_RANGE(+=) -OP_ASSIGN_WITH_RANGE(-=) -OP_ASSIGN_WITH_RANGE(*=) -OP_ASSIGN_WITH_RANGE(/=) -OP_ASSIGN_WITH_RANGE(%=) -OP_ASSIGN_WITH_RANGE(&=) -OP_ASSIGN_WITH_RANGE(|=) -OP_ASSIGN_WITH_RANGE(^=) -OP_ASSIGN_WITH_RANGE(>>=) -OP_ASSIGN_WITH_RANGE(<<=) - -#undef OP_ASSIGN_WITH_RANGE - -// equality and relational operators -#define OP_REL_WITH_RANGE(REL_OP) \ - template \ - INLINE bool operator REL_OP(const ap_range_ref<_AP_W1, _AP_S1>& op1, \ - const ap_int_base<_AP_W2, _AP_S2>& op2) { \ - return ap_int_base<_AP_W1, false>(op1).operator REL_OP(op2); \ - } \ - template \ - INLINE bool operator REL_OP(const ap_int_base<_AP_W1, _AP_S1>& op1, \ - const ap_range_ref<_AP_W2, _AP_S2>& op2) { \ - return op1.operator REL_OP(op2.operator ap_int_base<_AP_W2, false>()); \ - } - -OP_REL_WITH_RANGE(==) -OP_REL_WITH_RANGE(!=) -OP_REL_WITH_RANGE(>) -OP_REL_WITH_RANGE(>=) -OP_REL_WITH_RANGE(<) -OP_REL_WITH_RANGE(<=) - -#undef OP_REL_WITH_RANGE - -/* Operators with ap_bit_ref. - * ------------------------------------------------------------ - */ -// arithmetic, bitwise and shift operators. -#define OP_BIN_WITH_BIT(BIN_OP, RTYPE) \ - template \ - INLINE typename ap_int_base<_AP_W1, _AP_S1>::template RType<1, false>::RTYPE \ - operator BIN_OP(const ap_int_base<_AP_W1, _AP_S1>& op1, \ - const ap_bit_ref<_AP_W2, _AP_S2>& op2) { \ - return op1 BIN_OP ap_int_base<1, false>(op2); \ - } \ - template \ - INLINE typename ap_int_base<1, false>::template RType<_AP_W2, _AP_S2>::RTYPE \ - operator BIN_OP(const ap_bit_ref<_AP_W1, _AP_S1>& op1, \ - const ap_int_base<_AP_W2, _AP_S2>& op2) { \ - return ap_int_base<1, false>(op1) BIN_OP op2; \ - } - -OP_BIN_WITH_BIT(+, plus) -OP_BIN_WITH_BIT(-, minus) -OP_BIN_WITH_BIT(*, mult) -OP_BIN_WITH_BIT(/, div) -OP_BIN_WITH_BIT(%, mod) -OP_BIN_WITH_BIT(&, logic) -OP_BIN_WITH_BIT(|, logic) -OP_BIN_WITH_BIT(^, logic) -OP_BIN_WITH_BIT(>>, arg1) -OP_BIN_WITH_BIT(<<, arg1) - -#undef OP_BIN_WITH_BIT - -// compound assignment operators. -#define OP_ASSIGN_WITH_BIT(ASSIGN_OP) \ - template \ - INLINE ap_int_base<_AP_W1, _AP_S1>& operator ASSIGN_OP( \ - ap_int_base<_AP_W1, _AP_S1>& op1, ap_bit_ref<_AP_W2, _AP_S2>& op2) { \ - return op1 ASSIGN_OP ap_int_base<1, false>(op2); \ - } \ - template \ - INLINE ap_bit_ref<_AP_W1, _AP_S1>& operator ASSIGN_OP( \ - ap_bit_ref<_AP_W1, _AP_S1>& op1, ap_int_base<_AP_W2, _AP_S2>& op2) { \ - ap_int_base<1, false> tmp(op1); \ - tmp ASSIGN_OP op2; \ - op1 = tmp; \ - return op1; \ - } - -OP_ASSIGN_WITH_BIT(+=) -OP_ASSIGN_WITH_BIT(-=) -OP_ASSIGN_WITH_BIT(*=) -OP_ASSIGN_WITH_BIT(/=) -OP_ASSIGN_WITH_BIT(%=) -OP_ASSIGN_WITH_BIT(&=) -OP_ASSIGN_WITH_BIT(|=) -OP_ASSIGN_WITH_BIT(^=) -OP_ASSIGN_WITH_BIT(>>=) -OP_ASSIGN_WITH_BIT(<<=) - -#undef OP_ASSIGN_WITH_BIT - -// equality and relational operators. -#define OP_REL_WITH_BIT(REL_OP) \ - template \ - INLINE bool operator REL_OP(const ap_int_base<_AP_W1, _AP_S1>& op1, \ - const ap_bit_ref<_AP_W2, _AP_S2>& op2) { \ - return op1 REL_OP ap_int_base<1, false>(op2); \ - } \ - template \ - INLINE bool operator REL_OP(const ap_bit_ref<_AP_W1, _AP_S1>& op1, \ - const ap_int_base<_AP_W2, _AP_S2>& op2) { \ - return ap_int_base<1, false>(op1) REL_OP op2; \ - } - -OP_REL_WITH_BIT(==) -OP_REL_WITH_BIT(!=) -OP_REL_WITH_BIT(>) -OP_REL_WITH_BIT(>=) -OP_REL_WITH_BIT(<) -OP_REL_WITH_BIT(<=) - -#undef OP_REL_WITH_BIT - - -/* Operators with ap_concat_ref. - * ------------------------------------------------------------ - */ -// arithmetic, bitwise and shift operators. -// bitwise operators are defined in struct. -// TODO specify whether to define arithmetic and bitwise operators. -#if 0 -#define OP_BIN_WITH_CONCAT(BIN_OP, RTYPE) \ - template \ - INLINE typename ap_int_base<_AP_W3, _AP_S3>::template RType<_AP_W1 + _AP_W2, \ - false>::RTYPE \ - operator BIN_OP(const ap_int_base<_AP_W3, _AP_S3>& op1, \ - const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& op2) { \ - /* convert ap_concat_ref to ap_int_base */ \ - return op1 BIN_OP op2.get(); \ - } \ - template \ - INLINE typename ap_int_base<_AP_W1 + _AP_W2, \ - false>::template RType<_AP_W3, _AP_S3>::RTYPE \ - operator BIN_OP(const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& op1, \ - const ap_int_base<_AP_W3, _AP_S3>& op2) { \ - /* convert ap_concat_ref to ap_int_base */ \ - return op1.get() BIN_OP op2; \ - } - -OP_BIN_WITH_CONCAT(+, plus) -OP_BIN_WITH_CONCAT(-, minus) -OP_BIN_WITH_CONCAT(*, mult) -OP_BIN_WITH_CONCAT(/, div) -OP_BIN_WITH_CONCAT(%, mod) -OP_BIN_WITH_CONCAT(&, logic) -OP_BIN_WITH_CONCAT(|, logic) -OP_BIN_WITH_CONCAT(^, logic) -OP_BIN_WITH_CONCAT(>>, arg1) -OP_BIN_WITH_CONCAT(<<, arg1) - -#undef OP_BIN_WITH_CONCAT - -// compound assignment operators. -#define OP_ASSIGN_WITH_CONCAT(ASSIGN_OP) \ - template \ - INLINE typename ap_int_base<_AP_W3, _AP_S3>::template RType<_AP_W1 + _AP_W2, \ - false>::RTYPE \ - operator ASSIGN_OP( \ - const ap_int_base<_AP_W3, _AP_S3>& op1, \ - const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& op2) { \ - /* convert ap_concat_ref to ap_int_base */ \ - return op1 ASSIGN_OP op2.get(); \ - } \ - template \ - INLINE typename ap_int_base<_AP_W1 + _AP_W2, \ - false>::template RType<_AP_W3, _AP_S3>::RTYPE \ - operator ASSIGN_OP(const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& op1, \ - const ap_int_base<_AP_W3, _AP_S3>& op2) { \ - /* convert ap_concat_ref to ap_int_base */ \ - ap_int_base<_AP_W1 + _AP_W2, false> tmp = op1.get(); \ - tmp ASSIGN_OP op2; \ - op1 = tmp; \ - return op1; \ - } - -OP_ASSIGN_WITH_CONCAT(+=) -OP_ASSIGN_WITH_CONCAT(-=) -OP_ASSIGN_WITH_CONCAT(*=) -OP_ASSIGN_WITH_CONCAT(/=) -OP_ASSIGN_WITH_CONCAT(%=) -OP_ASSIGN_WITH_CONCAT(&=) -OP_ASSIGN_WITH_CONCAT(|=) -OP_ASSIGN_WITH_CONCAT(^=) -OP_ASSIGN_WITH_CONCAT(>>=) -OP_ASSIGN_WITH_CONCAT(<<=) - -#undef OP_ASSIGN_WITH_CONCAT -#endif - -// equality and relational operators. -#define OP_REL_WITH_CONCAT(REL_OP) \ - template \ - INLINE bool operator REL_OP( \ - const ap_int_base<_AP_W3, _AP_S3>& op1, \ - const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& op2) { \ - /* convert ap_concat_ref to ap_int_base */ \ - return op1 REL_OP op2.get(); \ - } \ - template \ - INLINE bool operator REL_OP( \ - const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& op1, \ - const ap_int_base<_AP_W3, _AP_S3>& op2) { \ - /* convert ap_concat_ref to ap_int_base */ \ - return op1.get() REL_OP op2; \ - } - -OP_REL_WITH_CONCAT(==) -OP_REL_WITH_CONCAT(!=) -OP_REL_WITH_CONCAT(>) -OP_REL_WITH_CONCAT(>=) -OP_REL_WITH_CONCAT(<) -OP_REL_WITH_CONCAT(<=) - -#undef OP_REL_WITH_CONCAT - -#endif // ifndef __cplusplus -#endif // ifndef __AP_INT_BASE_H__ - -// -*- cpp -*- diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_int_ref.h b/model/AE_model/hls4ml_prj/firmware/ap_types/ap_int_ref.h deleted file mode 100644 index 421f09f..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_int_ref.h +++ /dev/null @@ -1,1346 +0,0 @@ -/* - * Copyright 2011-2019 Xilinx, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AP_INT_REF_H__ -#define __AP_INT_REF_H__ - -#ifndef __AP_INT_H__ -#error "Only ap_fixed.h and ap_int.h can be included directly in user code." -#endif - -#ifndef __cplusplus -#error "C++ is required to include this header file" - -#else - -#ifndef __SYNTHESIS__ -#include -#endif - -/* Concatination reference. - ---------------------------------------------------------------- -*/ -template -struct ap_concat_ref { - enum { - _AP_WR = _AP_W1 + _AP_W2, - }; - - _AP_T1& mbv1; - _AP_T2& mbv2; - - INLINE ap_concat_ref(const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& ref) - : mbv1(ref.mbv1), mbv2(ref.mbv2) {} - - INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2) : mbv1(bv1), mbv2(bv2) {} - - template - INLINE ap_concat_ref& operator=(const ap_int_base<_AP_W3, _AP_S3>& val) { - ap_int_base<_AP_W1 + _AP_W2, false> vval(val); - int W_ref1 = mbv1.length(); - int W_ref2 = mbv2.length(); - ap_int_base<_AP_W1, false> Part1; - Part1.V = _AP_ROOT_op_get_range(vval.V, W_ref2, W_ref1 + W_ref2 - 1); - mbv1.set(Part1); - ap_int_base<_AP_W2, false> Part2; - Part2.V = _AP_ROOT_op_get_range(vval.V, 0, W_ref2 - 1); - mbv2.set(Part2); - return *this; - } - - // assign op from hls supported C integral types. - // FIXME disabled to support legacy code directly assign from sc_signal - //template - //INLINE typename _ap_type::enable_if<_ap_type::is_integral::value, - // ap_concat_ref&>::type - //operator=(T val) { - // ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); - // return operator=(tmpVal); - //} -#define ASSIGN_WITH_CTYPE(_Tp) \ - INLINE ap_concat_ref& operator=(_Tp val) { \ - ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); \ - return operator=(tmpVal); \ - } - - ASSIGN_WITH_CTYPE(bool) - ASSIGN_WITH_CTYPE(char) - ASSIGN_WITH_CTYPE(signed char) - ASSIGN_WITH_CTYPE(unsigned char) - ASSIGN_WITH_CTYPE(short) - ASSIGN_WITH_CTYPE(unsigned short) - ASSIGN_WITH_CTYPE(int) - ASSIGN_WITH_CTYPE(unsigned int) - ASSIGN_WITH_CTYPE(long) - ASSIGN_WITH_CTYPE(unsigned long) - ASSIGN_WITH_CTYPE(ap_slong) - ASSIGN_WITH_CTYPE(ap_ulong) -#if _AP_ENABLE_HALF_ == 1 - ASSIGN_WITH_CTYPE(half) -#endif - ASSIGN_WITH_CTYPE(float) - ASSIGN_WITH_CTYPE(double) - -#undef ASSIGN_WITH_CTYPE - - // Be explicit to prevent it from being deleted, as field d_bv - // is of reference type. - INLINE ap_concat_ref& operator=( - const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& val) { - ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); - return operator=(tmpVal); - } - - template - INLINE ap_concat_ref& operator=( - const ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { - ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); - return operator=(tmpVal); - } - - template - INLINE ap_concat_ref& operator=(const ap_bit_ref<_AP_W3, _AP_S3>& val) { - ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); - return operator=(tmpVal); - } - template - INLINE ap_concat_ref& operator=(const ap_range_ref<_AP_W3, _AP_S3>& val) { - ap_int_base<_AP_W1 + _AP_W2, false> tmpVal(val); - return operator=(tmpVal); - } - - template - INLINE ap_concat_ref& operator=( - const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>& val) { - return operator=((const ap_int_base<_AP_W3, false>)(val)); - } - - template - INLINE ap_concat_ref& operator=( - const ap_fixed_base<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>& - val) { - return operator=(val.to_ap_int_base()); - } - - template - INLINE ap_concat_ref& operator=( - const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>& val) { - return operator=((ap_ulong)(bool)(val)); - } - - INLINE operator ap_int_base<_AP_WR, false>() const { return get(); } - - INLINE operator ap_ulong() const { return get().to_uint64(); } - - template - INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, - ap_range_ref<_AP_W3, _AP_S3> > - operator,(const ap_range_ref<_AP_W3, _AP_S3> &a2) { - return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, - ap_range_ref<_AP_W3, _AP_S3> >( - *this, const_cast&>(a2)); - } - - template - INLINE - ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_int_base<_AP_W3, _AP_S3> > - operator,(ap_int_base<_AP_W3, _AP_S3> &a2) { - return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, - ap_int_base<_AP_W3, _AP_S3> >(*this, a2); - } - - template - INLINE - ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_int_base<_AP_W3, _AP_S3> > - operator,(volatile ap_int_base<_AP_W3, _AP_S3> &a2) { - return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, - ap_int_base<_AP_W3, _AP_S3> >( - *this, const_cast&>(a2)); - } - - template - INLINE - ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_int_base<_AP_W3, _AP_S3> > - operator,(const ap_int_base<_AP_W3, _AP_S3> &a2) { - return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, - ap_int_base<_AP_W3, _AP_S3> >( - *this, const_cast&>(a2)); - } - - template - INLINE - ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_int_base<_AP_W3, _AP_S3> > - operator,(const volatile ap_int_base<_AP_W3, _AP_S3> &a2) { - // FIXME op's life does not seem long enough - ap_int_base<_AP_W3, _AP_S3> op(a2); - return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, - ap_int_base<_AP_W3, _AP_S3> >( - *this, const_cast&>(op)); - } - - template - INLINE ap_concat_ref<_AP_WR, ap_concat_ref, 1, ap_bit_ref<_AP_W3, _AP_S3> > - operator,(const ap_bit_ref<_AP_W3, _AP_S3> &a2) { - return ap_concat_ref<_AP_WR, ap_concat_ref, 1, ap_bit_ref<_AP_W3, _AP_S3> >( - *this, const_cast&>(a2)); - } - - template - INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3 + _AP_W4, - ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4> > - operator,(const ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4> &a2) { - return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3 + _AP_W4, - ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4> >( - *this, const_cast&>(a2)); - } - - template - INLINE ap_concat_ref< - _AP_WR, ap_concat_ref, _AP_W3, - af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > - operator,( - const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> &a2) { - return ap_concat_ref< - _AP_WR, ap_concat_ref, _AP_W3, - af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >( - *this, - const_cast< - af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>&>(a2)); - } - - template - INLINE - ap_concat_ref<_AP_WR, ap_concat_ref, 1, - af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > - operator,(const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> - &a2) { - return ap_concat_ref< - _AP_WR, ap_concat_ref, 1, - af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >( - *this, - const_cast&>( - a2)); - } - - template - INLINE ap_int_base operator&( - const ap_int_base<_AP_W3, _AP_S3>& a2) { - return get() & a2; - } - - template - INLINE ap_int_base operator|( - const ap_int_base<_AP_W3, _AP_S3>& a2) { - return get() | a2; - } - - template - INLINE ap_int_base operator^( - const ap_int_base<_AP_W3, _AP_S3>& a2) { - return get() ^ a2; - } - -#if 0 - template - INLINE ap_int_base slice() { - ap_int_base<_AP_WR, false> bv = get(); - return bv.slice(); - } -#endif - - INLINE ap_int_base<_AP_WR, false> get() const { - ap_int_base<_AP_WR, false> tmpVal(0); - int W_ref1 = mbv1.length(); - int W_ref2 = mbv2.length(); - ap_int_base<_AP_W2, false> v2(mbv2); - ap_int_base<_AP_W1, false> v1(mbv1); - tmpVal.V = _AP_ROOT_op_set_range(tmpVal.V, 0, W_ref2 - 1, v2.V); - tmpVal.V = - _AP_ROOT_op_set_range(tmpVal.V, W_ref2, W_ref1 + W_ref2 - 1, v1.V); - return tmpVal; - } - - template - INLINE void set(const ap_int_base<_AP_W3, false>& val) { - ap_int_base<_AP_W1 + _AP_W2, false> vval(val); - int W_ref1 = mbv1.length(); - int W_ref2 = mbv2.length(); - ap_int_base<_AP_W1, false> tmpVal1; - tmpVal1.V = _AP_ROOT_op_get_range(vval.V, W_ref2, W_ref1 + W_ref2 - 1); - mbv1.set(tmpVal1); - ap_int_base<_AP_W2, false> tmpVal2; - tmpVal2.V = _AP_ROOT_op_get_range(vval.V, 0, W_ref2 - 1); - mbv2.set(tmpVal2); - } - - INLINE int length() const { return mbv1.length() + mbv2.length(); } -}; // struct ap_concat_ref - -/* Range (slice) reference. - ---------------------------------------------------------------- -*/ -template -struct ap_range_ref { - // struct ssdm_int or its sim model. - // TODO make it possible to reference to ap_fixed_base/ap_fixed/ap_ufixed - // and then we can retire af_range_ref. - typedef ap_int_base<_AP_W, _AP_S> ref_type; - ref_type& d_bv; - int l_index; - int h_index; - - public: - INLINE ap_range_ref(const ap_range_ref<_AP_W, _AP_S>& ref) - : d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} - - INLINE ap_range_ref(ref_type* bv, int h, int l) - : d_bv(*bv), l_index(l), h_index(h) {} - - INLINE ap_range_ref(const ref_type* bv, int h, int l) - : d_bv(*const_cast(bv)), l_index(l), h_index(h) {} - - INLINE operator ap_int_base<_AP_W, false>() const { - ap_int_base<_AP_W, false> ret; - ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); - return ret; - } - - INLINE operator ap_ulong() const { return to_uint64(); } - - /// @name assign operators - // @{ - - // FIXME disabled to work-around lagacy code assigning from sc_signal, - // which dependes on implicit type conversion. - // - // /// assign from hls supported C integral types. - // template - // INLINE typename _ap_type::enable_if<_ap_type::is_integral::value, - // ap_range_ref&>::type - // operator=(T val) { - // ap_int_base<_AP_W, false> tmp(val); - // d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V); - // return *this; - // } -#define ASSIGN_WITH_CTYPE(_Tp) \ - INLINE ap_range_ref& operator=(_Tp val) { \ - ap_int_base<_AP_W, false> tmp(val); \ - d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V); \ - return *this; \ - } - - ASSIGN_WITH_CTYPE(bool) - ASSIGN_WITH_CTYPE(char) - ASSIGN_WITH_CTYPE(signed char) - ASSIGN_WITH_CTYPE(unsigned char) - ASSIGN_WITH_CTYPE(short) - ASSIGN_WITH_CTYPE(unsigned short) - ASSIGN_WITH_CTYPE(int) - ASSIGN_WITH_CTYPE(unsigned int) - ASSIGN_WITH_CTYPE(long) - ASSIGN_WITH_CTYPE(unsigned long) - ASSIGN_WITH_CTYPE(ap_slong) - ASSIGN_WITH_CTYPE(ap_ulong) -#if _AP_ENABLE_HALF_ == 1 - ASSIGN_WITH_CTYPE(half) -#endif - ASSIGN_WITH_CTYPE(float) - ASSIGN_WITH_CTYPE(double) - -#undef ASSIGN_WITH_CTYPE - - /// assign using string. XXX crucial for cosim. - INLINE ap_range_ref& operator=(const char* val) { - const ap_int_base<_AP_W, false> tmp(val); // XXX figure out radix - d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V); - return *this; - } - - /// assign from ap_int_base. - template - INLINE ap_range_ref& operator=(const ap_int_base<_AP_W2, _AP_S2>& val) { - ap_int_base<_AP_W, false> tmp(val); - d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, tmp.V); - return *this; - } - - /// copy assign operator - // XXX Be explicit to prevent it from being deleted, as field d_bv - // is of reference type. - INLINE ap_range_ref& operator=(const ap_range_ref& val) { - return operator=((const ap_int_base<_AP_W, false>)val); - } - - /// assign from range reference to ap_int_base. - template - INLINE ap_range_ref& operator=(const ap_range_ref<_AP_W2, _AP_S2>& val) { - return operator=((const ap_int_base<_AP_W2, false>)val); - } - - /// assign from bit reference to ap_int_base. - template - INLINE ap_range_ref& operator=(const ap_bit_ref<_AP_W2, _AP_S2>& val) { - return operator=((ap_ulong)(bool)(val)); - } - - /// assign from ap_fixed_base. - template - INLINE ap_range_ref& operator=( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& - val) { - return operator=(val.to_ap_int_base()); - } - - /// assign from range reference to ap_fixed_base. - template - INLINE ap_range_ref& operator=( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - return operator=((const ap_int_base<_AP_W2, false>)val); - } - - /// assign from bit reference to ap_fixed_base. - template - INLINE ap_range_ref& operator=( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - return operator=((ap_ulong)(bool)(val)); - } - - /// assign from compound reference. - template - INLINE ap_range_ref& operator=( - const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { - return operator=((const ap_int_base<_AP_W2 + _AP_W3, false>)(val)); - } - // @} - - template - INLINE - ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > - operator,(const ap_range_ref<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, - ap_range_ref<_AP_W2, _AP_S2> >( - *this, const_cast&>(a2)); - } - - template - INLINE - ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(ap_int_base<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, - ap_int_base<_AP_W2, _AP_S2> >(*this, a2); - } - - INLINE - ap_concat_ref<_AP_W, ap_range_ref, _AP_W, ap_int_base<_AP_W, _AP_S> > - operator,(ap_int_base<_AP_W, _AP_S>& a2) { - return ap_concat_ref<_AP_W, ap_range_ref, _AP_W, - ap_int_base<_AP_W, _AP_S> >(*this, a2); - } - - template - INLINE - ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(volatile ap_int_base<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, - ap_int_base<_AP_W2, _AP_S2> >( - *this, const_cast&>(a2)); - } - - template - INLINE - ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(const ap_int_base<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, - ap_int_base<_AP_W2, _AP_S2> >( - *this, const_cast&>(a2)); - } - - template - INLINE - ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(const volatile ap_int_base<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2, - ap_int_base<_AP_W2, _AP_S2> >( - *this, const_cast&>(a2)); - } - - template - INLINE ap_concat_ref<_AP_W, ap_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > - operator,(const ap_bit_ref<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<_AP_W, ap_range_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> >( - *this, const_cast&>(a2)); - } - - template - INLINE ap_concat_ref<_AP_W, ap_range_ref, _AP_W2 + _AP_W3, - ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > - operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { - return ap_concat_ref<_AP_W, ap_range_ref, _AP_W2 + _AP_W3, - ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >( - *this, const_cast&>(a2)); - } - - template - INLINE ap_concat_ref< - _AP_W, ap_range_ref, _AP_W2, - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > - operator,( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> a2) { - return ap_concat_ref< - _AP_W, ap_range_ref, _AP_W2, - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( - *this, - const_cast< - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>&>(a2)); - } - - template - INLINE - ap_concat_ref<_AP_W, ap_range_ref, 1, - af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > - operator,(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> - &a2) { - return ap_concat_ref< - _AP_W, ap_range_ref, 1, - af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( - *this, - const_cast&>( - a2)); - } - - template - INLINE bool operator==(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - ap_int_base<_AP_W, false> lop(*this); - ap_int_base<_AP_W2, false> hop(op2); - return lop == hop; - } - - template - INLINE bool operator!=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - return !(operator==(op2)); - } - - template - INLINE bool operator<(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - ap_int_base<_AP_W, false> lop(*this); - ap_int_base<_AP_W2, false> hop(op2); - return lop < hop; - } - - template - INLINE bool operator<=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - ap_int_base<_AP_W, false> lop(*this); - ap_int_base<_AP_W2, false> hop(op2); - return lop <= hop; - } - - template - INLINE bool operator>(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - return !(operator<=(op2)); - } - - template - INLINE bool operator>=(const ap_range_ref<_AP_W2, _AP_S2>& op2) { - return !(operator<(op2)); - } - - template - INLINE ap_range_ref<_AP_W, _AP_S>& operator|=( - const ap_range_ref<_AP_W2, _AP_S2>& op2) { - (this->d_bv).V |= (op2.d_bv).V; - return *this; - }; - - template - INLINE ap_range_ref<_AP_W, _AP_S>& operator|=( - const ap_int_base<_AP_W2, _AP_S2>& op2) { - (this->d_bv).V |= op2.V; - return *this; - }; - - template - INLINE ap_range_ref<_AP_W, _AP_S>& operator&=( - const ap_range_ref<_AP_W2, _AP_S2>& op2) { - (this->d_bv).V &= (op2.d_bv).V; - return *this; - }; - - template - INLINE ap_range_ref<_AP_W, _AP_S>& operator&=( - const ap_int_base<_AP_W2, _AP_S2>& op2) { - (this->d_bv).V &= op2.V; - return *this; - }; - - template - INLINE ap_range_ref<_AP_W, _AP_S>& operator^=( - const ap_range_ref<_AP_W2, _AP_S2>& op2) { - (this->d_bv).V ^= (op2.d_bv).V; - return *this; - }; - - template - INLINE ap_range_ref<_AP_W, _AP_S>& operator^=( - const ap_int_base<_AP_W2, _AP_S2>& op2) { - (this->d_bv).V ^= op2.V; - return *this; - }; - - INLINE ap_int_base<_AP_W, false> get() const { - ap_int_base<_AP_W, false> ret; - ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); - return ret; - } - - template - INLINE void set(const ap_int_base<_AP_W2, false>& val) { - d_bv.V = _AP_ROOT_op_set_range(d_bv.V, l_index, h_index, val.V); - } - - INLINE int length() const { - return h_index >= l_index ? h_index - l_index + 1 : l_index - h_index + 1; - } - - INLINE int to_int() const { - return (int)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE unsigned to_uint() const { - return (unsigned)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE long to_long() const { - return (long)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE unsigned long to_ulong() const { - return (unsigned long)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE ap_slong to_int64() const { - return (ap_slong)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE ap_ulong to_uint64() const { - return (ap_ulong)(_AP_ROOT_op_get_range(d_bv.V, l_index, h_index)); - } - - INLINE bool and_reduce() const { - bool ret = true; - bool reverse = l_index > h_index; - unsigned low = reverse ? h_index : l_index; - unsigned high = reverse ? l_index : h_index; - for (unsigned i = low; i != high; ++i) { -#ifdef __SYNTHESIS__ -#pragma HLS unroll -#endif - ret &= _AP_ROOT_op_get_bit(d_bv.V, i); - } - return ret; - } - - INLINE bool or_reduce() const { - bool ret = false; - bool reverse = l_index > h_index; - unsigned low = reverse ? h_index : l_index; - unsigned high = reverse ? l_index : h_index; - for (unsigned i = low; i != high; ++i) { -#ifdef __SYNTHESIS__ -#pragma HLS unroll -#endif - ret |= _AP_ROOT_op_get_bit(d_bv.V, i); - } - return ret; - } - - INLINE bool xor_reduce() const { - bool ret = false; - bool reverse = l_index > h_index; - unsigned low = reverse ? h_index : l_index; - unsigned high = reverse ? l_index : h_index; - for (unsigned i = low; i != high; ++i) { -#ifdef __SYNTHESIS__ -#pragma HLS unroll -#endif - ret ^= _AP_ROOT_op_get_bit(d_bv.V, i); - } - return ret; - } -#ifndef __SYNTHESIS__ - std::string to_string(signed char radix = 2) const { - ap_int_base<_AP_W, false> ret; - ret.V = _AP_ROOT_op_get_range(d_bv.V, l_index, h_index); - return ret.to_string(radix); - } -#else - // XXX HLS will delete this in synthesis - INLINE char* to_string(signed char radix = 2) const { - return 0; - } -#endif -}; // struct ap_range_ref - -// XXX apcc cannot handle global std::ios_base::Init() brought in by -#ifndef AP_AUTOCC -#ifndef __SYNTHESIS__ -template -INLINE std::ostream& operator<<(std::ostream& os, - const ap_range_ref<_AP_W, _AP_S>& x) { - std::ios_base::fmtflags ff = std::cout.flags(); - if (ff & std::cout.hex) { - os << x.to_string(16); // don't print sign - } else if (ff & std::cout.oct) { - os << x.to_string(8); // don't print sign - } else { - os << x.to_string(10); - } - return os; -} -#endif // ifndef __SYNTHESIS__ - -#ifndef __SYNTHESIS__ -template -INLINE std::istream& operator>>(std::istream& in, - ap_range_ref<_AP_W, _AP_S>& op) { - std::string str; - in >> str; - op = ap_int_base<_AP_W, _AP_S>(str.c_str()); - return in; -} -#endif // ifndef __SYNTHESIS__ -#endif // ifndef AP_AUTOCC - -/* Bit reference. - ---------------------------------------------------------------- -*/ -template -struct ap_bit_ref { - // struct ssdm_int or its sim model. - // TODO make it possible to reference to ap_fixed_base/ap_fixed/ap_ufixed - // and then we can retire af_bit_ref. - typedef ap_int_base<_AP_W, _AP_S> ref_type; - ref_type& d_bv; - int d_index; - - public: - // copy ctor - INLINE ap_bit_ref(const ap_bit_ref<_AP_W, _AP_S>& ref) - : d_bv(ref.d_bv), d_index(ref.d_index) {} - - INLINE ap_bit_ref(ref_type* bv, int index = 0) : d_bv(*bv), d_index(index) {} - - INLINE ap_bit_ref(const ref_type* bv, int index = 0) - : d_bv(*const_cast(bv)), d_index(index) {} - - INLINE operator bool() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); } - INLINE bool to_bool() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); } - - // assign op from hls supported C integral types. - // FIXME disabled to support sc_signal. - // NOTE this used to be unsigned long long. - //template - //INLINE typename _ap_type::enable_if<_ap_type::is_integral::value, - // ap_bit_ref&>::type - //operator=(T val) { - // d_bv.V = _AP_ROOT_op_set_bit(d_bv.V, d_index, val); - // return *this; - //} -#define ASSIGN_WITH_CTYPE(_Tp) \ - INLINE ap_bit_ref& operator=(_Tp val) { \ - d_bv.V = _AP_ROOT_op_set_bit(d_bv.V, d_index, val); \ - return *this; \ - } - - ASSIGN_WITH_CTYPE(bool) - ASSIGN_WITH_CTYPE(char) - ASSIGN_WITH_CTYPE(signed char) - ASSIGN_WITH_CTYPE(unsigned char) - ASSIGN_WITH_CTYPE(short) - ASSIGN_WITH_CTYPE(unsigned short) - ASSIGN_WITH_CTYPE(int) - ASSIGN_WITH_CTYPE(unsigned int) - ASSIGN_WITH_CTYPE(long) - ASSIGN_WITH_CTYPE(unsigned long) - ASSIGN_WITH_CTYPE(ap_slong) - ASSIGN_WITH_CTYPE(ap_ulong) - -#undef ASSIGN_WITH_CTYPE - -#define ASSIGN_WITH_CTYPE_FP(_Tp) \ - INLINE ap_bit_ref& operator=(_Tp val) { \ - bool tmp_val = val; \ - d_bv.V = _AP_ROOT_op_set_bit(d_bv.V, d_index,tmp_val); \ - return *this; \ - } - -#if _AP_ENABLE_HALF_ == 1 - ASSIGN_WITH_CTYPE_FP(half) -#endif - ASSIGN_WITH_CTYPE_FP(float) - ASSIGN_WITH_CTYPE_FP(double) - -#undef ASSIGN_WITH_CTYPE_FP - - - template - INLINE ap_bit_ref& operator=(const ap_int_base<_AP_W2, _AP_S2>& val) { - return operator=((ap_ulong)(val.V != 0)); - } - - template - INLINE ap_bit_ref& operator=(const ap_range_ref<_AP_W2, _AP_S2>& val) { - return operator=((ap_int_base<_AP_W2, false>)val); - } - - // Be explicit to prevent it from being deleted, as field d_bv - // is of reference type. - INLINE ap_bit_ref& operator=(const ap_bit_ref& val) { - return operator=((ap_ulong)(bool)val); - } - - template - INLINE ap_bit_ref& operator=(const ap_bit_ref<_AP_W2, _AP_S2>& val) { - return operator=((ap_ulong)(bool)val); - } - - template - INLINE ap_bit_ref& operator=( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - return operator=((const ap_int_base<_AP_W2, false>)val); - } - - template - INLINE ap_bit_ref& operator=( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - return operator=((ap_ulong)(bool)val); - } - - template - INLINE ap_bit_ref& operator=( - const ap_concat_ref<_AP_W2, _AP_T3, _AP_W3, _AP_T3>& val) { - return operator=((const ap_int_base<_AP_W2 + _AP_W3, false>)val); - } - - template - INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(ap_int_base<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> >( - *this, a2); - } - - template - INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(volatile ap_int_base<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> >( - *this, const_cast&>(a2)); - } - - template - INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(const ap_int_base<_AP_W2, _AP_S2> &a2) { - ap_int_base<_AP_W2, _AP_S2> op(a2); - return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> >( - *this, const_cast&>(op)); - } - - template - INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> > - operator,(const volatile ap_int_base<_AP_W2, _AP_S2> &a2) { - ap_int_base<_AP_W2, _AP_S2> op(a2); - return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_int_base<_AP_W2, _AP_S2> >( - *this, const_cast&>(op)); - } - - template - INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> > - operator,(const ap_range_ref<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<1, ap_bit_ref, _AP_W2, ap_range_ref<_AP_W2, _AP_S2> >( - *this, const_cast&>(a2)); - } - - template - INLINE ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> > operator,( - const ap_bit_ref<_AP_W2, _AP_S2> &a2) { - return ap_concat_ref<1, ap_bit_ref, 1, ap_bit_ref<_AP_W2, _AP_S2> >( - *this, const_cast&>(a2)); - } - - template - INLINE ap_concat_ref<1, ap_bit_ref, _AP_W2 + _AP_W3, - ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > - operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { - return ap_concat_ref<1, ap_bit_ref, _AP_W2 + _AP_W3, - ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >( - *this, const_cast&>(a2)); - } - - template - INLINE ap_concat_ref< - 1, ap_bit_ref, _AP_W2, - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > - operator,( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) { - return ap_concat_ref< - 1, ap_bit_ref, _AP_W2, - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( - *this, - const_cast< - af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>&>(a2)); - } - - template - INLINE ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, - _AP_Q2, _AP_O2, _AP_N2> > - operator,( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) { - return ap_concat_ref<1, ap_bit_ref, 1, af_bit_ref<_AP_W2, _AP_I2, _AP_S2, - _AP_Q2, _AP_O2, _AP_N2> >( - *this, - const_cast&>( - a2)); - } - - template - INLINE bool operator==(const ap_bit_ref<_AP_W2, _AP_S2>& op) { - return get() == op.get(); - } - - template - INLINE bool operator!=(const ap_bit_ref<_AP_W2, _AP_S2>& op) { - return get() != op.get(); - } - - INLINE bool get() const { return _AP_ROOT_op_get_bit(d_bv.V, d_index); } - - INLINE bool get() { return _AP_ROOT_op_get_bit(d_bv.V, d_index); } - - template - INLINE void set(const ap_int_base<_AP_W3, false>& val) { - operator=(val); - } - - INLINE bool operator~() const { - bool bit = _AP_ROOT_op_get_bit(d_bv.V, d_index); - return bit ? false : true; - } - - INLINE int length() const { return 1; } - -#ifndef __SYNTHESIS__ - std::string to_string() const { return get() ? "1" : "0"; } -#else - // XXX HLS will delete this in synthesis - INLINE char* to_string() const { return 0; } -#endif -}; // struct ap_bit_ref - -/* ap_range_ref with int. - * ------------------------------------------------------------ - */ -// equality and relational operators. -#define REF_REL_OP_WITH_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE bool operator REL_OP(const ap_range_ref<_AP_W, _AP_S>& op, \ - C_TYPE op2) { \ - return ap_int_base<_AP_W, false>(op) \ - REL_OP ap_int_base<_AP_W2, _AP_S2>(op2); \ - } \ - template \ - INLINE bool operator REL_OP(const ap_bit_ref<_AP_W, _AP_S>& op, \ - C_TYPE op2) { \ - return bool(op) REL_OP op2; \ - } \ - template \ - INLINE bool operator REL_OP(C_TYPE op2, \ - const ap_bit_ref<_AP_W, _AP_S>& op) { \ - return op2 REL_OP bool(op); \ - } \ - template \ - INLINE bool operator REL_OP( \ - const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1>& op, C_TYPE op2) { \ - return ap_int_base<_AP_W + _AP_W1, false>(op) \ - REL_OP ap_int_base<_AP_W2, _AP_S2>(op2); \ - } - -// Make the line shorter than 5000 chars -#define REF_REL_WITH_INT_1(C_TYPE, _AP_WI, _AP_SI) \ - REF_REL_OP_WITH_INT(>, C_TYPE, _AP_WI, _AP_SI) \ - REF_REL_OP_WITH_INT(<, C_TYPE, _AP_WI, _AP_SI) \ - REF_REL_OP_WITH_INT(>=, C_TYPE, _AP_WI, _AP_SI) \ - REF_REL_OP_WITH_INT(<=, C_TYPE, _AP_WI, _AP_SI) - -REF_REL_WITH_INT_1(bool, 1, false) -REF_REL_WITH_INT_1(char, 8, CHAR_IS_SIGNED) -REF_REL_WITH_INT_1(signed char, 8, true) -REF_REL_WITH_INT_1(unsigned char, 8, false) -REF_REL_WITH_INT_1(short, _AP_SIZE_short, true) -REF_REL_WITH_INT_1(unsigned short, _AP_SIZE_short, false) -REF_REL_WITH_INT_1(int, _AP_SIZE_int, true) -REF_REL_WITH_INT_1(unsigned int, _AP_SIZE_int, false) -REF_REL_WITH_INT_1(long, _AP_SIZE_long, true) -REF_REL_WITH_INT_1(unsigned long, _AP_SIZE_long, false) -REF_REL_WITH_INT_1(ap_slong, _AP_SIZE_ap_slong, true) -REF_REL_WITH_INT_1(ap_ulong, _AP_SIZE_ap_slong, false) - -// Make the line shorter than 5000 chars -#define REF_REL_WITH_INT_2(C_TYPE, _AP_WI, _AP_SI) \ - REF_REL_OP_WITH_INT(==, C_TYPE, _AP_WI, _AP_SI) \ - REF_REL_OP_WITH_INT(!=, C_TYPE, _AP_WI, _AP_SI) - -REF_REL_WITH_INT_2(bool, 1, false) -REF_REL_WITH_INT_2(char, 8, CHAR_IS_SIGNED) -REF_REL_WITH_INT_2(signed char, 8, true) -REF_REL_WITH_INT_2(unsigned char, 8, false) -REF_REL_WITH_INT_2(short, _AP_SIZE_short, true) -REF_REL_WITH_INT_2(unsigned short, _AP_SIZE_short, false) -REF_REL_WITH_INT_2(int, _AP_SIZE_int, true) -REF_REL_WITH_INT_2(unsigned int, _AP_SIZE_int, false) -REF_REL_WITH_INT_2(long, _AP_SIZE_long, true) -REF_REL_WITH_INT_2(unsigned long, _AP_SIZE_long, false) -REF_REL_WITH_INT_2(ap_slong, _AP_SIZE_ap_slong, true) -REF_REL_WITH_INT_2(ap_ulong, _AP_SIZE_ap_slong, false) - -#undef REF_REL_OP_WITH_INT -#undef REF_REL_WITH_INT_1 -#undef REF_REL_WITH_INT_2 - -#define REF_BIN_OP_WITH_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE typename ap_int_base<_AP_W, false>::template RType<_AP_W2, \ - _AP_S2>::RTYPE \ - operator BIN_OP(const ap_range_ref<_AP_W, _AP_S>& op, C_TYPE op2) { \ - return ap_int_base<_AP_W, false>(op) \ - BIN_OP ap_int_base<_AP_W2, _AP_S2>(op2); \ - } \ - template \ - INLINE typename ap_int_base<_AP_W2, _AP_S2>::template RType<_AP_W, \ - false>::RTYPE \ - operator BIN_OP(C_TYPE op2, const ap_range_ref<_AP_W, _AP_S>& op) { \ - return ap_int_base<_AP_W2, _AP_S2>(op2) \ - BIN_OP ap_int_base<_AP_W, false>(op); \ - } - -// arithmetic operators. -#define REF_BIN_OP_WITH_INT_ARITH(C_TYPE, _AP_W2, _AP_S2) \ - REF_BIN_OP_WITH_INT(+, plus, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_WITH_INT(-, minus, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_WITH_INT(*, mult, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_WITH_INT(/, div, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_WITH_INT(%, mod, C_TYPE, (_AP_W2), (_AP_S2)) - -REF_BIN_OP_WITH_INT_ARITH(bool, 1, false) -REF_BIN_OP_WITH_INT_ARITH(char, 8, CHAR_IS_SIGNED) -REF_BIN_OP_WITH_INT_ARITH(signed char, 8, true) -REF_BIN_OP_WITH_INT_ARITH(unsigned char, 8, false) -REF_BIN_OP_WITH_INT_ARITH(short, _AP_SIZE_short, true) -REF_BIN_OP_WITH_INT_ARITH(unsigned short, _AP_SIZE_short, false) -REF_BIN_OP_WITH_INT_ARITH(int, _AP_SIZE_int, true) -REF_BIN_OP_WITH_INT_ARITH(unsigned int, _AP_SIZE_int, false) -REF_BIN_OP_WITH_INT_ARITH(long, _AP_SIZE_long, true) -REF_BIN_OP_WITH_INT_ARITH(unsigned long, _AP_SIZE_long, false) -REF_BIN_OP_WITH_INT_ARITH(ap_slong, _AP_SIZE_ap_slong, true) -REF_BIN_OP_WITH_INT_ARITH(ap_ulong, _AP_SIZE_ap_slong, false) - -#undef REF_BIN_OP_WITH_INT_ARITH - -// bitwise and shift operators -#define REF_BIN_OP_WITH_INT_BITS(C_TYPE, _AP_W2, _AP_S2) \ - REF_BIN_OP_WITH_INT(&, logic, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_WITH_INT(|, logic, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_WITH_INT(^, logic, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_WITH_INT(>>, arg1, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_WITH_INT(<<, arg1, C_TYPE, (_AP_W2), (_AP_S2)) - -REF_BIN_OP_WITH_INT_BITS(bool, 1, false) -REF_BIN_OP_WITH_INT_BITS(char, 8, CHAR_IS_SIGNED) -REF_BIN_OP_WITH_INT_BITS(signed char, 8, true) -REF_BIN_OP_WITH_INT_BITS(unsigned char, 8, false) -REF_BIN_OP_WITH_INT_BITS(short, _AP_SIZE_short, true) -REF_BIN_OP_WITH_INT_BITS(unsigned short, _AP_SIZE_short, false) -REF_BIN_OP_WITH_INT_BITS(int, _AP_SIZE_int, true) -REF_BIN_OP_WITH_INT_BITS(unsigned int, _AP_SIZE_int, false) -REF_BIN_OP_WITH_INT_BITS(long, _AP_SIZE_long, true) -REF_BIN_OP_WITH_INT_BITS(unsigned long, _AP_SIZE_long, false) -REF_BIN_OP_WITH_INT_BITS(ap_slong, _AP_SIZE_ap_slong, true) -REF_BIN_OP_WITH_INT_BITS(ap_ulong, _AP_SIZE_ap_slong, false) - -#undef REF_BIN_OP_WITH_INT_BITS - -/* ap_range_ref with ap_range_ref - * ------------------------------------------------------------ - */ -#define REF_BIN_OP(BIN_OP, RTYPE) \ - template \ - INLINE \ - typename ap_int_base<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \ - operator BIN_OP(const ap_range_ref<_AP_W, _AP_S>& lhs, \ - const ap_range_ref<_AP_W2, _AP_S2>& rhs) { \ - return (lhs.operator ap_int_base<_AP_W, false>())BIN_OP( \ - rhs.operator ap_int_base<_AP_W2, false>()); \ - } - -REF_BIN_OP(+, plus) -REF_BIN_OP(-, minus) -REF_BIN_OP(*, mult) -REF_BIN_OP(/, div) -REF_BIN_OP(%, mod) -REF_BIN_OP(&, logic) -REF_BIN_OP(|, logic) -REF_BIN_OP(^, logic) -REF_BIN_OP(>>, arg1) -REF_BIN_OP(<<, arg1) - -/* ap_concat_ref with ap_concat_ref. - * ------------------------------------------------------------ - */ - -//************************************************************************ -// Implement -// ap_int_base = ap_concat_ref OP ap_concat_ref -// for operators +, -, *, /, %, >>, <<, &, |, ^ -// Without these operators the operands are converted to int64 and -// larger results lose informations (higher order bits). -// -// operand OP -// / | -// left-concat right-concat -// / | / | -// -// -// _AP_LW1, _AP_LT1 (width and type of left-concat's left side) -// _AP_LW2, _AP_LT2 (width and type of left-concat's right side) -// Similarly for RHS of operand OP: _AP_RW1, AP_RW2, _AP_RT1, _AP_RT2 -// -// In Verilog 2001 result of concatenation is always unsigned even -// when both sides are signed. -//************************************************************************ - -#undef SYN_CONCAT_REF_BIN_OP - -#define SYN_CONCAT_REF_BIN_OP(BIN_OP, RTYPE) \ - template \ - INLINE typename ap_int_base<_AP_LW1 + _AP_LW2, false>::template RType< \ - _AP_RW1 + _AP_RW2, false>::RTYPE \ - operator BIN_OP( \ - const ap_concat_ref<_AP_LW1, _AP_LT1, _AP_LW2, _AP_LT2>& lhs, \ - const ap_concat_ref<_AP_RW1, _AP_RT1, _AP_RW2, _AP_RT2>& rhs) { \ - return lhs.get() BIN_OP rhs.get(); \ - } - -SYN_CONCAT_REF_BIN_OP(+, plus) -SYN_CONCAT_REF_BIN_OP(-, minus) -SYN_CONCAT_REF_BIN_OP(*, mult) -SYN_CONCAT_REF_BIN_OP(/, div) -SYN_CONCAT_REF_BIN_OP(%, mod) -SYN_CONCAT_REF_BIN_OP(&, logic) -SYN_CONCAT_REF_BIN_OP(|, logic) -SYN_CONCAT_REF_BIN_OP(^, logic) -SYN_CONCAT_REF_BIN_OP(>>, arg1) -SYN_CONCAT_REF_BIN_OP(<<, arg1) - -#undef SYN_CONCAT_REF_BIN_OP - -#define CONCAT_OP_WITH_INT(C_TYPE, _AP_WI, _AP_SI) \ - template \ - INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \ - const ap_int_base<_AP_W, _AP_S> &op1, C_TYPE op2) { \ - ap_int_base<_AP_WI + _AP_W, false> val(op2); \ - ap_int_base<_AP_WI + _AP_W, false> ret(op1); \ - ret <<= _AP_WI; \ - if (_AP_SI) { \ - val <<= _AP_W; \ - val >>= _AP_W; \ - } \ - ret |= val; \ - return ret; \ - } \ - template \ - INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \ - C_TYPE op1, const ap_int_base<_AP_W, _AP_S> &op2) { \ - ap_int_base<_AP_WI + _AP_W, false> val(op1); \ - ap_int_base<_AP_WI + _AP_W, false> ret(op2); \ - if (_AP_S) { \ - ret <<= _AP_WI; \ - ret >>= _AP_WI; \ - } \ - ret |= val << _AP_W; \ - return ret; \ - } \ - template \ - INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \ - const ap_range_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ - ap_int_base<_AP_WI + _AP_W, false> val(op2); \ - ap_int_base<_AP_WI + _AP_W, false> ret(op1); \ - ret <<= _AP_WI; \ - if (_AP_SI) { \ - val <<= _AP_W; \ - val >>= _AP_W; \ - } \ - ret |= val; \ - return ret; \ - } \ - template \ - INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \ - C_TYPE op1, const ap_range_ref<_AP_W, _AP_S> &op2) { \ - ap_int_base<_AP_WI + _AP_W, false> val(op1); \ - ap_int_base<_AP_WI + _AP_W, false> ret(op2); \ - int len = op2.length(); \ - val <<= len; \ - ret |= val; \ - return ret; \ - } \ - template \ - INLINE ap_int_base<_AP_WI + 1, false> operator,( \ - const ap_bit_ref<_AP_W, _AP_S> &op1, C_TYPE op2) { \ - ap_int_base<_AP_WI + 1, false> val(op2); \ - val[_AP_WI] = op1; \ - return val; \ - } \ - template \ - INLINE ap_int_base<_AP_WI + 1, false> operator,( \ - C_TYPE op1, const ap_bit_ref<_AP_W, _AP_S> &op2) { \ - ap_int_base<_AP_WI + 1, false> val(op1); \ - val <<= 1; \ - val[0] = op2; \ - return val; \ - } \ - template \ - INLINE ap_int_base<_AP_W + _AP_W2 + _AP_WI, false> operator,( \ - const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op1, C_TYPE op2) { \ - ap_int_base<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op2); \ - ap_int_base<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op1); \ - if (_AP_SI) { \ - val <<= _AP_W + _AP_W2; \ - val >>= _AP_W + _AP_W2; \ - } \ - ret <<= _AP_WI; \ - ret |= val; \ - return ret; \ - } \ - template \ - INLINE ap_int_base<_AP_W + _AP_W2 + _AP_WI, false> operator,( \ - C_TYPE op1, const ap_concat_ref<_AP_W, _AP_T, _AP_W2, _AP_T2> &op2) { \ - ap_int_base<_AP_WI + _AP_W + _AP_W2, _AP_SI> val(op1); \ - ap_int_base<_AP_WI + _AP_W + _AP_W2, _AP_SI> ret(op2); \ - int len = op2.length(); \ - val <<= len; \ - ret |= val; \ - return ret; \ - } \ - template \ - INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \ - const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op1, \ - C_TYPE op2) { \ - ap_int_base<_AP_WI + _AP_W, false> val(op2); \ - ap_int_base<_AP_WI + _AP_W, false> ret(op1); \ - if (_AP_SI) { \ - val <<= _AP_W; \ - val >>= _AP_W; \ - } \ - ret <<= _AP_WI; \ - ret |= val; \ - return ret; \ - } \ - template \ - INLINE ap_int_base<_AP_W + _AP_WI, false> operator,( \ - C_TYPE op1, \ - const af_range_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op2) { \ - ap_int_base<_AP_WI + _AP_W, false> val(op1); \ - ap_int_base<_AP_WI + _AP_W, false> ret(op2); \ - int len = op2.length(); \ - val <<= len; \ - ret |= val; \ - return ret; \ - } \ - template \ - INLINE ap_int_base<1 + _AP_WI, false> operator,( \ - const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op1, \ - C_TYPE op2) { \ - ap_int_base<_AP_WI + 1, _AP_SI> val(op2); \ - val[_AP_WI] = op1; \ - return val; \ - } \ - template \ - INLINE ap_int_base<1 + _AP_WI, false> operator,( \ - C_TYPE op1, \ - const af_bit_ref<_AP_W, _AP_I, _AP_S, _AP_Q, _AP_O, _AP_N> &op2) { \ - ap_int_base<_AP_WI + 1, _AP_SI> val(op1); \ - val <<= 1; \ - val[0] = op2; \ - return val; \ - } - -CONCAT_OP_WITH_INT(bool, 1, false) -CONCAT_OP_WITH_INT(char, 8, CHAR_IS_SIGNED) -CONCAT_OP_WITH_INT(signed char, 8, true) -CONCAT_OP_WITH_INT(unsigned char, 8, false) -CONCAT_OP_WITH_INT(short, _AP_SIZE_short, true) -CONCAT_OP_WITH_INT(unsigned short, _AP_SIZE_short, false) -CONCAT_OP_WITH_INT(int, _AP_SIZE_int, true) -CONCAT_OP_WITH_INT(unsigned int, _AP_SIZE_int, false) -CONCAT_OP_WITH_INT(long, _AP_SIZE_long, true) -CONCAT_OP_WITH_INT(unsigned long, _AP_SIZE_long, false) -CONCAT_OP_WITH_INT(ap_slong, _AP_SIZE_ap_slong, true) -CONCAT_OP_WITH_INT(ap_ulong, _AP_SIZE_ap_slong, false) - -#undef CONCAT_OP_WITH_INT - -#define CONCAT_SHIFT_WITH_INT(C_TYPE, OP) \ - template \ - INLINE ap_uint<_AP_W + _AP_W1> operator OP( \ - const ap_concat_ref<_AP_W, _AP_T, _AP_W1, _AP_T1> lhs, C_TYPE rhs) { \ - return ap_uint<_AP_W + _AP_W1>(lhs).get() OP int(rhs); \ - } - -// FIXME int(rhs) may loose precision. - -CONCAT_SHIFT_WITH_INT(int, <<) -CONCAT_SHIFT_WITH_INT(unsigned int, <<) -CONCAT_SHIFT_WITH_INT(long, <<) -CONCAT_SHIFT_WITH_INT(unsigned long, <<) -CONCAT_SHIFT_WITH_INT(ap_slong, <<) -CONCAT_SHIFT_WITH_INT(ap_ulong, <<) - -CONCAT_SHIFT_WITH_INT(int, >>) -CONCAT_SHIFT_WITH_INT(unsigned int, >>) -CONCAT_SHIFT_WITH_INT(long, >>) -CONCAT_SHIFT_WITH_INT(unsigned long, >>) -CONCAT_SHIFT_WITH_INT(ap_slong, >>) -CONCAT_SHIFT_WITH_INT(ap_ulong, >>) - -#endif // ifndef __cplusplus -#endif // ifndef __AP_INT_REF_H__ - -// -*- cpp -*- diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_int_special.h b/model/AE_model/hls4ml_prj/firmware/ap_types/ap_int_special.h deleted file mode 100644 index 3afc619..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_int_special.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2011-2019 Xilinx, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AP_INT_SPECIAL_H__ -#define __AP_INT_SPECIAL_H__ - -#ifndef __AP_INT_H__ -#error "Only ap_fixed.h and ap_int.h can be included directly in user code." -#endif - -#ifndef __SYNTHESIS__ -#include -#include -#endif -// FIXME AP_AUTOCC cannot handle many standard headers, so declare instead of -// include. -// #include -namespace std { -template class complex; -} - -/* - TODO: Modernize the code using C++11/C++14 - 1. constexpr http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0415r0.html - 2. move constructor -*/ - -namespace std { -/* - Specialize std::complex to zero initialization ap_int. - - To reduce the area cost, ap_int is not zero initialized, just like basic - types float or double. However, libstdc++ provides specialization for float, - double and long double, initializing image part to 0 when not specified. - - This has become a difficulty in switching legacy code from these C types to - ap_int. To ease the tranform of legacy code, we have to implement - specialization of std::complex<> for our type. - - As ap_int is a template, it is impossible to specialize only the methods - that causes default initialization of value type in std::complex<>. An - explicit full specialization of the template class has to be done, covering - all the member functions and operators of std::complex<> as specified - in standard 26.2.4 and 26.2.5. -*/ -template -class complex > { - public: - typedef ap_int<_AP_W> _Tp; - typedef _Tp value_type; - - // 26.2.4/1 - // Constructor without argument - // Default initialize, so that in dataflow, the variable is only written once. - complex() : _M_real(_Tp()), _M_imag(_Tp()) {} - // Constructor with ap_int. - // Zero initialize image part when not specified, so that `C(1) == C(1,0)` - complex(const _Tp &__r, const _Tp &__i = _Tp(0)) - : _M_real(__r), _M_imag(__i) {} - - // Constructor with another complex number - template - complex(const complex<_Up> &__z) : _M_real(__z.real()), _M_imag(__z.imag()) {} - -#if __cplusplus >= 201103L - const _Tp& real() const { return _M_real; } - const _Tp& imag() const { return _M_imag; } -#else - _Tp& real() { return _M_real; } - const _Tp& real() const { return _M_real; } - _Tp& imag() { return _M_imag; } - const _Tp& imag() const { return _M_imag; } -#endif - - void real(_Tp __val) { _M_real = __val; } - - void imag(_Tp __val) { _M_imag = __val; } - - // Assign this complex number with ap_int. - // Zero initialize image poarrt, so that `C c; c = 1; c == C(1,0);` - complex<_Tp> &operator=(const _Tp __t) { - _M_real = __t; - _M_imag = _Tp(0); - return *this; - } - - // 26.2.5/1 - // Add ap_int to this complex number. - complex<_Tp> &operator+=(const _Tp &__t) { - _M_real += __t; - return *this; - } - - // 26.2.5/3 - // Subtract ap_int from this complex number. - complex<_Tp> &operator-=(const _Tp &__t) { - _M_real -= __t; - return *this; - } - - // 26.2.5/5 - // Multiply this complex number by ap_int. - complex<_Tp> &operator*=(const _Tp &__t) { - _M_real *= __t; - _M_imag *= __t; - return *this; - } - - // 26.2.5/7 - // Divide this complex number by ap_int. - complex<_Tp> &operator/=(const _Tp &__t) { - _M_real /= __t; - _M_imag /= __t; - return *this; - } - - // Assign complex number to this complex number. - template - complex<_Tp> &operator=(const complex<_Up> &__z) { - _M_real = __z.real(); - _M_imag = __z.imag(); - return *this; - } - - // 26.2.5/9 - // Add complex number to this. - template - complex<_Tp> &operator+=(const complex<_Up> &__z) { - _M_real += __z.real(); - _M_imag += __z.imag(); - return *this; - } - - // 26.2.5/11 - // Subtract complex number from this. - template - complex<_Tp> &operator-=(const complex<_Up> &__z) { - _M_real -= __z.real(); - _M_imag -= __z.imag(); - return *this; - } - - // 26.2.5/13 - // Multiply this by complex number. - template - complex<_Tp> &operator*=(const complex<_Up> &__z) { - const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag(); - _M_imag = _M_real * __z.imag() + _M_imag * __z.real(); - _M_real = __r; - return *this; - } - - // 26.2.5/15 - // Divide this by complex number. - template - complex<_Tp> &operator/=(const complex<_Up> &__z) { - complex<_Tp> cj (__z.real(), -__z.imag()); - complex<_Tp> a = (*this) * cj; - complex<_Tp> b = cj * __z; - _M_real = a.real() / b.real(); - _M_imag = a.imag() / b.real(); - return *this; - } - - private: - _Tp _M_real; - _Tp _M_imag; - -}; // class complex > - - -/* - Non-member operations - These operations are not required by standard in 26.2.6, but libstdc++ - defines them for - float, double or long double's specialization. -*/ -// Compare complex number with ap_int. -template -inline bool operator==(const complex > &__x, const ap_int<_AP_W> &__y) { - return __x.real() == __y && - __x.imag() == 0; -} - -// Compare ap_int with complex number. -template -inline bool operator==(const ap_int<_AP_W> &__x, const complex > &__y) { - return __x == __y.real() && - 0 == __y.imag(); -} - -// Compare complex number with ap_int. -template -inline bool operator!=(const complex > &__x, const ap_int<_AP_W> &__y) { - return __x.real() != __y || - __x.imag() != 0; -} - -// Compare ap_int with complex number. -template -inline bool operator!=(const ap_int<_AP_W> &__x, const complex > &__y) { - return __x != __y.real() || - 0 != __y.imag(); -} - -} // namespace std - -#endif // ifndef __AP_INT_SPECIAL_H__ - -// -*- cpp -*- diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_shift_reg.h b/model/AE_model/hls4ml_prj/firmware/ap_types/ap_shift_reg.h deleted file mode 100644 index 94dba51..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/ap_shift_reg.h +++ /dev/null @@ -1,138 +0,0 @@ -/* -#- (c) Copyright 2011-2019 Xilinx, Inc. All rights reserved. -#- -#- This file contains confidential and proprietary information -#- of Xilinx, Inc. and is protected under U.S. and -#- international copyright and other intellectual property -#- laws. -#- -#- DISCLAIMER -#- This disclaimer is not a license and does not grant any -#- rights to the materials distributed herewith. Except as -#- otherwise provided in a valid license issued to you by -#- Xilinx, and to the maximum extent permitted by applicable -#- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND -#- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES -#- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING -#- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- -#- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and -#- (2) Xilinx shall not be liable (whether in contract or tort, -#- including negligence, or under any other theory of -#- liability) for any loss or damage of any kind or nature -#- related to, arising under or in connection with these -#- materials, including for any direct, or any indirect, -#- special, incidental, or consequential loss or damage -#- (including loss of data, profits, goodwill, or any type of -#- loss or damage suffered as a result of any action brought -#- by a third party) even if such damage or loss was -#- reasonably foreseeable or Xilinx had been advised of the -#- possibility of the same. -#- -#- CRITICAL APPLICATIONS -#- Xilinx products are not designed or intended to be fail- -#- safe, or for use in any application requiring fail-safe -#- performance, such as life-support or safety devices or -#- systems, Class III medical devices, nuclear facilities, -#- applications related to the deployment of airbags, or any -#- other applications that could lead to death, personal -#- injury, or severe property or environmental damage -#- (individually and collectively, "Critical -#- Applications"). Customer assumes the sole risk and -#- liability of any use of Xilinx products in Critical -#- Applications, subject only to applicable laws and -#- regulations governing limitations on product liability. -#- -#- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS -#- PART OF THIS FILE AT ALL TIMES. -#- ************************************************************************ - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#ifndef __SIM_AP_SHIFT_REG_H__ -#define __SIM_AP_SHIFT_REG_H__ - - -/* - * This file contains a C++ model of shift register. - * It defines C level simulation model. - */ -#ifndef __cplusplus -#error C++ is required to include this header file -#else - -#include - -////////////////////////////////////////////// -// C level simulation model for ap_shift_reg -////////////////////////////////////////////// -template -class ap_shift_reg -{ - public: - /// Constructors - ap_shift_reg() { } - ap_shift_reg(const char* name) { } - /// Destructor - virtual ~ap_shift_reg() { } - - private: - /// Make copy constructor and assignment operator private - ap_shift_reg(const ap_shift_reg< __SHIFT_T__, __SHIFT_DEPTH__ >& shreg) - { - for (unsigned i = 0; i < __SHIFT_DEPTH__; ++i) - Array[i] = shreg.Array[i]; - } - - ap_shift_reg& operator = (const ap_shift_reg< __SHIFT_T__, - __SHIFT_DEPTH__ >& shreg) - { - for (unsigned i = 0; i < __SHIFT_DEPTH__; ++i) - Array[i] = shreg.Array[i]; - return *this; - } - - public: - // Shift the queue, push to back and read from a given address. - __SHIFT_T__ shift(__SHIFT_T__ DataIn, - unsigned int Addr = __SHIFT_DEPTH__ - 1, bool Enable = true) - { - assert(Addr < __SHIFT_DEPTH__ && - "Out-of-bound shift is found in ap_shift_reg."); - __SHIFT_T__ ret = Array[Addr]; - if (Enable) { - for (unsigned int i = __SHIFT_DEPTH__ - 1; i > 0; --i) - Array[i] = Array[i-1]; - Array[0] = DataIn; - } - return ret; - } - - // Read from a given address. - __SHIFT_T__ read(unsigned int Addr = __SHIFT_DEPTH__ - 1) const - { - assert(Addr < __SHIFT_DEPTH__ && - "Out-of-bound read is found in ap_shift_reg."); - return Array[Addr]; - } - - protected: - __SHIFT_T__ Array[__SHIFT_DEPTH__]; -}; - -#endif //__cplusplus - -#endif //__SIM_AP_SHIFT_REG_H__ - - diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/etc/ap_private.h b/model/AE_model/hls4ml_prj/firmware/ap_types/etc/ap_private.h deleted file mode 100644 index 0c29a0a..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/etc/ap_private.h +++ /dev/null @@ -1,7199 +0,0 @@ -/* - * Copyright 2011-2019 Xilinx, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AP_PRIVATE_H__ -#define __AP_PRIVATE_H__ - -// common macros and type declarations are now defined in ap_common.h, and -// ap_private becomes part of it. -#ifndef __AP_COMMON_H__ -#error "etc/ap_private.h cannot be included directly." -#endif - -// forward declarations -//template -//class ap_private; // moved to ap_common.h -template -struct _private_range_ref; -template -struct _private_bit_ref; - -// TODO clean up this part. -#ifndef LLVM_SUPPORT_MATHEXTRAS_H -#define LLVM_SUPPORT_MATHEXTRAS_H - -#ifdef _MSC_VER -#if _MSC_VER <= 1500 -typedef __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#else -#include -#endif -#else -#include -#endif - -#ifndef INLINE -#define INLINE inline -// Enable to debug ap_int/ap_fixed -// #define INLINE __attribute__((weak)) -#endif - -// NOTE: The following support functions use the _32/_64 extensions instead of -// type overloading so that signed and unsigned integers can be used without -// ambiguity. -namespace AESL_std { -template -DataType INLINE min(DataType a, DataType b) { - return (a >= b) ? b : a; -} - -template -DataType INLINE max(DataType a, DataType b) { - return (a >= b) ? a : b; -} -} // namespace AESL_std - -// TODO clean up included headers. -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace ap_private_ops { -/// Hi_32 - This function returns the high 32 bits of a 64 bit value. -static INLINE uint32_t Hi_32(uint64_t Value) { - return static_cast(Value >> 32); -} - -/// Lo_32 - This function returns the low 32 bits of a 64 bit value. -static INLINE uint32_t Lo_32(uint64_t Value) { - return static_cast(Value); -} - -template -INLINE bool isNegative(const ap_private<_AP_W, false>& a) { - return false; -} - -template -INLINE bool isNegative(const ap_private<_AP_W, true>& a) { - enum { - APINT_BITS_PER_WORD = 64, - _AP_N = (_AP_W + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD - }; - static const uint64_t sign_mask = 1ULL << ((_AP_W - 1) % APINT_BITS_PER_WORD); - return (sign_mask & a.get_pVal(_AP_N - 1)) != 0; -} - -/// CountLeadingZeros_32 - this function performs the platform optimal form of -/// counting the number of zeros from the most significant bit to the first one -/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8. -/// Returns 32 if the word is zero. -static INLINE unsigned CountLeadingZeros_32(uint32_t Value) { - unsigned Count; // result -#if __GNUC__ >= 4 -// PowerPC is defined for __builtin_clz(0) -#if !defined(__ppc__) && !defined(__ppc64__) - if (Value == 0) return 32; -#endif - Count = __builtin_clz(Value); -#else - if (Value == 0) return 32; - Count = 0; - // bisecton method for count leading zeros - for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) { - uint32_t Tmp = (Value) >> (Shift); - if (Tmp) { - Value = Tmp; - } else { - Count |= Shift; - } - } -#endif - return Count; -} - -/// CountLeadingZeros_64 - This function performs the platform optimal form -/// of counting the number of zeros from the most significant bit to the first -/// one bit (64 bit edition.) -/// Returns 64 if the word is zero. -static INLINE unsigned CountLeadingZeros_64(uint64_t Value) { - unsigned Count; // result -#if __GNUC__ >= 4 -// PowerPC is defined for __builtin_clzll(0) -#if !defined(__ppc__) && !defined(__ppc64__) - if (!Value) return 64; -#endif - Count = __builtin_clzll(Value); -#else - if (sizeof(long) == sizeof(int64_t)) { - if (!Value) return 64; - Count = 0; - // bisecton method for count leading zeros - for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) { - uint64_t Tmp = (Value) >> (Shift); - if (Tmp) { - Value = Tmp; - } else { - Count |= Shift; - } - } - } else { - // get hi portion - uint32_t Hi = Hi_32(Value); - - // if some bits in hi portion - if (Hi) { - // leading zeros in hi portion plus all bits in lo portion - Count = CountLeadingZeros_32(Hi); - } else { - // get lo portion - uint32_t Lo = Lo_32(Value); - // same as 32 bit value - Count = CountLeadingZeros_32(Lo) + 32; - } - } -#endif - return Count; -} - -/// CountTrailingZeros_64 - This function performs the platform optimal form -/// of counting the number of zeros from the least significant bit to the first -/// one bit (64 bit edition.) -/// Returns 64 if the word is zero. -static INLINE unsigned CountTrailingZeros_64(uint64_t Value) { -#if __GNUC__ >= 4 - return (Value != 0) ? __builtin_ctzll(Value) : 64; -#else - static const unsigned Mod67Position[] = { - 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, 4, - 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, 47, 5, 32, - 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, 29, 50, 43, 46, 31, - 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, 7, 48, 35, 6, 34, 33, 0}; - return Mod67Position[(uint64_t)(-(int64_t)Value & (int64_t)Value) % 67]; -#endif -} - -/// CountPopulation_64 - this function counts the number of set bits in a value, -/// (64 bit edition.) -static INLINE unsigned CountPopulation_64(uint64_t Value) { -#if __GNUC__ >= 4 - return __builtin_popcountll(Value); -#else - uint64_t v = Value - (((Value) >> 1) & 0x5555555555555555ULL); - v = (v & 0x3333333333333333ULL) + (((v) >> 2) & 0x3333333333333333ULL); - v = (v + ((v) >> 4)) & 0x0F0F0F0F0F0F0F0FULL; - return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); -#endif -} - -static INLINE uint32_t countLeadingOnes_64(uint64_t __V, uint32_t skip) { - uint32_t Count = 0; - if (skip) (__V) <<= (skip); - while (__V && (__V & (1ULL << 63))) { - Count++; - (__V) <<= 1; - } - return Count; -} - -static INLINE std::string oct2Bin(char oct) { - switch (oct) { - case '\0': { - return ""; - } - case '.': { - return "."; - } - case '0': { - return "000"; - } - case '1': { - return "001"; - } - case '2': { - return "010"; - } - case '3': { - return "011"; - } - case '4': { - return "100"; - } - case '5': { - return "101"; - } - case '6': { - return "110"; - } - case '7': { - return "111"; - } - } - assert(0 && "Invalid character in digit string"); - return ""; -} - -static INLINE std::string hex2Bin(char hex) { - switch (hex) { - case '\0': { - return ""; - } - case '.': { - return "."; - } - case '0': { - return "0000"; - } - case '1': { - return "0001"; - } - case '2': { - return "0010"; - } - case '3': { - return "0011"; - } - case '4': { - return "0100"; - } - case '5': { - return "0101"; - } - case '6': { - return "0110"; - } - case '7': { - return "0111"; - } - case '8': { - return "1000"; - } - case '9': { - return "1001"; - } - case 'A': - case 'a': { - return "1010"; - } - case 'B': - case 'b': { - return "1011"; - } - case 'C': - case 'c': { - return "1100"; - } - case 'D': - case 'd': { - return "1101"; - } - case 'E': - case 'e': { - return "1110"; - } - case 'F': - case 'f': { - return "1111"; - } - } - assert(0 && "Invalid character in digit string"); - return ""; -} - -static INLINE uint32_t decode_digit(char cdigit, int radix) { - uint32_t digit = 0; - if (radix == 16) { -#define isxdigit(c) \ - (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || \ - ((c) >= 'A' && (c) <= 'F')) -#define isdigit(c) ((c) >= '0' && (c) <= '9') - if (!isxdigit(cdigit)) assert(0 && "Invalid hex digit in string"); - if (isdigit(cdigit)) - digit = cdigit - '0'; - else if (cdigit >= 'a') - digit = cdigit - 'a' + 10; - else if (cdigit >= 'A') - digit = cdigit - 'A' + 10; - else - assert(0 && "huh? we shouldn't get here"); - } else if (isdigit(cdigit)) { - digit = cdigit - '0'; - } else { - assert(0 && "Invalid character in digit string"); - } -#undef isxdigit -#undef isdigit - return digit; -} - -// Determine the radix of "val". -static INLINE std::string parseString(const std::string& input, unsigned char& radix) { - size_t len = input.length(); - if (len == 0) { - if (radix == 0) radix = 10; - return input; - } - - size_t startPos = 0; - // Trim whitespace - while (input[startPos] == ' ' && startPos < len) startPos++; - while (input[len - 1] == ' ' && startPos < len) len--; - - std::string val = input.substr(startPos, len - startPos); - // std::cout << "val = " << val << "\n"; - len = val.length(); - startPos = 0; - - // If the length of the string is less than 2, then radix - // is decimal and there is no exponent. - if (len < 2) { - if (radix == 0) radix = 10; - return val; - } - - bool isNegative = false; - std::string ans; - - // First check to see if we start with a sign indicator - if (val[0] == '-') { - ans = "-"; - ++startPos; - isNegative = true; - } else if (val[0] == '+') - ++startPos; - - if (len - startPos < 2) { - if (radix == 0) radix = 10; - return val; - } - - if (val.substr(startPos, 2) == "0x" || val.substr(startPos, 2) == "0X") { - // If we start with "0x", then the radix is hex. - radix = 16; - startPos += 2; - } else if (val.substr(startPos, 2) == "0b" || - val.substr(startPos, 2) == "0B") { - // If we start with "0b", then the radix is binary. - radix = 2; - startPos += 2; - } else if (val.substr(startPos, 2) == "0o" || - val.substr(startPos, 2) == "0O") { - // If we start with "0o", then the radix is octal. - radix = 8; - startPos += 2; - } else if (radix == 0) { - radix = 10; - } - - int exp = 0; - if (radix == 10) { - // If radix is decimal, then see if there is an - // exponent indicator. - size_t expPos = val.find('e'); - bool has_exponent = true; - if (expPos == std::string::npos) expPos = val.find('E'); - if (expPos == std::string::npos) { - // No exponent indicator, so the mantissa goes to the end. - expPos = len; - has_exponent = false; - } - // std::cout << "startPos = " << startPos << " " << expPos << "\n"; - - ans += val.substr(startPos, expPos - startPos); - if (has_exponent) { - // Parse the exponent. - std::istringstream iss(val.substr(expPos + 1, len - expPos - 1)); - iss >> exp; - } - } else { - // Check for a binary exponent indicator. - size_t expPos = val.find('p'); - bool has_exponent = true; - if (expPos == std::string::npos) expPos = val.find('P'); - if (expPos == std::string::npos) { - // No exponent indicator, so the mantissa goes to the end. - expPos = len; - has_exponent = false; - } - - // std::cout << "startPos = " << startPos << " " << expPos << "\n"; - - assert(startPos <= expPos); - // Convert to binary as we go. - for (size_t i = startPos; i < expPos; ++i) { - if (radix == 16) { - ans += hex2Bin(val[i]); - } else if (radix == 8) { - ans += oct2Bin(val[i]); - } else { // radix == 2 - ans += val[i]; - } - } - // End in binary - radix = 2; - if (has_exponent) { - // Parse the exponent. - std::istringstream iss(val.substr(expPos + 1, len - expPos - 1)); - iss >> exp; - } - } - if (exp == 0) return ans; - - size_t decPos = ans.find('.'); - if (decPos == std::string::npos) decPos = ans.length(); - if ((int)decPos + exp >= (int)ans.length()) { - int i = decPos; - for (; i < (int)ans.length() - 1; ++i) ans[i] = ans[i + 1]; - for (; i < (int)ans.length(); ++i) ans[i] = '0'; - for (; i < (int)decPos + exp; ++i) ans += '0'; - return ans; - } else if ((int)decPos + exp < (int)isNegative) { - std::string dupAns = "0."; - if (ans[0] == '-') dupAns = "-0."; - for (int i = 0; i < isNegative - (int)decPos - exp; ++i) dupAns += '0'; - for (size_t i = isNegative; i < ans.length(); ++i) - if (ans[i] != '.') dupAns += ans[i]; - return dupAns; - } - - if (exp > 0) - for (size_t i = decPos; i < decPos + exp; ++i) ans[i] = ans[i + 1]; - else { - if (decPos == ans.length()) ans += ' '; - for (int i = decPos; i > (int)decPos + exp; --i) ans[i] = ans[i - 1]; - } - ans[decPos + exp] = '.'; - return ans; -} - -/// sub_1 - This function subtracts a single "digit" (64-bit word), y, from -/// the multi-digit integer array, x[], propagating the borrowed 1 value until -/// no further borrowing is neeeded or it runs out of "digits" in x. The result -/// is 1 if "borrowing" exhausted the digits in x, or 0 if x was not exhausted. -/// In other words, if y > x then this function returns 1, otherwise 0. -/// @returns the borrow out of the subtraction -static INLINE bool sub_1(uint64_t x[], uint32_t len, uint64_t y) { - for (uint32_t i = 0; i < len; ++i) { - uint64_t __X = x[i]; - x[i] -= y; - if (y > __X) - y = 1; // We have to "borrow 1" from next "digit" - else { - y = 0; // No need to borrow - break; // Remaining digits are unchanged so exit early - } - } - return (y != 0); -} - -/// add_1 - This function adds a single "digit" integer, y, to the multiple -/// "digit" integer array, x[]. x[] is modified to reflect the addition and -/// 1 is returned if there is a carry out, otherwise 0 is returned. -/// @returns the carry of the addition. -static INLINE bool add_1(uint64_t dest[], uint64_t x[], uint32_t len, - uint64_t y) { - for (uint32_t i = 0; i < len; ++i) { - dest[i] = y + x[i]; - if (dest[i] < y) - y = 1; // Carry one to next digit. - else { - y = 0; // No need to carry so exit early - break; - } - } - return (y != 0); -} - -/// add - This function adds the integer array x to the integer array Y and -/// places the result in dest. -/// @returns the carry out from the addition -/// @brief General addition of 64-bit integer arrays -static INLINE bool add(uint64_t* dest, const uint64_t* x, const uint64_t* y, - uint32_t destlen, uint32_t xlen, uint32_t ylen, - bool xsigned, bool ysigned) { - bool carry = false; - uint32_t len = AESL_std::min(xlen, ylen); - uint32_t i; - for (i = 0; i < len && i < destlen; ++i) { - uint64_t limit = - AESL_std::min(x[i], y[i]); // must come first in case dest == x - dest[i] = x[i] + y[i] + carry; - carry = dest[i] < limit || (carry && dest[i] == limit); - } - if (xlen > ylen) { - const uint64_t yext = ysigned && int64_t(y[ylen - 1]) < 0 ? -1 : 0; - for (i = ylen; i < xlen && i < destlen; i++) { - uint64_t limit = AESL_std::min(x[i], yext); - dest[i] = x[i] + yext + carry; - carry = (dest[i] < limit) || (carry && dest[i] == limit); - } - } else if (ylen > xlen) { - const uint64_t xext = xsigned && int64_t(x[xlen - 1]) < 0 ? -1 : 0; - for (i = xlen; i < ylen && i < destlen; i++) { - uint64_t limit = AESL_std::min(xext, y[i]); - dest[i] = xext + y[i] + carry; - carry = (dest[i] < limit) || (carry && dest[i] == limit); - } - } - return carry; -} - -/// @returns returns the borrow out. -/// @brief Generalized subtraction of 64-bit integer arrays. -static INLINE bool sub(uint64_t* dest, const uint64_t* x, const uint64_t* y, - uint32_t destlen, uint32_t xlen, uint32_t ylen, - bool xsigned, bool ysigned) { - bool borrow = false; - uint32_t i; - uint32_t len = AESL_std::min(xlen, ylen); - for (i = 0; i < len && i < destlen; ++i) { - uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; - borrow = y[i] > x_tmp || (borrow && x[i] == 0); - dest[i] = x_tmp - y[i]; - } - if (xlen > ylen) { - const uint64_t yext = ysigned && int64_t(y[ylen - 1]) < 0 ? -1 : 0; - for (i = ylen; i < xlen && i < destlen; i++) { - uint64_t x_tmp = borrow ? x[i] - 1 : x[i]; - borrow = yext > x_tmp || (borrow && x[i] == 0); - dest[i] = x_tmp - yext; - } - } else if (ylen > xlen) { - const uint64_t xext = xsigned && int64_t(x[xlen - 1]) < 0 ? -1 : 0; - for (i = xlen; i < ylen && i < destlen; i++) { - uint64_t x_tmp = borrow ? xext - 1 : xext; - borrow = y[i] > x_tmp || (borrow && xext == 0); - dest[i] = x_tmp - y[i]; - } - } - return borrow; -} - -/// Subtracts the RHS ap_private from this ap_private -/// @returns this, after subtraction -/// @brief Subtraction assignment operator. - -/// Multiplies an integer array, x by a a uint64_t integer and places the result -/// into dest. -/// @returns the carry out of the multiplication. -/// @brief Multiply a multi-digit ap_private by a single digit (64-bit) integer. -static INLINE uint64_t mul_1(uint64_t dest[], const uint64_t x[], uint32_t len, - uint64_t y) { - // Split y into high 32-bit part (hy) and low 32-bit part (ly) - uint64_t ly = y & 0xffffffffULL, hy = (y) >> 32; - uint64_t carry = 0; - static const uint64_t two_power_32 = 1ULL << 32; - // For each digit of x. - for (uint32_t i = 0; i < len; ++i) { - // Split x into high and low words - uint64_t lx = x[i] & 0xffffffffULL; - uint64_t hx = (x[i]) >> 32; - // hasCarry - A flag to indicate if there is a carry to the next digit. - // hasCarry == 0, no carry - // hasCarry == 1, has carry - // hasCarry == 2, no carry and the calculation result == 0. - uint8_t hasCarry = 0; - dest[i] = carry + lx * ly; - // Determine if the add above introduces carry. - hasCarry = (dest[i] < carry) ? 1 : 0; - carry = hx * ly + ((dest[i]) >> 32) + (hasCarry ? two_power_32 : 0); - // The upper limit of carry can be (2^32 - 1)(2^32 - 1) + - // (2^32 - 1) + 2^32 = 2^64. - hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); - - carry += (lx * hy) & 0xffffffffULL; - dest[i] = ((carry) << 32) | (dest[i] & 0xffffffffULL); - carry = (((!carry && hasCarry != 2) || hasCarry == 1) ? two_power_32 : 0) + - ((carry) >> 32) + ((lx * hy) >> 32) + hx * hy; - } - return carry; -} - -/// Multiplies integer array x by integer array y and stores the result into -/// the integer array dest. Note that dest's size must be >= xlen + ylen in -/// order to -/// do a full precision computation. If it is not, then only the low-order words -/// are returned. -/// @brief Generalized multiplicate of integer arrays. -static INLINE void mul(uint64_t dest[], const uint64_t x[], uint32_t xlen, - const uint64_t y[], uint32_t ylen, uint32_t destlen) { - assert(xlen > 0); - assert(ylen > 0); - assert(destlen >= xlen + ylen); - if (xlen < destlen) dest[xlen] = mul_1(dest, x, xlen, y[0]); - for (uint32_t i = 1; i < ylen; ++i) { - uint64_t ly = y[i] & 0xffffffffULL, hy = (y[i]) >> 32; - uint64_t carry = 0, lx = 0, hx = 0; - for (uint32_t j = 0; j < xlen; ++j) { - lx = x[j] & 0xffffffffULL; - hx = (x[j]) >> 32; - // hasCarry - A flag to indicate if has carry. - // hasCarry == 0, no carry - // hasCarry == 1, has carry - // hasCarry == 2, no carry and the calculation result == 0. - uint8_t hasCarry = 0; - uint64_t resul = carry + lx * ly; - hasCarry = (resul < carry) ? 1 : 0; - carry = (hasCarry ? (1ULL << 32) : 0) + hx * ly + ((resul) >> 32); - hasCarry = (!carry && hasCarry) ? 1 : (!carry ? 2 : 0); - carry += (lx * hy) & 0xffffffffULL; - resul = ((carry) << 32) | (resul & 0xffffffffULL); - if (i + j < destlen) dest[i + j] += resul; - carry = - (((!carry && hasCarry != 2) || hasCarry == 1) ? (1ULL << 32) : 0) + - ((carry) >> 32) + (dest[i + j] < resul ? 1 : 0) + ((lx * hy) >> 32) + - hx * hy; - } - if (i + xlen < destlen) dest[i + xlen] = carry; - } -} - -/// Implementation of Knuth's Algorithm D (Division of nonnegative integers) -/// from "Art of Computer Programming, Volume 2", section 4.3.1, p. 272. The -/// variables here have the same names as in the algorithm. Comments explain -/// the algorithm and any deviation from it. -static INLINE void KnuthDiv(uint32_t* u, uint32_t* v, uint32_t* q, uint32_t* r, - uint32_t m, uint32_t n) { - assert(u && "Must provide dividend"); - assert(v && "Must provide divisor"); - assert(q && "Must provide quotient"); - assert(u != v && u != q && v != q && "Must us different memory"); - assert(n > 1 && "n must be > 1"); - - // Knuth uses the value b as the base of the number system. In our case b - // is 2^31 so we just set it to -1u. - uint64_t b = uint64_t(1) << 32; - - // DEBUG(cerr << "KnuthDiv: m=" << m << " n=" << n << '\n'); - // DEBUG(cerr << "KnuthDiv: original:"); - // DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << - // u[i]); - // DEBUG(cerr << " by"); - // DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << - // v[i-1]); - // DEBUG(cerr << '\n'); - // D1. [Normalize.] Set d = b / (v[n-1] + 1) and multiply all the digits of - // u and v by d. Note that we have taken Knuth's advice here to use a power - // of 2 value for d such that d * v[n-1] >= b/2 (b is the base). A power of - // 2 allows us to shift instead of multiply and it is easy to determine the - // shift amount from the leading zeros. We are basically normalizing the u - // and v so that its high bits are shifted to the top of v's range without - // overflow. Note that this can require an extra word in u so that u must - // be of length m+n+1. - uint32_t shift = CountLeadingZeros_32(v[n - 1]); - uint32_t v_carry = 0; - uint32_t u_carry = 0; - if (shift) { - for (uint32_t i = 0; i < m + n; ++i) { - uint32_t u_tmp = (u[i]) >> (32 - shift); - u[i] = ((u[i]) << (shift)) | u_carry; - u_carry = u_tmp; - } - for (uint32_t i = 0; i < n; ++i) { - uint32_t v_tmp = (v[i]) >> (32 - shift); - v[i] = ((v[i]) << (shift)) | v_carry; - v_carry = v_tmp; - } - } - u[m + n] = u_carry; - // DEBUG(cerr << "KnuthDiv: normal:"); - // DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << std::setbase(16) << - // u[i]); - // DEBUG(cerr << " by"); - // DEBUG(for (int i = n; i >0; i--) cerr << " " << std::setbase(16) << - // v[i-1]); - // DEBUG(cerr << '\n'); - - // D2. [Initialize j.] Set j to m. This is the loop counter over the places. - int j = m; - do { - // DEBUG(cerr << "KnuthDiv: quotient digit #" << j << '\n'); - // D3. [Calculate q'.]. - // Set qp = (u[j+n]*b + u[j+n-1]) / v[n-1]. (qp=qprime=q') - // Set rp = (u[j+n]*b + u[j+n-1]) % v[n-1]. (rp=rprime=r') - // Now test if qp == b or qp*v[n-2] > b*rp + u[j+n-2]; if so, decrease - // qp by 1, inrease rp by v[n-1], and repeat this test if rp < b. The test - // on v[n-2] determines at high speed most of the cases in which the trial - // value qp is one too large, and it eliminates all cases where qp is two - // too large. - uint64_t dividend = ((uint64_t(u[j + n]) << 32) + u[j + n - 1]); - // DEBUG(cerr << "KnuthDiv: dividend == " << dividend << '\n'); - uint64_t qp = dividend / v[n - 1]; - uint64_t rp = dividend % v[n - 1]; - if (qp == b || qp * v[n - 2] > b * rp + u[j + n - 2]) { - qp--; - rp += v[n - 1]; - if (rp < b && (qp == b || qp * v[n - 2] > b * rp + u[j + n - 2])) qp--; - } - // DEBUG(cerr << "KnuthDiv: qp == " << qp << ", rp == " << rp << '\n'); - - // D4. [Multiply and subtract.] Replace (u[j+n]u[j+n-1]...u[j]) with - // (u[j+n]u[j+n-1]..u[j]) - qp * (v[n-1]...v[1]v[0]). This computation - // consists of a simple multiplication by a one-place number, combined with - // a subtraction. - bool isNeg = false; - for (uint32_t i = 0; i < n; ++i) { - uint64_t u_tmp = uint64_t(u[j + i]) | ((uint64_t(u[j + i + 1])) << 32); - uint64_t subtrahend = uint64_t(qp) * uint64_t(v[i]); - bool borrow = subtrahend > u_tmp; - /*DEBUG(cerr << "KnuthDiv: u_tmp == " << u_tmp - << ", subtrahend == " << subtrahend - << ", borrow = " << borrow << '\n');*/ - - uint64_t result = u_tmp - subtrahend; - uint32_t k = j + i; - u[k++] = (uint32_t)(result & (b - 1)); // subtract low word - u[k++] = (uint32_t)((result) >> 32); // subtract high word - while (borrow && k <= m + n) { // deal with borrow to the left - borrow = u[k] == 0; - u[k]--; - k++; - } - isNeg |= borrow; - /*DEBUG(cerr << "KnuthDiv: u[j+i] == " << u[j+i] << ", u[j+i+1] == " << - u[j+i+1] << '\n');*/ - } - /*DEBUG(cerr << "KnuthDiv: after subtraction:"); - DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); - DEBUG(cerr << '\n');*/ - // The digits (u[j+n]...u[j]) should be kept positive; if the result of - // this step is actually negative, (u[j+n]...u[j]) should be left as the - // true value plus b**(n+1), namely as the b's complement of - // the true value, and a "borrow" to the left should be remembered. - // - if (isNeg) { - bool carry = true; // true because b's complement is "complement + 1" - for (uint32_t i = 0; i <= m + n; ++i) { - u[i] = ~u[i] + carry; // b's complement - carry = carry && u[i] == 0; - } - } - /*DEBUG(cerr << "KnuthDiv: after complement:"); - DEBUG(for (int i = m+n; i >=0; i--) cerr << " " << u[i]); - DEBUG(cerr << '\n');*/ - - // D5. [Test remainder.] Set q[j] = qp. If the result of step D4 was - // negative, go to step D6; otherwise go on to step D7. - q[j] = (uint32_t)qp; - if (isNeg) { - // D6. [Add back]. The probability that this step is necessary is very - // small, on the order of only 2/b. Make sure that test data accounts for - // this possibility. Decrease q[j] by 1 - q[j]--; - // and add (0v[n-1]...v[1]v[0]) to (u[j+n]u[j+n-1]...u[j+1]u[j]). - // A carry will occur to the left of u[j+n], and it should be ignored - // since it cancels with the borrow that occurred in D4. - bool carry = false; - for (uint32_t i = 0; i < n; i++) { - uint32_t limit = AESL_std::min(u[j + i], v[i]); - u[j + i] += v[i] + carry; - carry = u[j + i] < limit || (carry && u[j + i] == limit); - } - u[j + n] += carry; - } - /*DEBUG(cerr << "KnuthDiv: after correction:"); - DEBUG(for (int i = m+n; i >=0; i--) cerr <<" " << u[i]); - DEBUG(cerr << "\nKnuthDiv: digit result = " << q[j] << '\n');*/ - - // D7. [Loop on j.] Decrease j by one. Now if j >= 0, go back to D3. - } while (--j >= 0); - - /*DEBUG(cerr << "KnuthDiv: quotient:"); - DEBUG(for (int i = m; i >=0; i--) cerr <<" " << q[i]); - DEBUG(cerr << '\n');*/ - - // D8. [Unnormalize]. Now q[...] is the desired quotient, and the desired - // remainder may be obtained by dividing u[...] by d. If r is non-null we - // compute the remainder (urem uses this). - if (r) { - // The value d is expressed by the "shift" value above since we avoided - // multiplication by d by using a shift left. So, all we have to do is - // shift right here. In order to mak - if (shift) { - uint32_t carry = 0; - // DEBUG(cerr << "KnuthDiv: remainder:"); - for (int i = n - 1; i >= 0; i--) { - r[i] = ((u[i]) >> (shift)) | carry; - carry = (u[i]) << (32 - shift); - // DEBUG(cerr << " " << r[i]); - } - } else { - for (int i = n - 1; i >= 0; i--) { - r[i] = u[i]; - // DEBUG(cerr << " " << r[i]); - } - } - // DEBUG(cerr << '\n'); - } - // DEBUG(cerr << std::setbase(10) << '\n'); -} - -template -void divide(const ap_private<_AP_W, _AP_S>& LHS, uint32_t lhsWords, - const ap_private<_AP_W, _AP_S>& RHS, uint32_t rhsWords, - ap_private<_AP_W, _AP_S>* Quotient, - ap_private<_AP_W, _AP_S>* Remainder) { - assert(lhsWords >= rhsWords && "Fractional result"); - enum { APINT_BITS_PER_WORD = 64 }; - // First, compose the values into an array of 32-bit words instead of - // 64-bit words. This is a necessity of both the "short division" algorithm - // and the the Knuth "classical algorithm" which requires there to be native - // operations for +, -, and * on an m bit value with an m*2 bit result. We - // can't use 64-bit operands here because we don't have native results of - // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't - // work on large-endian machines. - uint64_t mask = ~0ull >> (sizeof(uint32_t) * 8); - uint32_t n = rhsWords * 2; - uint32_t m = (lhsWords * 2) - n; - - // Allocate space for the temporary values we need either on the stack, if - // it will fit, or on the heap if it won't. - uint32_t SPACE[128]; - uint32_t* __U = 0; - uint32_t* __V = 0; - uint32_t* __Q = 0; - uint32_t* __R = 0; - if ((Remainder ? 4 : 3) * n + 2 * m + 1 <= 128) { - __U = &SPACE[0]; - __V = &SPACE[m + n + 1]; - __Q = &SPACE[(m + n + 1) + n]; - if (Remainder) __R = &SPACE[(m + n + 1) + n + (m + n)]; - } else { - __U = new uint32_t[m + n + 1]; - __V = new uint32_t[n]; - __Q = new uint32_t[m + n]; - if (Remainder) __R = new uint32_t[n]; - } - - // Initialize the dividend - memset(__U, 0, (m + n + 1) * sizeof(uint32_t)); - for (unsigned i = 0; i < lhsWords; ++i) { - uint64_t tmp = LHS.get_pVal(i); - __U[i * 2] = (uint32_t)(tmp & mask); - __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t) * 8); - } - __U[m + n] = 0; // this extra word is for "spill" in the Knuth algorithm. - - // Initialize the divisor - memset(__V, 0, (n) * sizeof(uint32_t)); - for (unsigned i = 0; i < rhsWords; ++i) { - uint64_t tmp = RHS.get_pVal(i); - __V[i * 2] = (uint32_t)(tmp & mask); - __V[i * 2 + 1] = (tmp) >> (sizeof(uint32_t) * 8); - } - - // initialize the quotient and remainder - memset(__Q, 0, (m + n) * sizeof(uint32_t)); - if (Remainder) memset(__R, 0, n * sizeof(uint32_t)); - - // Now, adjust m and n for the Knuth division. n is the number of words in - // the divisor. m is the number of words by which the dividend exceeds the - // divisor (i.e. m+n is the length of the dividend). These sizes must not - // contain any zero words or the Knuth algorithm fails. - for (unsigned i = n; i > 0 && __V[i - 1] == 0; i--) { - n--; - m++; - } - for (unsigned i = m + n; i > 0 && __U[i - 1] == 0; i--) m--; - - // If we're left with only a single word for the divisor, Knuth doesn't work - // so we implement the short division algorithm here. This is much simpler - // and faster because we are certain that we can divide a 64-bit quantity - // by a 32-bit quantity at hardware speed and short division is simply a - // series of such operations. This is just like doing short division but we - // are using base 2^32 instead of base 10. - assert(n != 0 && "Divide by zero?"); - if (n == 1) { - uint32_t divisor = __V[0]; - uint32_t remainder = 0; - for (int i = m + n - 1; i >= 0; i--) { - uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; - if (partial_dividend == 0) { - __Q[i] = 0; - remainder = 0; - } else if (partial_dividend < divisor) { - __Q[i] = 0; - remainder = (uint32_t)partial_dividend; - } else if (partial_dividend == divisor) { - __Q[i] = 1; - remainder = 0; - } else { - __Q[i] = (uint32_t)(partial_dividend / divisor); - remainder = (uint32_t)(partial_dividend - (__Q[i] * divisor)); - } - } - if (__R) __R[0] = remainder; - } else { - // Now we're ready to invoke the Knuth classical divide algorithm. In this - // case n > 1. - KnuthDiv(__U, __V, __Q, __R, m, n); - } - - // If the caller wants the quotient - if (Quotient) { - // Set up the Quotient value's memory. - if (Quotient->BitWidth != LHS.BitWidth) { - if (Quotient->isSingleWord()) Quotient->set_VAL(0); - } else - Quotient->clear(); - - // The quotient is in Q. Reconstitute the quotient into Quotient's low - // order words. - if (lhsWords == 1) { - uint64_t tmp = - uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); - Quotient->set_VAL(tmp); - } else { - assert(!Quotient->isSingleWord() && - "Quotient ap_private not large enough"); - for (unsigned i = 0; i < lhsWords; ++i) - Quotient->set_pVal( - i, uint64_t(__Q[i * 2]) | - ((uint64_t(__Q[i * 2 + 1])) << (APINT_BITS_PER_WORD / 2))); - } - Quotient->clearUnusedBits(); - } - - // If the caller wants the remainder - if (Remainder) { - // Set up the Remainder value's memory. - if (Remainder->BitWidth != RHS.BitWidth) { - if (Remainder->isSingleWord()) Remainder->set_VAL(0); - } else - Remainder->clear(); - - // The remainder is in R. Reconstitute the remainder into Remainder's low - // order words. - if (rhsWords == 1) { - uint64_t tmp = - uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); - Remainder->set_VAL(tmp); - } else { - assert(!Remainder->isSingleWord() && - "Remainder ap_private not large enough"); - for (unsigned i = 0; i < rhsWords; ++i) - Remainder->set_pVal( - i, uint64_t(__R[i * 2]) | - ((uint64_t(__R[i * 2 + 1])) << (APINT_BITS_PER_WORD / 2))); - } - Remainder->clearUnusedBits(); - } - - // Clean up the memory we allocated. - if (__U != &SPACE[0]) { - delete[] __U; - delete[] __V; - delete[] __Q; - delete[] __R; - } -} - -template -void divide(const ap_private<_AP_W, _AP_S>& LHS, uint32_t lhsWords, - uint64_t RHS, ap_private<_AP_W, _AP_S>* Quotient, - ap_private<_AP_W, _AP_S>* Remainder) { - uint32_t rhsWords = 1; - assert(lhsWords >= rhsWords && "Fractional result"); - enum { APINT_BITS_PER_WORD = 64 }; - // First, compose the values into an array of 32-bit words instead of - // 64-bit words. This is a necessity of both the "short division" algorithm - // and the the Knuth "classical algorithm" which requires there to be native - // operations for +, -, and * on an m bit value with an m*2 bit result. We - // can't use 64-bit operands here because we don't have native results of - // 128-bits. Furthremore, casting the 64-bit values to 32-bit values won't - // work on large-endian machines. - uint64_t mask = ~0ull >> (sizeof(uint32_t) * 8); - uint32_t n = 2; - uint32_t m = (lhsWords * 2) - n; - - // Allocate space for the temporary values we need either on the stack, if - // it will fit, or on the heap if it won't. - uint32_t SPACE[128]; - uint32_t* __U = 0; - uint32_t* __V = 0; - uint32_t* __Q = 0; - uint32_t* __R = 0; - if ((Remainder ? 4 : 3) * n + 2 * m + 1 <= 128) { - __U = &SPACE[0]; - __V = &SPACE[m + n + 1]; - __Q = &SPACE[(m + n + 1) + n]; - if (Remainder) __R = &SPACE[(m + n + 1) + n + (m + n)]; - } else { - __U = new uint32_t[m + n + 1]; - __V = new uint32_t[n]; - __Q = new uint32_t[m + n]; - if (Remainder) __R = new uint32_t[n]; - } - - // Initialize the dividend - memset(__U, 0, (m + n + 1) * sizeof(uint32_t)); - for (unsigned i = 0; i < lhsWords; ++i) { - uint64_t tmp = LHS.get_pVal(i); - __U[i * 2] = tmp & mask; - __U[i * 2 + 1] = (tmp) >> (sizeof(uint32_t) * 8); - } - __U[m + n] = 0; // this extra word is for "spill" in the Knuth algorithm. - - // Initialize the divisor - memset(__V, 0, (n) * sizeof(uint32_t)); - __V[0] = RHS & mask; - __V[1] = (RHS) >> (sizeof(uint32_t) * 8); - - // initialize the quotient and remainder - memset(__Q, 0, (m + n) * sizeof(uint32_t)); - if (Remainder) memset(__R, 0, n * sizeof(uint32_t)); - - // Now, adjust m and n for the Knuth division. n is the number of words in - // the divisor. m is the number of words by which the dividend exceeds the - // divisor (i.e. m+n is the length of the dividend). These sizes must not - // contain any zero words or the Knuth algorithm fails. - for (unsigned i = n; i > 0 && __V[i - 1] == 0; i--) { - n--; - m++; - } - for (unsigned i = m + n; i > 0 && __U[i - 1] == 0; i--) m--; - - // If we're left with only a single word for the divisor, Knuth doesn't work - // so we implement the short division algorithm here. This is much simpler - // and faster because we are certain that we can divide a 64-bit quantity - // by a 32-bit quantity at hardware speed and short division is simply a - // series of such operations. This is just like doing short division but we - // are using base 2^32 instead of base 10. - assert(n != 0 && "Divide by zero?"); - if (n == 1) { - uint32_t divisor = __V[0]; - uint32_t remainder = 0; - for (int i = m + n - 1; i >= 0; i--) { - uint64_t partial_dividend = (uint64_t(remainder)) << 32 | __U[i]; - if (partial_dividend == 0) { - __Q[i] = 0; - remainder = 0; - } else if (partial_dividend < divisor) { - __Q[i] = 0; - remainder = partial_dividend; - } else if (partial_dividend == divisor) { - __Q[i] = 1; - remainder = 0; - } else { - __Q[i] = partial_dividend / divisor; - remainder = partial_dividend - (__Q[i] * divisor); - } - } - if (__R) __R[0] = remainder; - } else { - // Now we're ready to invoke the Knuth classical divide algorithm. In this - // case n > 1. - KnuthDiv(__U, __V, __Q, __R, m, n); - } - - // If the caller wants the quotient - if (Quotient) { - // Set up the Quotient value's memory. - if (Quotient->BitWidth != LHS.BitWidth) { - if (Quotient->isSingleWord()) Quotient->set_VAL(0); - } else - Quotient->clear(); - - // The quotient is in Q. Reconstitute the quotient into Quotient's low - // order words. - if (lhsWords == 1) { - uint64_t tmp = - uint64_t(__Q[0]) | ((uint64_t(__Q[1])) << (APINT_BITS_PER_WORD / 2)); - Quotient->set_VAL(tmp); - } else { - assert(!Quotient->isSingleWord() && - "Quotient ap_private not large enough"); - for (unsigned i = 0; i < lhsWords; ++i) - Quotient->set_pVal( - i, uint64_t(__Q[i * 2]) | - ((uint64_t(__Q[i * 2 + 1])) << (APINT_BITS_PER_WORD / 2))); - } - Quotient->clearUnusedBits(); - } - - // If the caller wants the remainder - if (Remainder) { - // Set up the Remainder value's memory. - if (Remainder->BitWidth != 64 /* RHS.BitWidth */) { - if (Remainder->isSingleWord()) Remainder->set_VAL(0); - } else - Remainder->clear(); - - // The remainder is in __R. Reconstitute the remainder into Remainder's low - // order words. - if (rhsWords == 1) { - uint64_t tmp = - uint64_t(__R[0]) | ((uint64_t(__R[1])) << (APINT_BITS_PER_WORD / 2)); - Remainder->set_VAL(tmp); - } else { - assert(!Remainder->isSingleWord() && - "Remainder ap_private not large enough"); - for (unsigned i = 0; i < rhsWords; ++i) - Remainder->set_pVal( - i, uint64_t(__R[i * 2]) | - ((uint64_t(__R[i * 2 + 1])) << (APINT_BITS_PER_WORD / 2))); - } - Remainder->clearUnusedBits(); - } - - // Clean up the memory we allocated. - if (__U != &SPACE[0]) { - delete[] __U; - delete[] __V; - delete[] __Q; - delete[] __R; - } -} - -/// @brief Logical right-shift function. -template -INLINE ap_private<_AP_W, _AP_S, _AP_C> lshr( - const ap_private<_AP_W, _AP_S, _AP_C>& LHS, uint32_t shiftAmt) { - return LHS.lshr(shiftAmt); -} - -/// Left-shift the ap_private by shiftAmt. -/// @brief Left-shift function. -template -INLINE ap_private<_AP_W, _AP_S, _AP_C> shl( - const ap_private<_AP_W, _AP_S, _AP_C>& LHS, uint32_t shiftAmt) { - return LHS.shl(shiftAmt); -} - -} // namespace ap_private_ops - -#endif // LLVM_SUPPORT_MATHEXTRAS_H - -/// This enumeration just provides for internal constants used in this -/// translation unit. -enum { - MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified - ///< Note that this must remain synchronized with IntegerType::MIN_INT_BITS - MAX_INT_BITS = (1 << 23) - 1 ///< Maximum number of bits that can be specified - ///< Note that this must remain synchronized with IntegerType::MAX_INT_BITS -}; - -//===----------------------------------------------------------------------===// -// ap_private Class -//===----------------------------------------------------------------------===// - -/// ap_private - This class represents arbitrary precision constant integral -/// values. -/// It is a functional replacement for common case unsigned integer type like -/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width -/// integer sizes and large integer value types such as 3-bits, 15-bits, or more -/// than 64-bits of precision. ap_private provides a variety of arithmetic -/// operators -/// and methods to manipulate integer values of any bit-width. It supports both -/// the typical integer arithmetic and comparison operations as well as bitwise -/// manipulation. -/// -/// The class has several invariants worth noting: -/// * All bit, byte, and word positions are zero-based. -/// * Once the bit width is set, it doesn't change except by the Truncate, -/// SignExtend, or ZeroExtend operations. -/// * All binary operators must be on ap_private instances of the same bit -/// width. -/// Attempting to use these operators on instances with different bit -/// widths will yield an assertion. -/// * The value is stored canonically as an unsigned value. For operations -/// where it makes a difference, there are both signed and unsigned variants -/// of the operation. For example, sdiv and udiv. However, because the bit -/// widths must be the same, operations such as Mul and Add produce the same -/// results regardless of whether the values are interpreted as signed or -/// not. -/// * In general, the class tries to follow the style of computation that LLVM -/// uses in its IR. This simplifies its use for LLVM. -/// -/// @brief Class for arbitrary precision integers. - -#if defined(_MSC_VER) -#if _MSC_VER < 1400 && !defined(for) -#define for if (0); else for -#endif -typedef unsigned __int64 ap_ulong; -typedef signed __int64 ap_slong; -#else -typedef unsigned long long ap_ulong; -typedef signed long long ap_slong; -#endif -template -struct valtype; - -template -struct valtype<_AP_N8, false> { - typedef uint64_t Type; -}; - -template -struct valtype<_AP_N8, true> { - typedef int64_t Type; -}; - -template <> -struct valtype<1, false> { - typedef unsigned char Type; -}; -template <> -struct valtype<2, false> { - typedef unsigned short Type; -}; -template <> -struct valtype<3, false> { - typedef unsigned int Type; -}; -template <> -struct valtype<4, false> { - typedef unsigned int Type; -}; -template <> -struct valtype<1, true> { - typedef signed char Type; -}; -template <> -struct valtype<2, true> { - typedef short Type; -}; -template <> -struct valtype<3, true> { - typedef int Type; -}; -template <> -struct valtype<4, true> { - typedef int Type; -}; - -template -struct ap_private_enable_if {}; -template <> -struct ap_private_enable_if { - static const bool isValid = true; -}; - -// When bitwidth < 64 -template -class ap_private<_AP_W, _AP_S, true> { - // SFINAE pattern. Only consider this class when _AP_W <= 64 - const static bool valid = ap_private_enable_if<_AP_W <= 64>::isValid; - -#ifdef _MSC_VER -#pragma warning(disable : 4521 4522) -#endif - public: - typedef typename valtype<(_AP_W + 7) / 8, _AP_S>::Type ValType; - typedef ap_private<_AP_W, _AP_S> Type; - template - struct RType { - enum { - mult_w = _AP_W + _AP_W2, - mult_s = _AP_S || _AP_S2, - plus_w = - AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1, - plus_s = _AP_S || _AP_S2, - minus_w = - AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1, - minus_s = true, - div_w = _AP_W + _AP_S2, - div_s = _AP_S || _AP_S2, - mod_w = AP_MIN(_AP_W, _AP_W2 + (!_AP_S2 && _AP_S)), - mod_s = _AP_S, - logic_w = AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)), - logic_s = _AP_S || _AP_S2 - }; - typedef ap_private mult; - typedef ap_private plus; - typedef ap_private minus; - typedef ap_private logic; - typedef ap_private div; - typedef ap_private mod; - typedef ap_private<_AP_W, _AP_S> arg1; - typedef bool reduce; - }; - enum { APINT_BITS_PER_WORD = sizeof(uint64_t) * 8 }; - enum { - excess_bits = (_AP_W % APINT_BITS_PER_WORD) - ? APINT_BITS_PER_WORD - (_AP_W % APINT_BITS_PER_WORD) - : 0 - }; - static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); - static const uint64_t not_mask = ~mask; - static const uint64_t sign_bit_mask = 1ULL << (APINT_BITS_PER_WORD - 1); - template - struct sign_ext_mask { - static const uint64_t mask = ~0ULL << _AP_W1; - }; - static const int width = _AP_W; - - enum { - BitWidth = _AP_W, - _AP_N = 1, - }; - ValType VAL; ///< Used to store the <= 64 bits integer value. -#ifdef AP_CANARY - ValType CANARY; - void check_canary() { assert(CANARY == (ValType)0xDEADBEEFDEADBEEF); } - void set_canary() { CANARY = (ValType)0xDEADBEEFDEADBEEF; } -#else - void check_canary() {} - void set_canary() {} -#endif - - INLINE ValType& get_VAL(void) { return VAL; } - INLINE ValType get_VAL(void) const { return VAL; } - INLINE ValType get_VAL(void) const volatile { return VAL; } - INLINE void set_VAL(uint64_t value) { VAL = (ValType)value; } - INLINE ValType& get_pVal(int i) { return VAL; } - INLINE ValType get_pVal(int i) const { return VAL; } - INLINE const uint64_t* get_pVal() const { - assert(0 && "invalid usage"); - return 0; - } - INLINE ValType get_pVal(int i) const volatile { return VAL; } - INLINE uint64_t* get_pVal() const volatile { - assert(0 && "invalid usage"); - return 0; - } - INLINE void set_pVal(int i, uint64_t value) { VAL = (ValType)value; } - - INLINE uint32_t getBitWidth() const { return BitWidth; } - - template - ap_private<_AP_W, _AP_S>& operator=(const ap_private<_AP_W1, _AP_S1>& RHS) { - VAL = (ValType)(RHS.get_VAL()); - clearUnusedBits(); - return *this; - } - - template - ap_private<_AP_W, _AP_S>& operator=( - const volatile ap_private<_AP_W1, _AP_S1>& RHS) { - VAL = (ValType)(RHS.get_VAL()); // TODO check here about ap_private - clearUnusedBits(); - return *this; - } - - void operator=(const ap_private& RHS) volatile { - // Don't do anything for X = X - VAL = RHS.get_VAL(); // No need to check because no harm done by copying. - clearUnusedBits(); - } - - ap_private& operator=(const ap_private& RHS) { - // Don't do anything for X = X - VAL = RHS.get_VAL(); // No need to check because no harm done by copying. - clearUnusedBits(); - return *this; - } - - void operator=(const volatile ap_private& RHS) volatile { - // Don't do anything for X = X - VAL = RHS.get_VAL(); // No need to check because no harm done by copying. - clearUnusedBits(); - } - - ap_private& operator=(const volatile ap_private& RHS) { - // Don't do anything for X = X - VAL = RHS.get_VAL(); // No need to check because no harm done by copying. - clearUnusedBits(); - return *this; - } - - template - INLINE ap_private& operator=(const _private_range_ref<_AP_W2, _AP_S2>& op2) { - *this = ap_private<_AP_W2, false>(op2); - return *this; - } - -#define ASSIGN_OP_FROM_INT(C_TYPE) \ - INLINE ap_private& operator=(const C_TYPE v) { \ - set_canary(); \ - this->VAL = (ValType)v; \ - clearUnusedBits(); \ - check_canary(); \ - return *this; \ - } - -ASSIGN_OP_FROM_INT(bool) -ASSIGN_OP_FROM_INT(char) -ASSIGN_OP_FROM_INT(signed char) -ASSIGN_OP_FROM_INT(unsigned char) -ASSIGN_OP_FROM_INT(short) -ASSIGN_OP_FROM_INT(unsigned short) -ASSIGN_OP_FROM_INT(int) -ASSIGN_OP_FROM_INT(unsigned int) -ASSIGN_OP_FROM_INT(long) -ASSIGN_OP_FROM_INT(unsigned long) -ASSIGN_OP_FROM_INT(ap_slong) -ASSIGN_OP_FROM_INT(ap_ulong) -#if 0 -ASSIGN_OP_FROM_INT(half) -ASSIGN_OP_FROM_INT(float) -ASSIGN_OP_FROM_INT(double) -#endif -#undef ASSIGN_OP_FROM_INT - - // XXX This is a must to prevent pointer being converted to bool. - INLINE ap_private& operator=(const char* s) { - ap_private tmp(s); // XXX direct-initialization, as ctor is explicit. - operator=(tmp); - return *this; - } - - private: - explicit INLINE ap_private(uint64_t* val) : VAL(val[0]) { - set_canary(); - clearUnusedBits(); - check_canary(); - } - - INLINE bool isSingleWord() const { return true; } - - public: - INLINE void fromString(const char* strStart, uint32_t slen, uint8_t radix) { - bool isNeg = strStart[0] == '-'; - if (isNeg) { - strStart++; - slen--; - } - - if (strStart[0] == '0' && (strStart[1] == 'b' || strStart[1] == 'B')) { - //if(radix == 0) radix = 2; - _AP_WARNING(radix != 2, "%s seems to have base %d, but %d given.", strStart, 2, radix); - strStart += 2; - slen -=2; - } else if (strStart[0] == '0' && (strStart[1] == 'o' || strStart[1] == 'O')) { - //if (radix == 0) radix = 8; - _AP_WARNING(radix != 8, "%s seems to have base %d, but %d given.", strStart, 8, radix); - strStart += 2; - slen -=2; - } else if (strStart[0] == '0' && (strStart[1] == 'x' || strStart[1] == 'X')) { - //if (radix == 0) radix = 16; - _AP_WARNING(radix != 16, "%s seems to have base %d, but %d given.", strStart, 16, radix); - strStart += 2; - slen -=2; - } else if (strStart[0] == '0' && (strStart[1] == 'd' || strStart[1] == 'D')) { - //if (radix == 0) radix = 10; - _AP_WARNING(radix != 10, "%s seems to have base %d, but %d given.", strStart, 10, radix); - strStart += 2; - slen -=2; - } else if (radix == 0) { - //radix = 2; // XXX default value - } - - // Check our assumptions here - assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && - "Radix should be 2, 8, 10, or 16!"); - assert(strStart && "String is null?"); - - // Clear bits. - uint64_t tmpVAL = VAL = 0; - - switch (radix) { - case 2: - // sscanf(strStart,"%b",&VAL); - // tmpVAL = *strStart =='1' ? ~0ULL : 0; - for (; *strStart; ++strStart) { - assert((*strStart == '0' || *strStart == '1') && - ("Wrong binary number")); - tmpVAL <<= 1; - tmpVAL |= (*strStart - '0'); - } - break; - case 8: -#ifdef _MSC_VER - sscanf_s(strStart, "%llo", &tmpVAL, slen + 1); -#else -#if defined(__x86_64__) && !defined(__MINGW32__) && !defined(__WIN32__) - sscanf(strStart, "%lo", &tmpVAL); -#else - sscanf(strStart, "%llo", &tmpVAL); -#endif //__x86_64__ -#endif //_MSC_VER - break; - case 10: -#ifdef _MSC_VER - sscanf_s(strStart, "%llu", &tmpVAL, slen + 1); -#else -#if defined(__x86_64__) && !defined(__MINGW32__) && !defined(__WIN32__) - sscanf(strStart, "%lu", &tmpVAL); -#else - sscanf(strStart, "%llu", &tmpVAL); -#endif //__x86_64__ -#endif //_MSC_VER - break; - case 16: -#ifdef _MSC_VER - sscanf_s(strStart, "%llx", &tmpVAL, slen + 1); -#else -#if defined(__x86_64__) && !defined(__MINGW32__) && !defined(__WIN32__) - sscanf(strStart, "%lx", &tmpVAL); -#else - sscanf(strStart, "%llx", &tmpVAL); -#endif //__x86_64__ -#endif //_MSC_VER - break; - default: - assert(true && "Unknown radix"); - // error - } - VAL = isNeg ? (ValType)(-tmpVAL) : (ValType)(tmpVAL); - - clearUnusedBits(); - } - - private: - INLINE ap_private(const std::string& val, uint8_t radix = 2) : VAL(0) { - assert(!val.empty() && "String empty?"); - set_canary(); - fromString(val.c_str(), val.size(), radix); - check_canary(); - } - - INLINE ap_private(const char strStart[], uint32_t slen, uint8_t radix) - : VAL(0) { - set_canary(); - fromString(strStart, slen, radix); - check_canary(); - } - - INLINE ap_private(uint32_t numWords, const uint64_t bigVal[]) - : VAL(bigVal[0]) { - set_canary(); - clearUnusedBits(); - check_canary(); - } - - public: - INLINE ap_private() { - set_canary(); - clearUnusedBits(); - check_canary(); - } - -#define CTOR(TYPE) \ - INLINE ap_private(TYPE v) : VAL((ValType)v) { \ - set_canary(); \ - clearUnusedBits(); \ - check_canary(); \ - } - CTOR(bool) - CTOR(char) - CTOR(signed char) - CTOR(unsigned char) - CTOR(short) - CTOR(unsigned short) - CTOR(int) - CTOR(unsigned int) - CTOR(long) - CTOR(unsigned long) - CTOR(ap_slong) - CTOR(ap_ulong) -#if 0 - CTOR(half) - CTOR(float) - CTOR(double) -#endif -#undef CTOR - - template - INLINE ap_private(const ap_private<_AP_W1, _AP_S1, _AP_OPT>& that) - : VAL((ValType)that.get_VAL()) { - set_canary(); - clearUnusedBits(); - check_canary(); - } - - template - INLINE ap_private(const volatile ap_private<_AP_W1, _AP_S1, _AP_OPT>& that) - : VAL((ValType)that.get_VAL()) { - set_canary(); - clearUnusedBits(); - check_canary(); - } - - explicit INLINE ap_private(const char* val) { - set_canary(); - unsigned char radix = 10; - std::string str = ap_private_ops::parseString(val, radix); // will set radix. - std::string::size_type pos = str.find('.'); - // trunc all fraction part - if (pos != std::string::npos) str = str.substr(pos); - - ap_private<_AP_W, _AP_S> ap_private_val(str, radix); - operator=(ap_private_val); - check_canary(); - } - - INLINE ap_private(const char* val, signed char rd) { - set_canary(); - unsigned char radix = rd; - std::string str = ap_private_ops::parseString(val, radix); // will set radix. - std::string::size_type pos = str.find('.'); - // trunc all fraction part - if (pos != std::string::npos) str = str.substr(pos); - - ap_private<_AP_W, _AP_S> ap_private_val(str, radix); - operator=(ap_private_val); - check_canary(); - } - - INLINE ~ap_private() { check_canary(); } - - INLINE bool isNegative() const { - static const uint64_t sign_mask = 1ULL << (_AP_W - 1); - return _AP_S && (sign_mask & VAL); - } - - INLINE bool isPositive() const { return !isNegative(); } - - INLINE bool isStrictlyPositive() const { return !isNegative() && VAL != 0; } - - INLINE bool isAllOnesValue() const { return (mask & VAL) == mask; } - - INLINE bool operator==(const ap_private<_AP_W, _AP_S>& RHS) const { - return VAL == RHS.get_VAL(); - } - INLINE bool operator==(const ap_private<_AP_W, !_AP_S>& RHS) const { - return (uint64_t)VAL == (uint64_t)RHS.get_VAL(); - } - - INLINE bool operator==(uint64_t Val) const { return ((uint64_t)VAL == Val); } - INLINE bool operator!=(uint64_t Val) const { return ((uint64_t)VAL != Val); } - INLINE bool operator!=(const ap_private<_AP_W, _AP_S>& RHS) const { - return VAL != RHS.get_VAL(); - } - INLINE bool operator!=(const ap_private<_AP_W, !_AP_S>& RHS) const { - return (uint64_t)VAL != (uint64_t)RHS.get_VAL(); - } - - /// postfix increment. - const ap_private operator++(int) { - ap_private orig(*this); - VAL++; - clearUnusedBits(); - return orig; - } - - /// prefix increment. - const ap_private operator++() { - ++VAL; - clearUnusedBits(); - return *this; - } - - /// postfix decrement. - const ap_private operator--(int) { - ap_private orig(*this); - --VAL; - clearUnusedBits(); - return orig; - } - - /// prefix decrement. - const ap_private operator--() { - --VAL; - clearUnusedBits(); - return *this; - } - - /// one's complement. - INLINE ap_private<_AP_W + !_AP_S, true> operator~() const { - ap_private<_AP_W + !_AP_S, true> Result(*this); - Result.flip(); - return Result; - } - - /// two's complement. - INLINE typename RType<1, false>::minus operator-() const { - return ap_private<1, false>(0) - (*this); - } - - /// logic negation. - INLINE bool operator!() const { return !VAL; } - - INLINE std::string toString(uint8_t radix, bool wantSigned) const; - INLINE std::string toStringUnsigned(uint8_t radix = 10) const { - return toString(radix, false); - } - INLINE std::string toStringSigned(uint8_t radix = 10) const { - return toString(radix, true); - } - INLINE void clear() { VAL = 0; } - INLINE ap_private& clear(uint32_t bitPosition) { - VAL &= ~(1ULL << (bitPosition)); - clearUnusedBits(); - return *this; - } - - INLINE ap_private ashr(uint32_t shiftAmt) const { - if (_AP_S) - return ap_private((shiftAmt == BitWidth) ? 0 - : ((int64_t)VAL) >> (shiftAmt)); - else - return ap_private((shiftAmt == BitWidth) ? 0 - : ((uint64_t)VAL) >> (shiftAmt)); - } - - INLINE ap_private lshr(uint32_t shiftAmt) const { - return ap_private((shiftAmt == BitWidth) - ? ap_private(0) - : ap_private((VAL & mask) >> (shiftAmt))); - } - - INLINE ap_private shl(uint32_t shiftAmt) const -// just for clang compiler -#if defined(__clang__) && !defined(__CLANG_3_1__) - __attribute__((no_sanitize("undefined"))) -#endif - { - if (shiftAmt > BitWidth) { - if (!isNegative()) - return ap_private(0); - else - return ap_private(-1); - } - if (shiftAmt == BitWidth) - return ap_private(0); - else - return ap_private((VAL) << (shiftAmt)); - // return ap_private((shiftAmt == BitWidth) ? ap_private(0ULL) : - // ap_private(VAL << shiftAmt)); - } - - INLINE int64_t getSExtValue() const { return VAL; } - - // XXX XXX this function is used in CBE - INLINE uint64_t getZExtValue() const { return VAL & mask; } - - template - INLINE ap_private(const _private_range_ref<_AP_W2, _AP_S2>& ref) { - set_canary(); - *this = ref.get(); - check_canary(); - } - - template - INLINE ap_private(const _private_bit_ref<_AP_W2, _AP_S2>& ref) { - set_canary(); - *this = ((uint64_t)(bool)ref); - check_canary(); - } - -// template -// INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref) { -// set_canary(); -// *this = ref.get(); -// check_canary(); -// } -// -// template -// INLINE ap_private( -// const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { -// set_canary(); -// *this = ((val.operator ap_private<_AP_W2, false>())); -// check_canary(); -// } -// -// template -// INLINE ap_private( -// const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { -// set_canary(); -// *this = (uint64_t)(bool)val; -// check_canary(); -// } - - INLINE void write(const ap_private<_AP_W, _AP_S>& op2) volatile { - *this = (op2); - } - - // Explicit conversions to C interger types - //----------------------------------------------------------- - INLINE operator ValType() const { return get_VAL(); } - - INLINE int to_uchar() const { return (unsigned char)get_VAL(); } - - INLINE int to_char() const { return (signed char)get_VAL(); } - - INLINE int to_ushort() const { return (unsigned short)get_VAL(); } - - INLINE int to_short() const { return (short)get_VAL(); } - - INLINE int to_int() const { - // ap_private<64 /* _AP_W */, _AP_S> res(V); - return (int)get_VAL(); - } - - INLINE unsigned to_uint() const { return (unsigned)get_VAL(); } - - INLINE long to_long() const { return (long)get_VAL(); } - - INLINE unsigned long to_ulong() const { return (unsigned long)get_VAL(); } - - INLINE ap_slong to_int64() const { return (ap_slong)get_VAL(); } - - INLINE ap_ulong to_uint64() const { return (ap_ulong)get_VAL(); } - - INLINE double to_double() const { - if (isNegative()) - return roundToDouble(true); - else - return roundToDouble(false); - } - - INLINE unsigned length() const { return _AP_W; } - - INLINE bool isMinValue() const { return VAL == 0; } - template - INLINE ap_private& operator&=(const ap_private<_AP_W1, _AP_S1>& RHS) { - VAL = (ValType)(((uint64_t)VAL) & RHS.get_VAL()); - clearUnusedBits(); - return *this; - } - - template - INLINE ap_private& operator|=(const ap_private<_AP_W1, _AP_S1>& RHS) { - VAL = (ValType)(((uint64_t)VAL) | RHS.get_VAL()); - clearUnusedBits(); - return *this; - } - - template - INLINE ap_private& operator^=(const ap_private<_AP_W1, _AP_S1>& RHS) { - VAL = (ValType)(((uint64_t)VAL) ^ RHS.get_VAL()); - clearUnusedBits(); - return *this; - } - - template - INLINE ap_private& operator*=(const ap_private<_AP_W1, _AP_S1>& RHS) { - VAL = (ValType)(((uint64_t)VAL) * RHS.get_VAL()); - clearUnusedBits(); - return *this; - } - - template - INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1>& RHS) { - VAL = (ValType)(((uint64_t)VAL) + RHS.get_VAL()); - clearUnusedBits(); - return *this; - } - - template - INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1>& RHS) { - VAL = (ValType)(((uint64_t)VAL) - RHS.get_VAL()); - clearUnusedBits(); - return *this; - } - - template - INLINE typename RType<_AP_W1, _AP_S1>::logic operator&( - const ap_private<_AP_W1, _AP_S1>& RHS) const { - if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { - typename RType<_AP_W1, _AP_S1>::logic Ret(((uint64_t)VAL) & - RHS.get_VAL()); - return Ret; - } else { - typename RType<_AP_W1, _AP_S1>::logic Ret = *this; - return Ret & RHS; - } - } - - template - INLINE typename RType<_AP_W1, _AP_S1>::logic operator^( - const ap_private<_AP_W1, _AP_S1>& RHS) const { - if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { - typename RType<_AP_W1, _AP_S1>::logic Ret(((uint64_t)VAL) ^ - RHS.get_VAL()); - return Ret; - } else { - typename RType<_AP_W1, _AP_S1>::logic Ret = *this; - return Ret ^ RHS; - } - } - - template - INLINE typename RType<_AP_W1, _AP_S1>::logic operator|( - const ap_private<_AP_W1, _AP_S1>& RHS) const { - if (RType<_AP_W1, _AP_S1>::logic_w <= 64) { - typename RType<_AP_W1, _AP_S1>::logic Ret(((uint64_t)VAL) | - RHS.get_VAL()); - return Ret; - } else { - typename RType<_AP_W1, _AP_S1>::logic Ret = *this; - return Ret | RHS; - } - } - - INLINE ap_private And(const ap_private& RHS) const { - return ap_private(VAL & RHS.get_VAL()); - } - - INLINE ap_private Or(const ap_private& RHS) const { - return ap_private(VAL | RHS.get_VAL()); - } - - INLINE ap_private Xor(const ap_private& RHS) const { - return ap_private(VAL ^ RHS.get_VAL()); - } -#if 1 - template - INLINE typename RType<_AP_W1, _AP_S1>::mult operator*( - const ap_private<_AP_W1, _AP_S1>& RHS) const { - if (RType<_AP_W1, _AP_S1>::mult_w <= 64) { - typename RType<_AP_W1, _AP_S1>::mult Result(((uint64_t)VAL) * - RHS.get_VAL()); - return Result; - } else { - typename RType<_AP_W1, _AP_S1>::mult Result(*this); - Result *= RHS; - return Result; - } - } -#endif - INLINE ap_private Mul(const ap_private& RHS) const { - return ap_private(VAL * RHS.get_VAL()); - } - - INLINE ap_private Add(const ap_private& RHS) const { - return ap_private(VAL + RHS.get_VAL()); - } - - INLINE ap_private Sub(const ap_private& RHS) const { - return ap_private(VAL - RHS.get_VAL()); - } - - INLINE ap_private& operator&=(uint64_t RHS) { - VAL &= (ValType)RHS; - clearUnusedBits(); - return *this; - } - INLINE ap_private& operator|=(uint64_t RHS) { - VAL |= (ValType)RHS; - clearUnusedBits(); - return *this; - } - INLINE ap_private& operator^=(uint64_t RHS) { - VAL ^= (ValType)RHS; - clearUnusedBits(); - return *this; - } - INLINE ap_private& operator*=(uint64_t RHS) { - VAL *= (ValType)RHS; - clearUnusedBits(); - return *this; - } - INLINE ap_private& operator+=(uint64_t RHS) { - VAL += (ValType)RHS; - clearUnusedBits(); - return *this; - } - INLINE ap_private& operator-=(uint64_t RHS) { - VAL -= (ValType)RHS; - clearUnusedBits(); - return *this; - } - - INLINE bool isMinSignedValue() const { - static const uint64_t min_mask = ~(~0ULL << (_AP_W - 1)); - return BitWidth == 1 ? VAL == 1 - : (ap_private_ops::isNegative<_AP_W>(*this) && - ((min_mask & VAL) == 0)); - } - - template - INLINE typename RType<_AP_W1, _AP_S1>::plus operator+( - const ap_private<_AP_W1, _AP_S1>& RHS) const { - if (RType<_AP_W1, _AP_S1>::plus_w <= 64) - return typename RType<_AP_W1, _AP_S1>::plus( - RType<_AP_W1, _AP_S1>::plus_s - ? int64_t(((uint64_t)VAL) + RHS.get_VAL()) - : uint64_t(((uint64_t)VAL) + RHS.get_VAL())); - typename RType<_AP_W1, _AP_S1>::plus Result = RHS; - Result += VAL; - return Result; - } - - template - INLINE typename RType<_AP_W1, _AP_S1>::minus operator-( - const ap_private<_AP_W1, _AP_S1>& RHS) const { - if (RType<_AP_W1, _AP_S1>::minus_w <= 64) - return typename RType<_AP_W1, _AP_S1>::minus( - int64_t(((uint64_t)VAL) - RHS.get_VAL())); - typename RType<_AP_W1, _AP_S1>::minus Result = *this; - Result -= RHS; - return Result; - } - - INLINE uint32_t countPopulation() const { - return ap_private_ops::CountPopulation_64(VAL); - } - INLINE uint32_t countLeadingZeros() const { - int remainder = BitWidth % 64; - int excessBits = (64 - remainder) % 64; - uint32_t Count = ap_private_ops::CountLeadingZeros_64(VAL); - if (Count) Count -= excessBits; - return AESL_std::min(Count, (uint32_t)_AP_W); - } - - /// HiBits - This function returns the high "numBits" bits of this ap_private. - INLINE ap_private<_AP_W, _AP_S> getHiBits(uint32_t numBits) const { - ap_private<_AP_W, _AP_S> ret(*this); - ret = (ret) >> (BitWidth - numBits); - return ret; - } - - /// LoBits - This function returns the low "numBits" bits of this ap_private. - INLINE ap_private<_AP_W, _AP_S> getLoBits(uint32_t numBits) const { - ap_private<_AP_W, _AP_S> ret(((uint64_t)VAL) << (BitWidth - numBits)); - ret = (ret) >> (BitWidth - numBits); - return ret; - // return ap_private(numBits, (VAL << (BitWidth - numBits))>> (BitWidth - - // numBits)); - } - - INLINE ap_private<_AP_W, _AP_S>& set(uint32_t bitPosition) { - VAL |= (1ULL << (bitPosition)); - clearUnusedBits(); - return *this; // clearUnusedBits(); - } - - INLINE void set() { - VAL = (ValType)~0ULL; - clearUnusedBits(); - } - - template - INLINE void set(const ap_private<_AP_W3, false>& val) { - operator=(ap_private<_AP_W3, _AP_S>(val)); - } - - INLINE void set(const ap_private& val) { operator=(val); } - - INLINE void clearUnusedBits(void) volatile -// just for clang compiler -#if defined(__clang__) && !defined(__CLANG_3_1__) - __attribute__((no_sanitize("undefined"))) -#endif - { - enum { excess_bits = (_AP_W % 64) ? 64 - _AP_W % 64 : 0 }; - VAL = (ValType)( - _AP_S - ? ((((int64_t)VAL) << (excess_bits)) >> (excess_bits)) - : (excess_bits ? (((uint64_t)VAL) << (excess_bits)) >> (excess_bits) - : (uint64_t)VAL)); - } - - INLINE void clearUnusedBitsToZero(void) { - enum { excess_bits = (_AP_W % 64) ? 64 - _AP_W % 64 : 0 }; - static uint64_t mask = ~0ULL >> (excess_bits); - VAL &= mask; - } - - INLINE ap_private udiv(const ap_private& RHS) const { - return ap_private((uint64_t)VAL / RHS.get_VAL()); - } - - /// Signed divide this ap_private by ap_private RHS. - /// @brief Signed division function for ap_private. - INLINE ap_private sdiv(const ap_private& RHS) const { - if (isNegative()) - if (RHS.isNegative()) - return ((uint64_t)(0 - (*this))) / (uint64_t)(0 - RHS); - else - return 0 - ((uint64_t)(0 - (*this)) / (uint64_t)(RHS)); - else if (RHS.isNegative()) - return 0 - (this->udiv((ap_private)(0 - RHS))); - return this->udiv(RHS); - } - - template - INLINE ap_private urem(const ap_private<_AP_W, _AP_S2>& RHS) const { - assert(RHS.get_VAL() != 0 && "Divide by 0"); - return ap_private(((uint64_t)VAL) % ((uint64_t)RHS.get_VAL())); - } - - /// Signed remainder operation on ap_private. - /// @brief Function for signed remainder operation. - template - INLINE ap_private srem(const ap_private<_AP_W, _AP_S2>& RHS) const { - if (isNegative()) { - ap_private lhs = 0 - (*this); - if (RHS.isNegative()) { - ap_private rhs = 0 - RHS; - return 0 - (lhs.urem(rhs)); - } else - return 0 - (lhs.urem(RHS)); - } else if (RHS.isNegative()) { - ap_private rhs = 0 - RHS; - return this->urem(rhs); - } - return this->urem(RHS); - } - - template - INLINE bool eq(const ap_private<_AP_W1, _AP_S1>& RHS) const { - return (*this) == RHS; - } - - template - INLINE bool ne(const ap_private<_AP_W1, _AP_S1>& RHS) const { - return !((*this) == RHS); - } - - /// Regards both *this and RHS as unsigned quantities and compares them for - /// the validity of the less-than relationship. - /// @returns true if *this < RHS when both are considered unsigned. - /// @brief Unsigned less than comparison - template - INLINE bool ult(const ap_private<_AP_W1, _AP_S1>& RHS) const { - if (_AP_W1 <= 64) { - uint64_t lhsZext = ((uint64_t(VAL)) << (64 - _AP_W)) >> (64 - _AP_W); - uint64_t rhsZext = - ((uint64_t(RHS.get_VAL())) << (64 - _AP_W1)) >> (64 - _AP_W1); - return lhsZext < rhsZext; - } else - return RHS.uge(*this); - } - - /// Regards both *this and RHS as signed quantities and compares them for - /// validity of the less-than relationship. - /// @returns true if *this < RHS when both are considered signed. - /// @brief Signed less than comparison - template - INLINE bool slt(const ap_private<_AP_W1, _AP_S1>& RHS) const -// just for clang compiler -#if defined(__clang__) && !defined(__CLANG_3_1__) - __attribute__((no_sanitize("undefined"))) -#endif - { - if (_AP_W1 <= 64) { - int64_t lhsSext = ((int64_t(VAL)) << (64 - _AP_W)) >> (64 - _AP_W); - int64_t rhsSext = - ((int64_t(RHS.get_VAL())) << (64 - _AP_W1)) >> (64 - _AP_W1); - return lhsSext < rhsSext; - } else - return RHS.sge(*this); - } - - /// Regards both *this and RHS as unsigned quantities and compares them for - /// validity of the less-or-equal relationship. - /// @returns true if *this <= RHS when both are considered unsigned. - /// @brief Unsigned less or equal comparison - template - INLINE bool ule(const ap_private<_AP_W1, _AP_S1>& RHS) const { - return ult(RHS) || eq(RHS); - } - - /// Regards both *this and RHS as signed quantities and compares them for - /// validity of the less-or-equal relationship. - /// @returns true if *this <= RHS when both are considered signed. - /// @brief Signed less or equal comparison - template - INLINE bool sle(const ap_private<_AP_W1, _AP_S1>& RHS) const { - return slt(RHS) || eq(RHS); - } - - /// Regards both *this and RHS as unsigned quantities and compares them for - /// the validity of the greater-than relationship. - /// @returns true if *this > RHS when both are considered unsigned. - /// @brief Unsigned greather than comparison - template - INLINE bool ugt(const ap_private<_AP_W1, _AP_S1>& RHS) const { - return !ult(RHS) && !eq(RHS); - } - - /// Regards both *this and RHS as signed quantities and compares them for - /// the validity of the greater-than relationship. - /// @returns true if *this > RHS when both are considered signed. - /// @brief Signed greather than comparison - template - INLINE bool sgt(const ap_private<_AP_W1, _AP_S1>& RHS) const { - return !slt(RHS) && !eq(RHS); - } - - /// Regards both *this and RHS as unsigned quantities and compares them for - /// validity of the greater-or-equal relationship. - /// @returns true if *this >= RHS when both are considered unsigned. - /// @brief Unsigned greater or equal comparison - template - INLINE bool uge(const ap_private<_AP_W1, _AP_S1>& RHS) const { - return !ult(RHS); - } - - /// Regards both *this and RHS as signed quantities and compares them for - /// validity of the greater-or-equal relationship. - /// @returns true if *this >= RHS when both are considered signed. - /// @brief Signed greather or equal comparison - template - INLINE bool sge(const ap_private<_AP_W1, _AP_S1>& RHS) const { - return !slt(RHS); - } - - INLINE ap_private abs() const { - if (isNegative()) return -(*this); - return *this; - } - - INLINE ap_private<_AP_W, false> get() const { - ap_private<_AP_W, false> ret(*this); - return ret; - } - - INLINE static uint32_t getBitsNeeded(const char* str, uint32_t slen, - uint8_t radix) { - return _AP_W; - } - - INLINE uint32_t getActiveBits() const { - uint32_t bits = _AP_W - countLeadingZeros(); - return bits ? bits : 1; - } - - INLINE double roundToDouble(bool isSigned = false) const { - return isSigned ? double((int64_t)VAL) : double((uint64_t)VAL); - } - - /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise - * versa*/ - INLINE ap_private& reverse() { - for (int i = 0; i < _AP_W / 2; ++i) { - bool tmp = operator[](i); - if (operator[](_AP_W - 1 - i)) - set(i); - else - clear(i); - if (tmp) - set(_AP_W - 1 - i); - else - clear(_AP_W - 1 - i); - } - clearUnusedBits(); - return *this; - } - - /*Return true if the value of ap_private instance is zero*/ - INLINE bool iszero() const { return isMinValue(); } - - INLINE bool to_bool() const { return !iszero(); } - - /* x < 0 */ - INLINE bool sign() const { - if (isNegative()) return true; - return false; - } - - /* x[i] = !x[i] */ - INLINE void invert(int i) { - assert(i >= 0 && "Attempting to read bit with negative index"); - assert(i < _AP_W && "Attempting to read bit beyond MSB"); - flip(i); - } - - /* x[i] */ - INLINE bool test(int i) const { - assert(i >= 0 && "Attempting to read bit with negative index"); - assert(i < _AP_W && "Attempting to read bit beyond MSB"); - return operator[](i); - } - - // This is used for sc_lv and sc_bv, which is implemented by sc_uint - // Rotate an ap_private object n places to the left - INLINE void lrotate(int n) { - assert(n >= 0 && "Attempting to shift negative index"); - assert(n < _AP_W && "Shift value larger than bit width"); - operator=(shl(n) | lshr(_AP_W - n)); - } - - // This is used for sc_lv and sc_bv, which is implemented by sc_uint - // Rotate an ap_private object n places to the right - INLINE void rrotate(int n) { - assert(n >= 0 && "Attempting to shift negative index"); - assert(n < _AP_W && "Shift value larger than bit width"); - operator=(lshr(n) | shl(_AP_W - n)); - } - - // Set the ith bit into v - INLINE void set(int i, bool v) { - assert(i >= 0 && "Attempting to write bit with negative index"); - assert(i < _AP_W && "Attempting to write bit beyond MSB"); - v ? set(i) : clear(i); - } - - // Set the ith bit into v - INLINE void set_bit(int i, bool v) { - assert(i >= 0 && "Attempting to write bit with negative index"); - assert(i < _AP_W && "Attempting to write bit beyond MSB"); - v ? set(i) : clear(i); - } - - // Get the value of ith bit - INLINE bool get_bit(int i) const { - assert(i >= 0 && "Attempting to read bit with negative index"); - assert(i < _AP_W && "Attempting to read bit beyond MSB"); - return (((1ULL << i) & VAL) != 0); - } - - /// Toggle all bits. - INLINE ap_private& flip() { - VAL = (ValType)((~0ULL ^ VAL) & mask); - clearUnusedBits(); - return *this; - } - - /// Toggles a given bit to its opposite value. - INLINE ap_private& flip(uint32_t bitPosition) { - assert(bitPosition < BitWidth && "Out of the bit-width range!"); - set_bit(bitPosition, !get_bit(bitPosition)); - return *this; - } - - // complements every bit - INLINE void b_not() { flip(); } - -// Binary Arithmetic -//----------------------------------------------------------- -#define OP_BIN_AP(Sym, Rty, Fun) \ - template \ - INLINE typename RType<_AP_W2, _AP_S2>::Rty operator Sym( \ - const ap_private<_AP_W2, _AP_S2>& op) const { \ - typename RType<_AP_W2, _AP_S2>::Rty lhs(*this); \ - typename RType<_AP_W2, _AP_S2>::Rty rhs(op); \ - return lhs.Fun(rhs); \ - } - -/// Bitwise and, or, xor -// OP_BIN_AP(&,logic, And) -// OP_BIN_AP(|,logic, Or) -// OP_BIN_AP(^,logic, Xor) -#undef OP_BIN_AP - - template - INLINE typename RType<_AP_W2, _AP_S2>::div operator/( - const ap_private<_AP_W2, _AP_S2>& op) const { - ap_private _AP_W2 ? _AP_S - : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))> - lhs = *this; - ap_private _AP_W2 ? _AP_S - : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))> - rhs = op; - return typename RType<_AP_W2, _AP_S2>::div( - (_AP_S || _AP_S2) ? lhs.sdiv(rhs) : lhs.udiv(rhs)); - } - - template - INLINE typename RType<_AP_W2, _AP_S2>::mod operator%( - const ap_private<_AP_W2, _AP_S2>& op) const { - ap_private _AP_W2 ? _AP_S - : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))> - lhs = *this; - ap_private _AP_W2 ? _AP_S - : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))> - rhs = op; - typename RType<_AP_W2, _AP_S2>::mod res = - typename RType<_AP_W2, _AP_S2>::mod(_AP_S ? lhs.srem(rhs) - : lhs.urem(rhs)); - return res; - } - -#define OP_ASSIGN_AP_2(Sym) \ - template \ - INLINE ap_private<_AP_W, _AP_S>& operator Sym##=( \ - const ap_private<_AP_W2, _AP_S2>& op) { \ - *this = operator Sym(op); \ - return *this; \ - } - - OP_ASSIGN_AP_2(/) - OP_ASSIGN_AP_2(%) -#undef OP_ASSIGN_AP_2 - -/// Bitwise assign: and, or, xor -//------------------------------------------------------------- -// OP_ASSIGN_AP(&) -// OP_ASSIGN_AP(^) -// OP_ASSIGN_AP(|) - -#define OP_LEFT_SHIFT_CTYPE(TYPE, SIGNED) \ - INLINE ap_private operator<<(const TYPE op) const { \ - if (op >= _AP_W) return ap_private(0); \ - if (SIGNED && op < 0) return *this >> (0 - op); \ - return shl(op); \ - } - - // OP_LEFT_SHIFT_CTYPE(bool, false) - OP_LEFT_SHIFT_CTYPE(char, CHAR_IS_SIGNED) - OP_LEFT_SHIFT_CTYPE(signed char, true) - OP_LEFT_SHIFT_CTYPE(unsigned char, false) - OP_LEFT_SHIFT_CTYPE(short, true) - OP_LEFT_SHIFT_CTYPE(unsigned short, false) - OP_LEFT_SHIFT_CTYPE(int, true) - OP_LEFT_SHIFT_CTYPE(unsigned int, false) - OP_LEFT_SHIFT_CTYPE(long, true) - OP_LEFT_SHIFT_CTYPE(unsigned long, false) - OP_LEFT_SHIFT_CTYPE(long long, true) - OP_LEFT_SHIFT_CTYPE(unsigned long long, false) -#if 0 - OP_LEFT_SHIFT_CTYPE(half, false) - OP_LEFT_SHIFT_CTYPE(float, false) - OP_LEFT_SHIFT_CTYPE(double, false) -#endif - -#undef OP_LEFT_SHIFT_CTYPE - - template - INLINE ap_private operator<<(const ap_private<_AP_W2, _AP_S2>& op2) const { - if (_AP_S2 == false) { - uint32_t sh = op2.to_uint(); - return *this << sh; - } else { - int sh = op2.to_int(); - return *this << sh; - } - } - -#define OP_RIGHT_SHIFT_CTYPE(TYPE, SIGNED) \ - INLINE ap_private operator>>(const TYPE op) const { \ - if (op >= _AP_W) { \ - if (isNegative()) \ - return ap_private(-1); \ - else \ - return ap_private(0); \ - } \ - if ((SIGNED) && op < 0) return *this << (0 - op); \ - if (_AP_S) \ - return ashr(op); \ - else \ - return lshr(op); \ - } - - // OP_RIGHT_SHIFT_CTYPE(bool, false) - OP_RIGHT_SHIFT_CTYPE(char, CHAR_IS_SIGNED) - OP_RIGHT_SHIFT_CTYPE(signed char, true) - OP_RIGHT_SHIFT_CTYPE(unsigned char, false) - OP_RIGHT_SHIFT_CTYPE(short, true) - OP_RIGHT_SHIFT_CTYPE(unsigned short, false) - OP_RIGHT_SHIFT_CTYPE(int, true) - OP_RIGHT_SHIFT_CTYPE(unsigned int, false) - OP_RIGHT_SHIFT_CTYPE(long, true) - OP_RIGHT_SHIFT_CTYPE(unsigned long, false) - OP_RIGHT_SHIFT_CTYPE(unsigned long long, false) - OP_RIGHT_SHIFT_CTYPE(long long, true) -#if 0 - OP_RIGHT_SHIFT_CTYPE(half, false) - OP_RIGHT_SHIFT_CTYPE(float, false) - OP_RIGHT_SHIFT_CTYPE(double, false) -#endif - -#undef OP_RIGHT_SHIFT_CTYPE - - template - INLINE ap_private operator>>(const ap_private<_AP_W2, _AP_S2>& op2) const { - if (_AP_S2 == false) { - uint32_t sh = op2.to_uint(); - return *this >> sh; - } else { - int sh = op2.to_int(); - return *this >> sh; - } - } - - /// Shift assign - //----------------------------------------------------------------- - - //INLINE const ap_private& operator<<=(uint32_t shiftAmt) { - // VAL <<= shiftAmt; - // clearUnusedBits(); - // return *this; - //} - -#define OP_ASSIGN_AP(Sym) \ - template \ - INLINE ap_private& operator Sym##=(int op) { \ - *this = operator Sym(op); \ - clearUnusedBits(); \ - return *this; \ - } \ - INLINE ap_private& operator Sym##=(unsigned int op) { \ - *this = operator Sym(op); \ - clearUnusedBits(); \ - return *this; \ - } \ - template \ - INLINE ap_private& operator Sym##=(const ap_private<_AP_W2, _AP_S2>& op) { \ - *this = operator Sym(op); \ - clearUnusedBits(); \ - return *this; \ - } - - OP_ASSIGN_AP(>>) - OP_ASSIGN_AP(<<) -#undef OP_ASSIGN_AP - - /// Comparisons - //----------------------------------------------------------------- - template - INLINE bool operator==(const ap_private<_AP_W1, _AP_S1>& op) const { - enum { _AP_MAX_W = AP_MAX(AP_MAX(_AP_W, _AP_W1), 32) }; - ap_private<_AP_MAX_W, false> lhs(*this); - ap_private<_AP_MAX_W, false> rhs(op); - if (_AP_MAX_W <= 64) { - return (uint64_t)lhs.get_VAL() == (uint64_t)rhs.get_VAL(); - } else - return lhs == rhs; - } - - template - INLINE bool operator!=(const ap_private<_AP_W2, _AP_S2>& op) const { - return !(*this == op); - } - - template - INLINE bool operator>(const ap_private<_AP_W2, _AP_S2>& op) const { - enum { - _AP_MAX_W = AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2)) - }; - ap_private<_AP_MAX_W, _AP_S> lhs(*this); - ap_private<_AP_MAX_W, _AP_S2> rhs(op); - // this will follow gcc rule for comparison - // between different bitwidth and signness - if (_AP_S == _AP_S2) - return _AP_S ? lhs.sgt(rhs) : lhs.ugt(rhs); - else if (_AP_W < 32 && _AP_W2 < 32) - // different signness but both bitwidth is less than 32 - return lhs.sgt(rhs); - else - // different signness but bigger bitwidth - // is greater or equal to 32 - if (_AP_S) - if (_AP_W2 >= _AP_W) - return lhs.ugt(rhs); - else - return lhs.sgt(rhs); - else if (_AP_W >= _AP_W2) - return lhs.ugt(rhs); - else - return lhs.sgt(rhs); - } - - template - INLINE bool operator<=(const ap_private<_AP_W2, _AP_S2>& op) const { - return !(*this > op); - } - - template - INLINE bool operator<(const ap_private<_AP_W2, _AP_S2>& op) const { - enum { - _AP_MAX_W = AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2)) - }; - ap_private<_AP_MAX_W, _AP_S> lhs(*this); - ap_private<_AP_MAX_W, _AP_S2> rhs(op); - if (_AP_S == _AP_S2) - return _AP_S ? lhs.slt(rhs) : lhs.ult(rhs); - else if (_AP_W < 32 && _AP_W2 < 32) - return lhs.slt(rhs); - else if (_AP_S) - if (_AP_W2 >= _AP_W) - return lhs.ult(rhs); - else - return lhs.slt(rhs); - else if (_AP_W >= _AP_W2) - return lhs.ult(rhs); - else - return lhs.slt(rhs); - } - - template - INLINE bool operator>=(const ap_private<_AP_W2, _AP_S2>& op) const { - return !(*this < op); - } - - /// Bit and Part Select - //-------------------------------------------------------------- - // FIXME now _private_range_ref refs to _AP_ROOT_TYPE(struct ssdm_int). - INLINE _private_range_ref<_AP_W, _AP_S> operator()(int Hi, int Lo) { - return _private_range_ref<_AP_W, _AP_S>(this, Hi, Lo); - } - - INLINE _private_range_ref<_AP_W, _AP_S> operator()(int Hi, int Lo) const { - return _private_range_ref<_AP_W, _AP_S>( - const_cast*>(this), Hi, Lo); - } - - INLINE _private_range_ref<_AP_W, _AP_S> range(int Hi, int Lo) const { - return _private_range_ref<_AP_W, _AP_S>( - (const_cast*>(this)), Hi, Lo); - } - - INLINE _private_range_ref<_AP_W, _AP_S> range(int Hi, int Lo) { - return _private_range_ref<_AP_W, _AP_S>(this, Hi, Lo); - } - - INLINE _private_bit_ref<_AP_W, _AP_S> operator[](int index) { - return _private_bit_ref<_AP_W, _AP_S>(*this, index); - } - - template - INLINE _private_bit_ref<_AP_W, _AP_S> operator[]( - const ap_private<_AP_W2, _AP_S2>& index) { - return _private_bit_ref<_AP_W, _AP_S>(*this, index.to_int()); - } - - INLINE const _private_bit_ref<_AP_W, _AP_S> operator[](int index) const { - return _private_bit_ref<_AP_W, _AP_S>( - const_cast&>(*this), index); - } - - template - INLINE const _private_bit_ref<_AP_W, _AP_S> operator[]( - const ap_private<_AP_W2, _AP_S2>& index) const { - return _private_bit_ref<_AP_W, _AP_S>( - const_cast&>(*this), index.to_int()); - } - - INLINE _private_bit_ref<_AP_W, _AP_S> bit(int index) { - return _private_bit_ref<_AP_W, _AP_S>(*this, index); - } - - template - INLINE _private_bit_ref<_AP_W, _AP_S> bit(const ap_private<_AP_W2, _AP_S2>& index) { - return _private_bit_ref<_AP_W, _AP_S>(*this, index.to_int()); - } - - INLINE const _private_bit_ref<_AP_W, _AP_S> bit(int index) const { - return _private_bit_ref<_AP_W, _AP_S>( - const_cast&>(*this), index); - } - - template - INLINE const _private_bit_ref<_AP_W, _AP_S> bit( - const ap_private<_AP_W2, _AP_S2>& index) const { - return _private_bit_ref<_AP_W, _AP_S>( - const_cast&>(*this), index.to_int()); - } - -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// ap_private<_AP_W2, _AP_S2> > -// concat(const ap_private<_AP_W2, _AP_S2>& a2) const { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >( -// const_cast&>(*this), -// const_cast&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// ap_private<_AP_W2, _AP_S2> > -// concat(ap_private<_AP_W2, _AP_S2>& a2) { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >(*this, a2); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > -// operator,(const ap_private<_AP_W2, _AP_S2> &a2) const { -// return ap_concat_ref<_AP_W, ap_private, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >( -// const_cast&>(*this), -// const_cast&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > -// operator,(const ap_private<_AP_W2, _AP_S2> &a2) { -// return ap_concat_ref<_AP_W, ap_private, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >( -// *this, const_cast&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > -// operator,(ap_private<_AP_W2, _AP_S2> &a2) const { -// return ap_concat_ref<_AP_W, ap_private, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >( -// const_cast&>(*this), a2); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > -// operator,(ap_private<_AP_W2, _AP_S2> &a2) { -// return ap_concat_ref<_AP_W, ap_private, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >(*this, a2); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// _private_range_ref<_AP_W2, _AP_S2> > -// operator,(const _private_range_ref<_AP_W2, _AP_S2> &a2) const { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// _private_range_ref<_AP_W2, _AP_S2> >( -// const_cast&>(*this), -// const_cast<_private_range_ref<_AP_W2, _AP_S2>&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// _private_range_ref<_AP_W2, _AP_S2> > -// operator,(_private_range_ref<_AP_W2, _AP_S2> &a2) { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// _private_range_ref<_AP_W2, _AP_S2> >(*this, a2); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, -// _private_bit_ref<_AP_W2, _AP_S2> > -// operator,(const _private_bit_ref<_AP_W2, _AP_S2> &a2) const { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, -// _private_bit_ref<_AP_W2, _AP_S2> >( -// const_cast&>(*this), -// const_cast<_private_bit_ref<_AP_W2, _AP_S2>&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, -// _private_bit_ref<_AP_W2, _AP_S2> > -// operator,(_private_bit_ref<_AP_W2, _AP_S2> &a2) { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, -// _private_bit_ref<_AP_W2, _AP_S2> >(*this, a2); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3, -// ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > -// operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3, -// ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >( -// const_cast&>(*this), -// const_cast&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3, -// ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > -// operator,(ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3, -// ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, -// a2); -// } -// -// template -// INLINE ap_concat_ref< -// _AP_W, ap_private, _AP_W2, -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > -// operator,(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> -// &a2) const { -// return ap_concat_ref< -// _AP_W, ap_private, _AP_W2, -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( -// const_cast&>(*this), -// const_cast< -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>&>(a2)); -// } -// -// template -// INLINE ap_concat_ref< -// _AP_W, ap_private, _AP_W2, -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > -// operator,(af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) { -// return ap_concat_ref< -// _AP_W, ap_private, _AP_W2, -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, -// a2); -// } -// -// template -// INLINE -// ap_concat_ref<_AP_W, ap_private, 1, -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > -// operator,(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> -// &a2) const { -// return ap_concat_ref< -// _AP_W, ap_private, 1, -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( -// const_cast&>(*this), -// const_cast&>( -// a2)); -// } -// -// template -// INLINE -// ap_concat_ref<_AP_W, ap_private, 1, -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > -// operator,( -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) { -// return ap_concat_ref< -// _AP_W, ap_private, 1, -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); -// } -// -// template -// INLINE ap_private operator&( -// const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { -// return *this & a2.get(); -// } -// -// template -// INLINE ap_private operator|( -// const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { -// return *this | a2.get(); -// } -// -// template -// INLINE ap_private operator^( -// const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { -// return *this ^ a2.get(); -// } - - // Reduce operation - //----------------------------------------------------------- - INLINE bool and_reduce() const { return (VAL & mask) == mask; } - - INLINE bool nand_reduce() const { return (VAL & mask) != mask; } - - INLINE bool or_reduce() const { return (bool)VAL; } - - INLINE bool nor_reduce() const { return VAL == 0; } - - INLINE bool xor_reduce() const { - unsigned int i = countPopulation(); - return (i % 2) ? true : false; - } - - INLINE bool xnor_reduce() const { - unsigned int i = countPopulation(); - return (i % 2) ? false : true; - } - - INLINE std::string to_string(uint8_t radix = 2, bool sign = false) const { - return toString(radix, radix == 10 ? _AP_S : sign); - } -}; // End of class ap_private <_AP_W, _AP_S, true> - -template -std::string ap_private<_AP_W, _AP_S, true>::toString(uint8_t radix, - bool wantSigned) const { - assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && - "Radix should be 2, 8, 10, or 16!"); - static const char* digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", - "8", "9", "a", "b", "c", "d", "e", "f"}; - std::string result; - if (radix != 10) { - // For the 2, 8 and 16 bit cases, we can just shift instead of divide - // because the number of bits per digit (1,3 and 4 respectively) divides - // equaly. We just shift until there value is zero. - - // First, check for a zero value and just short circuit the logic below. - if (*this == (uint64_t)(0)) { - // Always generate a radix indicator because fixed-point - // formats require it. - switch (radix) { - case 2: - result = "0b0"; - break; - case 8: - result = "0o0"; - break; - case 16: - result = "0x0"; - break; - default: - assert("invalid radix" && 0); - } - } else { - ap_private<_AP_W, false, true> tmp(*this); - size_t insert_at = 0; - bool leading_zero = true; - if (wantSigned && isNegative()) { - // They want to print the signed version and it is a negative value - // Flip the bits and add one to turn it into the equivalent positive - // value and put a '-' in the result. - tmp.flip(); - tmp++; - result = "-"; - insert_at = 1; - leading_zero = false; - } - switch (radix) { - case 2: - result += "0b"; - break; - case 8: - result += "0o"; - break; - case 16: - result += "0x"; - break; - default: - assert("invalid radix" && 0); - } - insert_at += 2; - - // Just shift tmp right for each digit width until it becomes zero - uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); - uint64_t mask = radix - 1; - ap_private<_AP_W, false, true> zero(0); - unsigned bits = 0; - bool msb = false; - while (tmp.ne(zero)) { - unsigned digit = (unsigned)(tmp.get_VAL() & mask); - result.insert(insert_at, digits[digit]); - tmp = tmp.lshr(shift); - bits++; - msb = (digit >> (shift - 1)) == 1; - } - bits *= shift; - if (bits < _AP_W && leading_zero && msb) - result.insert(insert_at, digits[0]); - } - return result; - } - - ap_private<_AP_W, false, true> tmp(*this); - ap_private<6, false, true> divisor(radix); - ap_private<_AP_W, _AP_S, true> zero(0); - size_t insert_at = 0; - if (wantSigned && isNegative()) { - // They want to print the signed version and it is a negative value - // Flip the bits and add one to turn it into the equivalent positive - // value and put a '-' in the result. - tmp.flip(); - tmp++; - result = "-"; - insert_at = 1; - } - if (tmp == ap_private<_AP_W, false, true>(0ULL)) - result = "0"; - else - while (tmp.ne(zero)) { - ap_private<_AP_W, false, true> APdigit = tmp % divisor; - ap_private<_AP_W, false, true> tmp2 = tmp / divisor; - uint32_t digit = (uint32_t)(APdigit.getZExtValue()); - assert(digit < radix && "divide failed"); - result.insert(insert_at, digits[digit]); - tmp = tmp2; - } - return result; - -} // End of ap_private<_AP_W, _AP_S, true>::toString() - -// bitwidth > 64 -template -class ap_private<_AP_W, _AP_S, false> { - // SFINAE pattern. Only consider this class when _AP_W > 64 - const static bool valid = ap_private_enable_if<(_AP_W > 64)>::isValid; - -#ifdef _MSC_VER -#pragma warning(disable : 4521 4522) -#endif - public: - enum { BitWidth = _AP_W, _AP_N = (_AP_W + 63) / 64 }; - static const int width = _AP_W; - - private: - /// This constructor is used only internally for speed of construction of - /// temporaries. It is unsafe for general use so it is not public. - - /* Constructors */ - /// Note that numWords can be smaller or larger than the corresponding bit - /// width but any extraneous bits will be dropped. - /// @param numWords the number of words in bigVal - /// @param bigVal a sequence of words to form the initial value of the - /// ap_private - /// @brief Construct an ap_private, initialized as bigVal[]. - INLINE ap_private(uint32_t numWords, const uint64_t bigVal[]) { - set_canary(); - assert(bigVal && "Null pointer detected!"); - { - // Get memory, cleared to 0 - memset(pVal, 0, _AP_N * sizeof(uint64_t)); - - // Calculate the number of words to copy - uint32_t words = AESL_std::min(numWords, _AP_N); - // Copy the words from bigVal to pVal - memcpy(pVal, bigVal, words * APINT_WORD_SIZE); - if (words >= _AP_W) clearUnusedBits(); - // Make sure unused high bits are cleared - } - check_canary(); - } - - /// This constructor interprets Val as a string in the given radix. The - /// interpretation stops when the first charater that is not suitable for the - /// radix is encountered. Acceptable radix values are 2, 8, 10 and 16. It is - /// an error for the value implied by the string to require more bits than - /// numBits. - /// @param val the string to be interpreted - /// @param radix the radix of Val to use for the intepretation - /// @brief Construct an ap_private from a string representation. - INLINE ap_private(const std::string& val, uint8_t radix = 2) { - set_canary(); - assert(!val.empty() && "The input string is empty."); - const char* c_str = val.c_str(); - fromString(c_str, val.size(), radix); - check_canary(); - } - - /// This constructor interprets the slen characters starting at StrStart as - /// a string in the given radix. The interpretation stops when the first - /// character that is not suitable for the radix is encountered. Acceptable - /// radix values are 2, 8, 10 and 16. It is an error for the value implied by - /// the string to require more bits than numBits. - /// @param strStart the start of the string to be interpreted - /// @param slen the maximum number of characters to interpret - /// @param radix the radix to use for the conversion - /// @brief Construct an ap_private from a string representation. - /// This method does not consider whether it is negative or not. - INLINE ap_private(const char strStart[], uint32_t slen, uint8_t radix) { - set_canary(); - fromString(strStart, slen, radix); - check_canary(); - } - - INLINE void report() { - _AP_ERROR(_AP_W > MAX_MODE(AP_INT_MAX_W) * 1024, - "ap_%sint<%d>: Bitwidth exceeds the " - "default max value %d. Please use macro " - "AP_INT_MAX_W to set a larger max value.", - _AP_S ? "" : "u", _AP_W, MAX_MODE(AP_INT_MAX_W) * 1024); - } - /// This union is used to store the integer value. When the - /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. - - /// This enum is used to hold the constants we needed for ap_private. - // uint64_t VAL; ///< Used to store the <= 64 bits integer value. - uint64_t pVal[_AP_N]; ///< Used to store the >64 bits integer value. -#ifdef AP_CANARY - uint64_t CANARY; - INLINE void check_canary() { assert(CANARY == (uint64_t)0xDEADBEEFDEADBEEF); } - INLINE void set_canary() { CANARY = (uint64_t)0xDEADBEEFDEADBEEF; } -#else - INLINE void check_canary() {} - INLINE void set_canary() {} -#endif - - public: - typedef typename valtype<8, _AP_S>::Type ValType; - typedef ap_private<_AP_W, _AP_S> Type; - // FIXME remove friend type? - template - friend struct ap_fixed_base; - /// return type of variety of operations - //---------------------------------------------------------- - template - struct RType { - enum { - mult_w = _AP_W + _AP_W2, - mult_s = _AP_S || _AP_S2, - plus_w = - AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1, - plus_s = _AP_S || _AP_S2, - minus_w = - AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)) + 1, - minus_s = true, - div_w = _AP_W + _AP_S2, - div_s = _AP_S || _AP_S2, - mod_w = AP_MIN(_AP_W, _AP_W2 + (!_AP_S2 && _AP_S)), - mod_s = _AP_S, - logic_w = AP_MAX(_AP_W + (_AP_S2 && !_AP_S), _AP_W2 + (_AP_S && !_AP_S2)), - logic_s = _AP_S || _AP_S2 - }; - typedef ap_private mult; - typedef ap_private plus; - typedef ap_private minus; - typedef ap_private logic; - typedef ap_private div; - typedef ap_private mod; - typedef ap_private<_AP_W, _AP_S> arg1; - typedef bool reduce; - }; - - INLINE uint64_t& get_VAL(void) { return pVal[0]; } - INLINE uint64_t get_VAL(void) const { return pVal[0]; } - INLINE uint64_t get_VAL(void) const volatile { return pVal[0]; } - INLINE void set_VAL(uint64_t value) { pVal[0] = value; } - INLINE uint64_t& get_pVal(int index) { return pVal[index]; } - INLINE uint64_t* get_pVal() { return pVal; } - INLINE const uint64_t* get_pVal() const { return pVal; } - INLINE uint64_t get_pVal(int index) const { return pVal[index]; } - INLINE uint64_t* get_pVal() const volatile { return pVal; } - INLINE uint64_t get_pVal(int index) const volatile { return pVal[index]; } - INLINE void set_pVal(int i, uint64_t value) { pVal[i] = value; } - - /// This enum is used to hold the constants we needed for ap_private. - enum { - APINT_BITS_PER_WORD = sizeof(uint64_t) * 8, ///< Bits in a word - APINT_WORD_SIZE = sizeof(uint64_t) ///< Byte size of a word - }; - - enum { - excess_bits = (_AP_W % APINT_BITS_PER_WORD) - ? APINT_BITS_PER_WORD - (_AP_W % APINT_BITS_PER_WORD) - : 0 - }; - static const uint64_t mask = ((uint64_t)~0ULL >> (excess_bits)); - - public: - // NOTE changed to explicit to be consistent with ap_private - explicit INLINE ap_private(const char* val) { - set_canary(); - unsigned char radix = 10; - std::string str = ap_private_ops::parseString(val, radix); // determine radix. - std::string::size_type pos = str.find('.'); - if (pos != std::string::npos) str = str.substr(pos); - ap_private ap_private_val(str, radix); - operator=(ap_private_val); - report(); - check_canary(); - } - - INLINE ap_private(const char* val, unsigned char rd) { - set_canary(); - unsigned char radix = rd; - std::string str = ap_private_ops::parseString(val, radix); // determine radix. - std::string::size_type pos = str.find('.'); - if (pos != std::string::npos) str = str.substr(pos); - ap_private ap_private_val(str, radix); - operator=(ap_private_val); - report(); - - report(); - check_canary(); - } - - template - INLINE ap_private(const _private_range_ref<_AP_W2, _AP_S2>& ref) { - set_canary(); - *this = ref.get(); - report(); - check_canary(); - } - - template - INLINE ap_private(const _private_bit_ref<_AP_W2, _AP_S2>& ref) { - set_canary(); - *this = ((uint64_t)(bool)ref); - report(); - check_canary(); - } - -// template -// INLINE ap_private(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& ref) { -// set_canary(); -// *this = ref.get(); -// report(); -// check_canary(); -// } -// -// template -// INLINE ap_private( -// const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { -// set_canary(); -// *this = ((val.operator ap_private<_AP_W2, false>())); -// report(); -// check_canary(); -// } -// -// template -// INLINE ap_private( -// const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { -// set_canary(); -// *this = (uint64_t)(bool)val; -// report(); -// check_canary(); -// } - - /// Simply makes *this a copy of that. - /// @brief Copy Constructor. - INLINE ap_private(const ap_private& that) { - set_canary(); - memcpy(pVal, that.get_pVal(), _AP_N * APINT_WORD_SIZE); - clearUnusedBits(); - check_canary(); - } - - template - INLINE ap_private(const ap_private<_AP_W1, _AP_S1, false>& that) { - set_canary(); - operator=(that); - check_canary(); - } - - template - INLINE ap_private(const volatile ap_private<_AP_W1, _AP_S1, false>& that) { - set_canary(); - operator=(const_cast&>(that)); - check_canary(); - } - - template - INLINE ap_private(const ap_private<_AP_W1, _AP_S1, true>& that) { - set_canary(); - static const uint64_t that_sign_ext_mask = - (_AP_W1 == APINT_BITS_PER_WORD) - ? 0 - : ~0ULL >> (_AP_W1 % APINT_BITS_PER_WORD) - << (_AP_W1 % APINT_BITS_PER_WORD); - if (that.isNegative()) { - pVal[0] = that.get_VAL() | that_sign_ext_mask; - memset(pVal + 1, ~0, sizeof(uint64_t) * (_AP_N - 1)); - } else { - pVal[0] = that.get_VAL(); - memset(pVal + 1, 0, sizeof(uint64_t) * (_AP_N - 1)); - } - clearUnusedBits(); - check_canary(); - } - - template - INLINE ap_private(const volatile ap_private<_AP_W1, _AP_S1, true>& that) { - set_canary(); - operator=(const_cast&>(that)); - check_canary(); - } - - /// @brief Destructor. - // virtual ~ap_private() {} - INLINE ~ap_private() { check_canary(); } - - /// @name Constructors - /// @{ - - /// Default constructor that creates an uninitialized ap_private. This is - /// useful - /// for object deserialization (pair this with the static method Read). - INLINE ap_private() { - set_canary(); - clearUnusedBits(); - check_canary(); - } - - INLINE ap_private(uint64_t* val, uint32_t bits = _AP_W) { assert(0); } - INLINE ap_private(const uint64_t* const val, uint32_t bits) { assert(0); } - -/// If isSigned is true then val is treated as if it were a signed value -/// (i.e. as an int64_t) and the appropriate sign extension to the bit width -/// will be done. Otherwise, no sign extension occurs (high order bits beyond -/// the range of val are zero filled). -/// @param numBits the bit width of the constructed ap_private -/// @param val the initial value of the ap_private -/// @param isSigned how to treat signedness of val -/// @brief Create a new ap_private of numBits width, initialized as val. -#define CTOR(TYPE, SIGNED) \ - INLINE ap_private(TYPE val, bool isSigned = SIGNED) { \ - set_canary(); \ - pVal[0] = (ValType)val; \ - if (isSigned && int64_t(pVal[0]) < 0) { \ - memset(pVal + 1, ~0, sizeof(uint64_t) * (_AP_N - 1)); \ - } else { \ - memset(pVal + 1, 0, sizeof(uint64_t) * (_AP_N - 1)); \ - } \ - clearUnusedBits(); \ - check_canary(); \ - } - - CTOR(bool, false) - CTOR(char, CHAR_IS_SIGNED) - CTOR(signed char, true) - CTOR(unsigned char, false) - CTOR(short, true) - CTOR(unsigned short, false) - CTOR(int, true) - CTOR(unsigned int, false) - CTOR(long, true) - CTOR(unsigned long, false) - CTOR(ap_slong, true) - CTOR(ap_ulong, false) -#if 0 - CTOR(half, false) - CTOR(float, false) - CTOR(double, false) -#endif -#undef CTOR - - /// @returns true if the number of bits <= 64, false otherwise. - /// @brief Determine if this ap_private just has one word to store value. - INLINE bool isSingleWord() const { return false; } - - /// @returns the word position for the specified bit position. - /// @brief Determine which word a bit is in. - static INLINE uint32_t whichWord(uint32_t bitPosition) { - // return bitPosition / APINT_BITS_PER_WORD; - return (bitPosition) >> 6; - } - - /// @returns the bit position in a word for the specified bit position - /// in the ap_private. - /// @brief Determine which bit in a word a bit is in. - static INLINE uint32_t whichBit(uint32_t bitPosition) { - // return bitPosition % APINT_BITS_PER_WORD; - return bitPosition & 0x3f; - } - - /// bit at a specific bit position. This is used to mask the bit in the - /// corresponding word. - /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set - /// @brief Get a single bit mask. - static INLINE uint64_t maskBit(uint32_t bitPosition) { - return 1ULL << (whichBit(bitPosition)); - } - - /// @returns the corresponding word for the specified bit position. - /// @brief Get the word corresponding to a bit position - INLINE uint64_t getWord(uint32_t bitPosition) const { - return pVal[whichWord(bitPosition)]; - } - - /// This method is used internally to clear the to "N" bits in the high order - /// word that are not used by the ap_private. This is needed after the most - /// significant word is assigned a value to ensure that those bits are - /// zero'd out. - /// @brief Clear unused high order bits - INLINE void clearUnusedBits(void) volatile -// just for clang compiler -#if defined(__clang__) && !defined(__CLANG_3_1__) - __attribute__((no_sanitize("undefined"))) -#endif - { - pVal[_AP_N - 1] = - _AP_S ? ((((int64_t)pVal[_AP_N - 1]) << (excess_bits)) >> excess_bits) - : (excess_bits - ? ((pVal[_AP_N - 1]) << (excess_bits)) >> (excess_bits) - : pVal[_AP_N - 1]); - } - - INLINE void clearUnusedBitsToZero(void) { pVal[_AP_N - 1] &= mask; } - - INLINE void clearUnusedBitsToOne(void) { pVal[_AP_N - 1] |= mask; } - - /// This is used by the constructors that take string arguments. - /// @brief Convert a char array into an ap_private - INLINE void fromString(const char* str, uint32_t slen, uint8_t radix) { - enum { numbits = _AP_W }; - bool isNeg = str[0] == '-'; - if (isNeg) { - str++; - slen--; - } - - if (str[0] == '0' && (str[1] == 'b' || str[1] == 'B')) { - //if(radix == 0) radix = 2; - _AP_WARNING(radix != 2, "%s seems to have base %d, but %d given.", str, 2, radix); - str += 2; - slen -=2; - } else if (str[0] == '0' && (str[1] == 'o' || str[1] == 'O')) { - //if (radix == 0) radix = 8; - _AP_WARNING(radix != 8, "%s seems to have base %d, but %d given.", str, 8, radix); - str += 2; - slen -=2; - } else if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { - //if (radix == 0) radix = 16; - _AP_WARNING(radix != 16, "%s seems to have base %d, but %d given.", str, 16, radix); - str += 2; - slen -=2; - } else if (str[0] == '0' && (str[1] == 'd' || str[1] == 'D')) { - //if (radix == 0) radix = 10; - _AP_WARNING(radix != 10, "%s seems to have base %d, but %d given.", str, 10, radix); - str += 2; - slen -=2; - } else if (radix == 0) { - //radix = 2; // XXX default value - } - - // Check our assumptions here - assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && - "Radix should be 2, 8, 10, or 16!"); - assert(str && "String is null?"); - - // skip any leading zero - while (*str == '0' && *(str + 1) != '\0') { - str++; - slen--; - } - assert((slen <= numbits || radix != 2) && "Insufficient bit width"); - assert(((slen - 1) * 3 <= numbits || radix != 8) && - "Insufficient bit width"); - assert(((slen - 1) * 4 <= numbits || radix != 16) && - "Insufficient bit width"); - assert((((slen - 1) * 64) / 22 <= numbits || radix != 10) && - "Insufficient bit width"); - - // clear bits - memset(pVal, 0, _AP_N * sizeof(uint64_t)); - - // Figure out if we can shift instead of multiply - uint32_t shift = (radix == 16 ? 4 : radix == 8 ? 3 : radix == 2 ? 1 : 0); - - // Set up an ap_private for the digit to add outside the loop so we don't - // constantly construct/destruct it. - uint64_t bigVal[_AP_N]; - memset(bigVal, 0, _AP_N * sizeof(uint64_t)); - ap_private<_AP_W, _AP_S> apdigit(getBitWidth(), bigVal); - ap_private<_AP_W, _AP_S> apradix(radix); - - // Enter digit traversal loop - for (unsigned i = 0; i < slen; i++) { - // Get a digit - uint32_t digit = 0; - char cdigit = str[i]; - if (radix == 16) { -#define isxdigit(c) \ - (((c) >= '0' && (c) <= '9') || ((c) >= 'a' && (c) <= 'f') || \ - ((c) >= 'A' && (c) <= 'F')) -#define isdigit(c) ((c) >= '0' && (c) <= '9') - if (!isxdigit(cdigit)) assert(0 && "Invalid hex digit in string"); - if (isdigit(cdigit)) - digit = cdigit - '0'; - else if (cdigit >= 'a') - digit = cdigit - 'a' + 10; - else if (cdigit >= 'A') - digit = cdigit - 'A' + 10; - else - assert(0 && "huh? we shouldn't get here"); - } else if (isdigit(cdigit)) { - digit = cdigit - '0'; - } else if (cdigit != '\0') { - assert(0 && "Invalid character in digit string"); - } -#undef isxdigit -#undef isdigit - // Shift or multiply the value by the radix - if (shift) - *this <<= shift; - else - *this *= apradix; - - // Add in the digit we just interpreted - apdigit.set_VAL(digit); - *this += apdigit; - } - // If its negative, put it in two's complement form - if (isNeg) { - (*this)--; - this->flip(); - } - clearUnusedBits(); - } - - INLINE ap_private read() volatile { return *this; } - - INLINE void write(const ap_private& op2) volatile { *this = (op2); } - - INLINE operator ValType() const { return get_VAL(); } - - INLINE int to_uchar() const { return (unsigned char)get_VAL(); } - - INLINE int to_char() const { return (signed char)get_VAL(); } - - INLINE int to_ushort() const { return (unsigned short)get_VAL(); } - - INLINE int to_short() const { return (short)get_VAL(); } - - INLINE int to_int() const { return (int)get_VAL(); } - - INLINE unsigned to_uint() const { return (unsigned)get_VAL(); } - - INLINE long to_long() const { return (long)get_VAL(); } - - INLINE unsigned long to_ulong() const { return (unsigned long)get_VAL(); } - - INLINE ap_slong to_int64() const { return (ap_slong)get_VAL(); } - - INLINE ap_ulong to_uint64() const { return (ap_ulong)get_VAL(); } - - INLINE double to_double() const { - if (isNegative()) - return roundToDouble(true); - else - return roundToDouble(false); - } - - INLINE unsigned length() const { return _AP_W; } - - /*Reverse the contents of ap_private instance. I.e. LSB becomes MSB and vise - * versa*/ - INLINE ap_private& reverse() { - for (int i = 0; i < _AP_W / 2; ++i) { - bool tmp = operator[](i); - if (operator[](_AP_W - 1 - i)) - set(i); - else - clear(i); - if (tmp) - set(_AP_W - 1 - i); - else - clear(_AP_W - 1 - i); - } - clearUnusedBits(); - return *this; - } - - /*Return true if the value of ap_private instance is zero*/ - INLINE bool iszero() const { return isMinValue(); } - - INLINE bool to_bool() const { return !iszero(); } - - /* x < 0 */ - INLINE bool sign() const { - if (isNegative()) return true; - return false; - } - - /* x[i] = !x[i] */ - INLINE void invert(int i) { - assert(i >= 0 && "Attempting to read bit with negative index"); - assert(i < _AP_W && "Attempting to read bit beyond MSB"); - flip(i); - } - - /* x[i] */ - INLINE bool test(int i) const { - assert(i >= 0 && "Attempting to read bit with negative index"); - assert(i < _AP_W && "Attempting to read bit beyond MSB"); - return operator[](i); - } - - // Set the ith bit into v - INLINE void set(int i, bool v) { - assert(i >= 0 && "Attempting to write bit with negative index"); - assert(i < _AP_W && "Attempting to write bit beyond MSB"); - v ? set(i) : clear(i); - } - - // Set the ith bit into v - INLINE void set_bit(int i, bool v) { - assert(i >= 0 && "Attempting to write bit with negative index"); - assert(i < _AP_W && "Attempting to write bit beyond MSB"); - v ? set(i) : clear(i); - } - - // FIXME different argument for different action? - INLINE ap_private& set(uint32_t bitPosition) { - pVal[whichWord(bitPosition)] |= maskBit(bitPosition); - clearUnusedBits(); - return *this; - } - - INLINE void set() { - for (int i = 0; i < _AP_N; ++i) pVal[i] = ~0ULL; - clearUnusedBits(); - } - - // Get the value of ith bit - INLINE bool get(int i) const { - assert(i >= 0 && "Attempting to read bit with negative index"); - assert(i < _AP_W && "Attempting to read bit beyond MSB"); - return ((maskBit(i) & (pVal[whichWord(i)])) != 0); - } - - // Get the value of ith bit - INLINE bool get_bit(int i) const { - assert(i >= 0 && "Attempting to read bit with negative index"); - assert(i < _AP_W && "Attempting to read bit beyond MSB"); - return ((maskBit(i) & (pVal[whichWord(i)])) != 0); - } - - // This is used for sc_lv and sc_bv, which is implemented by sc_uint - // Rotate an ap_private object n places to the left - INLINE void lrotate(int n) { - assert(n >= 0 && "Attempting to shift negative index"); - assert(n < _AP_W && "Shift value larger than bit width"); - operator=(shl(n) | lshr(_AP_W - n)); - } - - // This is used for sc_lv and sc_bv, which is implemented by sc_uint - // Rotate an ap_private object n places to the right - INLINE void rrotate(int n) { - assert(n >= 0 && "Attempting to shift negative index"); - assert(n < _AP_W && "Shift value larger than bit width"); - operator=(lshr(n) | shl(_AP_W - n)); - } - - /// Set the given bit to 0 whose position is given as "bitPosition". - /// @brief Set a given bit to 0. - INLINE ap_private& clear(uint32_t bitPosition) { - pVal[whichWord(bitPosition)] &= ~maskBit(bitPosition); - clearUnusedBits(); - return *this; - } - - /// @brief Set every bit to 0. - INLINE void clear() { memset(pVal, 0, _AP_N * APINT_WORD_SIZE); } - - /// @brief Toggle every bit to its opposite value. - ap_private& flip() { - for (int i = 0; i < _AP_N; ++i) pVal[i] ^= ~0ULL; - clearUnusedBits(); - return *this; - } - - /// @brief Toggles a given bit to its opposite value. - INLINE ap_private& flip(uint32_t bitPosition) { - assert(bitPosition < BitWidth && "Out of the bit-width range!"); - set_bit(bitPosition, !get_bit(bitPosition)); - return *this; - } - - // complements every bit - INLINE void b_not() { flip(); } - - INLINE ap_private getLoBits(uint32_t numBits) const { - return ap_private_ops::lshr(ap_private_ops::shl(*this, _AP_W - numBits), - _AP_W - numBits); - } - - INLINE ap_private getHiBits(uint32_t numBits) const { - return ap_private_ops::lshr(*this, _AP_W - numBits); - } - - // Binary Arithmetic - //----------------------------------------------------------- - -// template -// INLINE ap_private operator&( -// const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { -// return *this & a2.get(); -// } -// -// template -// INLINE ap_private operator|( -// const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { -// return *this | a2.get(); -// } -// -// template -// INLINE ap_private operator^( -// const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3>& a2) { -// return *this ^ a2.get(); -// } - -/// Arithmetic assign -//------------------------------------------------------------- - -#define OP_BIN_LOGIC_ASSIGN_AP(Sym) \ - template \ - INLINE ap_private& operator Sym(const ap_private<_AP_W1, _AP_S1>& RHS) { \ - const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N; \ - uint32_t numWords = AESL_std::min((int)_AP_N, _AP_N1); \ - uint32_t i; \ - if (_AP_W != _AP_W1) \ - fprintf(stderr, \ - "Warning! Bitsize mismach for ap_[u]int " #Sym " ap_[u]int.\n"); \ - for (i = 0; i < numWords; ++i) pVal[i] Sym RHS.get_pVal(i); \ - if (_AP_N1 < _AP_N) { \ - uint64_t ext = RHS.isNegative() ? ~0ULL : 0; \ - for (; i < _AP_N; i++) pVal[i] Sym ext; \ - } \ - clearUnusedBits(); \ - return *this; \ - } - - OP_BIN_LOGIC_ASSIGN_AP(&=); - OP_BIN_LOGIC_ASSIGN_AP(|=); - OP_BIN_LOGIC_ASSIGN_AP(^=); -#undef OP_BIN_LOGIC_ASSIGN_AP - - /// Adds the RHS APint to this ap_private. - /// @returns this, after addition of RHS. - /// @brief Addition assignment operator. - template - INLINE ap_private& operator+=(const ap_private<_AP_W1, _AP_S1>& RHS) { - const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N; - uint64_t RHSpVal[_AP_N1]; - for (int i = 0; i < _AP_N1; ++i) RHSpVal[i] = RHS.get_pVal(i); - ap_private_ops::add(pVal, pVal, RHSpVal, _AP_N, _AP_N, _AP_N1, _AP_S, - _AP_S1); - clearUnusedBits(); - return *this; - } - - template - INLINE ap_private& operator-=(const ap_private<_AP_W1, _AP_S1>& RHS) { - const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N; - uint64_t RHSpVal[_AP_N1]; - for (int i = 0; i < _AP_N1; ++i) RHSpVal[i] = RHS.get_pVal(i); - ap_private_ops::sub(pVal, pVal, RHSpVal, _AP_N, _AP_N, _AP_N1, _AP_S, - _AP_S1); - clearUnusedBits(); - return *this; - } - - template - INLINE ap_private& operator*=(const ap_private<_AP_W1, _AP_S1>& RHS) { - // Get some bit facts about LHS and check for zero - uint32_t lhsBits = getActiveBits(); - uint32_t lhsWords = !lhsBits ? 0 : whichWord(lhsBits - 1) + 1; - if (!lhsWords) { - // 0 * X ===> 0 - return *this; - } - - ap_private dupRHS = RHS; - // Get some bit facts about RHS and check for zero - uint32_t rhsBits = dupRHS.getActiveBits(); - uint32_t rhsWords = !rhsBits ? 0 : whichWord(rhsBits - 1) + 1; - if (!rhsWords) { - // X * 0 ===> 0 - clear(); - return *this; - } - - // Allocate space for the result - uint32_t destWords = rhsWords + lhsWords; - uint64_t* dest = (uint64_t*)malloc(destWords * sizeof(uint64_t)); - - // Perform the long multiply - ap_private_ops::mul(dest, pVal, lhsWords, dupRHS.get_pVal(), rhsWords, - destWords); - - // Copy result back into *this - clear(); - uint32_t wordsToCopy = destWords >= _AP_N ? _AP_N : destWords; - - memcpy(pVal, dest, wordsToCopy * APINT_WORD_SIZE); - - uint64_t ext = (isNegative() ^ RHS.isNegative()) ? ~0ULL : 0ULL; - for (int i = wordsToCopy; i < _AP_N; i++) pVal[i] = ext; - clearUnusedBits(); - // delete dest array and return - free(dest); - return *this; - } - -#define OP_ASSIGN_AP(Sym) \ - template \ - INLINE ap_private& operator Sym##=(const ap_private<_AP_W2, _AP_S2>& op) { \ - *this = operator Sym(op); \ - return *this; \ - } - - OP_ASSIGN_AP(/) - OP_ASSIGN_AP(%) -#undef OP_ASSIGN_AP - -#define OP_BIN_LOGIC_AP(Sym) \ - template \ - INLINE typename RType<_AP_W1, _AP_S1>::logic operator Sym( \ - const ap_private<_AP_W1, _AP_S1>& RHS) const { \ - enum { \ - numWords = (RType<_AP_W1, _AP_S1>::logic_w + APINT_BITS_PER_WORD - 1) / \ - APINT_BITS_PER_WORD \ - }; \ - typename RType<_AP_W1, _AP_S1>::logic Result; \ - uint32_t i; \ - const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N; \ - uint32_t min_N = std::min((int)_AP_N, _AP_N1); \ - uint32_t max_N = std::max((int)_AP_N, _AP_N1); \ - for (i = 0; i < min_N; ++i) \ - Result.set_pVal(i, pVal[i] Sym RHS.get_pVal(i)); \ - if (numWords > i) { \ - uint64_t ext = ((_AP_N < _AP_N1 && isNegative()) || \ - (_AP_N1 < _AP_N && RHS.isNegative())) \ - ? ~0ULL \ - : 0; \ - if (_AP_N > _AP_N1) \ - for (; i < max_N; i++) Result.set_pVal(i, pVal[i] Sym ext); \ - else \ - for (; i < max_N; i++) Result.set_pVal(i, RHS.get_pVal(i) Sym ext); \ - if (numWords > i) { \ - uint64_t ext2 = ((_AP_N > _AP_N1 && isNegative()) || \ - (_AP_N1 > _AP_N && RHS.isNegative())) \ - ? ~0ULL \ - : 0; \ - Result.set_pVal(i, ext Sym ext2); \ - } \ - } \ - Result.clearUnusedBits(); \ - return Result; \ - } - - OP_BIN_LOGIC_AP(|); - OP_BIN_LOGIC_AP(&); - OP_BIN_LOGIC_AP(^); - -#undef OP_BIN_LOGIC_AP - - template - INLINE typename RType<_AP_W1, _AP_S1>::plus operator+( - const ap_private<_AP_W1, _AP_S1>& RHS) const { - typename RType<_AP_W1, _AP_S1>::plus Result, lhs(*this), rhs(RHS); - const int Result_AP_N = (RType<_AP_W1, _AP_S1>::plus_w + 63) / 64; - ap_private_ops::add(Result.get_pVal(), lhs.get_pVal(), rhs.get_pVal(), - Result_AP_N, Result_AP_N, Result_AP_N, _AP_S, _AP_S1); - Result.clearUnusedBits(); - return Result; - } - - template - INLINE typename RType<_AP_W1, _AP_S1>::minus operator-( - const ap_private<_AP_W1, _AP_S1>& RHS) const { - typename RType<_AP_W1, _AP_S1>::minus Result, lhs(*this), rhs(RHS); - const int Result_AP_N = (RType<_AP_W1, _AP_S1>::minus_w + 63) / 64; - ap_private_ops::sub(Result.get_pVal(), lhs.get_pVal(), rhs.get_pVal(), - Result_AP_N, Result_AP_N, Result_AP_N, _AP_S, _AP_S1); - Result.clearUnusedBits(); - return Result; - } - - template - INLINE typename RType<_AP_W1, _AP_S1>::mult operator*( - const ap_private<_AP_W1, _AP_S1>& RHS) const { - typename RType<_AP_W1, _AP_S1>::mult temp = *this; - temp *= RHS; - return temp; - } - - template - INLINE typename RType<_AP_W2, _AP_S2>::div operator/( - const ap_private<_AP_W2, _AP_S2>& op) const { - ap_private _AP_W2 ? _AP_S - : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))> - lhs = *this; - ap_private _AP_W2 ? _AP_S - : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))> - rhs = op; - return typename RType<_AP_W2, _AP_S2>::div( - (_AP_S || _AP_S2) ? lhs.sdiv(rhs) : lhs.udiv(rhs)); - } - - template - INLINE typename RType<_AP_W2, _AP_S2>::mod operator%( - const ap_private<_AP_W2, _AP_S2>& op) const { - ap_private _AP_W2 ? _AP_S - : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))> - lhs = *this; - ap_private _AP_W2 ? _AP_S - : (_AP_W2 > _AP_W ? _AP_S2 : _AP_S || _AP_S2))> - rhs = op; - typename RType<_AP_W2, _AP_S2>::mod res = - typename RType<_AP_W2, _AP_S2>::mod(_AP_S ? lhs.srem(rhs) - : lhs.urem(rhs)); - return res; - } - -#define OP_LEFT_SHIFT_CTYPE(TYPE, SIGNED) \ - INLINE ap_private operator<<(const TYPE op) const { \ - if (op >= _AP_W) return ap_private(0); \ - if (SIGNED && op < 0) return *this >> (0 - op); \ - return shl(op); \ - } - - OP_LEFT_SHIFT_CTYPE(int, true) - // OP_LEFT_SHIFT_CTYPE(bool, false) - OP_LEFT_SHIFT_CTYPE(signed char, true) - OP_LEFT_SHIFT_CTYPE(unsigned char, false) - OP_LEFT_SHIFT_CTYPE(short, true) - OP_LEFT_SHIFT_CTYPE(unsigned short, false) - OP_LEFT_SHIFT_CTYPE(unsigned int, false) - OP_LEFT_SHIFT_CTYPE(long, true) - OP_LEFT_SHIFT_CTYPE(unsigned long, false) - OP_LEFT_SHIFT_CTYPE(unsigned long long, false) - OP_LEFT_SHIFT_CTYPE(long long, true) -#if 0 - OP_LEFT_SHIFT_CTYPE(half, false) - OP_LEFT_SHIFT_CTYPE(float, false) - OP_LEFT_SHIFT_CTYPE(double, false) -#endif -#undef OP_LEFT_SHIFT_CTYPE - - template - INLINE ap_private operator<<(const ap_private<_AP_W2, _AP_S2>& op2) const { - if (_AP_S2 == false) { - uint32_t sh = op2.to_uint(); - return *this << sh; - } else { - int sh = op2.to_int(); - return *this << sh; - } - } - -#define OP_RIGHT_SHIFT_CTYPE(TYPE, SIGNED) \ - INLINE ap_private operator>>(const TYPE op) const { \ - if (op >= _AP_W) { \ - if (isNegative()) \ - return ap_private(-1); \ - else \ - return ap_private(0); \ - } \ - if ((SIGNED) && op < 0) return *this << (0 - op); \ - if (_AP_S) \ - return ashr(op); \ - else \ - return lshr(op); \ - } - - // OP_RIGHT_SHIFT_CTYPE(bool, false) - OP_RIGHT_SHIFT_CTYPE(char, CHAR_IS_SIGNED) - OP_RIGHT_SHIFT_CTYPE(signed char, true) - OP_RIGHT_SHIFT_CTYPE(unsigned char, false) - OP_RIGHT_SHIFT_CTYPE(short, true) - OP_RIGHT_SHIFT_CTYPE(unsigned short, false) - OP_RIGHT_SHIFT_CTYPE(int, true) - OP_RIGHT_SHIFT_CTYPE(unsigned int, false) - OP_RIGHT_SHIFT_CTYPE(long, true) - OP_RIGHT_SHIFT_CTYPE(unsigned long, false) - OP_RIGHT_SHIFT_CTYPE(unsigned long long, false) - OP_RIGHT_SHIFT_CTYPE(long long, true) -#if 0 - OP_RIGHT_SHIFT_CTYPE(half, false) - OP_RIGHT_SHIFT_CTYPE(float, false) - OP_RIGHT_SHIFT_CTYPE(double, false) -#endif -#undef OP_RIGHT_SHIFT_CTYPE - - template - INLINE ap_private operator>>(const ap_private<_AP_W2, _AP_S2>& op2) const { - if (_AP_S2 == false) { - uint32_t sh = op2.to_uint(); - return *this >> sh; - } else { - int sh = op2.to_int(); - return *this >> sh; - } - } - - /// Shift assign - //------------------------------------------------------------------ - // TODO call clearUnusedBits ? -#define OP_ASSIGN_AP(Sym) \ - template \ - INLINE ap_private& operator Sym##=(int op) { \ - *this = operator Sym(op); \ - return *this; \ - } \ - INLINE ap_private& operator Sym##=(unsigned int op) { \ - *this = operator Sym(op); \ - return *this; \ - } \ - template \ - INLINE ap_private& operator Sym##=(const ap_private<_AP_W2, _AP_S2>& op) { \ - *this = operator Sym(op); \ - return *this; \ - } - OP_ASSIGN_AP(>>) - OP_ASSIGN_AP(<<) -#undef OP_ASSIGN_AP - - /// Comparisons - //----------------------------------------------------------------- - INLINE bool operator==(const ap_private& RHS) const { - // Get some facts about the number of bits used in the two operands. - uint32_t n1 = getActiveBits(); - uint32_t n2 = RHS.getActiveBits(); - - // If the number of bits isn't the same, they aren't equal - if (n1 != n2) return false; - - // If the number of bits fits in a word, we only need to compare the low - // word. - if (n1 <= APINT_BITS_PER_WORD) return pVal[0] == RHS.get_pVal(0); - - // Otherwise, compare everything - for (int i = whichWord(n1 - 1); i >= 0; --i) - if (pVal[i] != RHS.get_pVal(i)) return false; - return true; - } - - template - INLINE bool operator==(const ap_private<_AP_W2, _AP_S2>& op) const { - enum { - _AP_MAX_W = AP_MAX(_AP_W, _AP_W2), - }; - ap_private<_AP_MAX_W, false> lhs(*this); - ap_private<_AP_MAX_W, false> rhs(op); - return lhs == rhs; - } - - INLINE bool operator==(uint64_t Val) const { - uint32_t n = getActiveBits(); - if (n <= APINT_BITS_PER_WORD) - return pVal[0] == Val; - else - return false; - } - - template - INLINE bool operator!=(const ap_private<_AP_W2, _AP_S2>& op) const { - return !(*this == op); - } - - template - INLINE bool operator!=(const ap_private<_AP_W, _AP_S1>& RHS) const { - return !((*this) == RHS); - } - - INLINE bool operator!=(uint64_t Val) const { return !((*this) == Val); } - - template - INLINE bool operator<=(const ap_private<_AP_W2, _AP_S2>& op) const { - return !(*this > op); - } - - INLINE bool operator<(const ap_private& op) const { - return _AP_S ? slt(op) : ult(op); - } - - template - INLINE bool operator<(const ap_private<_AP_W2, _AP_S2>& op) const { - enum { - _AP_MAX_W = AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2)) - }; - ap_private<_AP_MAX_W, _AP_S> lhs(*this); - ap_private<_AP_MAX_W, _AP_S2> rhs(op); - if (_AP_S == _AP_S2) - return _AP_S ? lhs.slt(rhs) : lhs.ult(rhs); - else if (_AP_S) - if (_AP_W2 >= _AP_W) - return lhs.ult(rhs); - else - return lhs.slt(rhs); - else if (_AP_W >= _AP_W2) - return lhs.ult(rhs); - else - return lhs.slt(rhs); - } - - template - INLINE bool operator>=(const ap_private<_AP_W2, _AP_S2>& op) const { - return !(*this < op); - } - - INLINE bool operator>(const ap_private& op) const { - return _AP_S ? sgt(op) : ugt(op); - } - - template - INLINE bool operator>(const ap_private<_AP_W2, _AP_S2>& op) const { - enum { - _AP_MAX_W = AP_MAX(_AP_W + (_AP_S || _AP_S2), _AP_W2 + (_AP_S || _AP_S2)) - }; - ap_private<_AP_MAX_W, _AP_S> lhs(*this); - ap_private<_AP_MAX_W, _AP_S2> rhs(op); - if (_AP_S == _AP_S2) - return _AP_S ? lhs.sgt(rhs) : lhs.ugt(rhs); - else if (_AP_S) - if (_AP_W2 >= _AP_W) - return lhs.ugt(rhs); - else - return lhs.sgt(rhs); - else if (_AP_W >= _AP_W2) - return lhs.ugt(rhs); - else - return lhs.sgt(rhs); - } - - /// Bit and Part Select - //-------------------------------------------------------------- - INLINE _private_range_ref<_AP_W, _AP_S> operator()(int Hi, int Lo) { - return _private_range_ref<_AP_W, _AP_S>(this, Hi, Lo); - } - - INLINE _private_range_ref<_AP_W, _AP_S> operator()(int Hi, int Lo) const { - return _private_range_ref<_AP_W, _AP_S>( - const_cast*>(this), Hi, Lo); - } - - INLINE _private_range_ref<_AP_W, _AP_S> range(int Hi, int Lo) const { - return _private_range_ref<_AP_W, _AP_S>( - (const_cast*>(this)), Hi, Lo); - } - - INLINE _private_range_ref<_AP_W, _AP_S> range(int Hi, int Lo) { - return _private_range_ref<_AP_W, _AP_S>(this, Hi, Lo); - } - - template - INLINE _private_range_ref<_AP_W, _AP_S> range( - const ap_private<_AP_W2, _AP_S2>& HiIdx, - const ap_private<_AP_W3, _AP_S3>& LoIdx) { - int Hi = HiIdx.to_int(); - int Lo = LoIdx.to_int(); - return _private_range_ref<_AP_W, _AP_S>(this, Hi, Lo); - } - - template - INLINE _private_range_ref<_AP_W, _AP_S> operator()( - const ap_private<_AP_W2, _AP_S2>& HiIdx, - const ap_private<_AP_W3, _AP_S3>& LoIdx) { - int Hi = HiIdx.to_int(); - int Lo = LoIdx.to_int(); - return _private_range_ref<_AP_W, _AP_S>(this, Hi, Lo); - } - - template - INLINE _private_range_ref<_AP_W, _AP_S> range( - const ap_private<_AP_W2, _AP_S2>& HiIdx, - const ap_private<_AP_W3, _AP_S3>& LoIdx) const { - int Hi = HiIdx.to_int(); - int Lo = LoIdx.to_int(); - return _private_range_ref<_AP_W, _AP_S>(const_cast(this), Hi, Lo); - } - - template - INLINE _private_range_ref<_AP_W, _AP_S> operator()( - const ap_private<_AP_W2, _AP_S2>& HiIdx, - const ap_private<_AP_W3, _AP_S3>& LoIdx) const { - int Hi = HiIdx.to_int(); - int Lo = LoIdx.to_int(); - return this->range(Hi, Lo); - } - - INLINE _private_bit_ref<_AP_W, _AP_S> operator[](int index) { - return _private_bit_ref<_AP_W, _AP_S>(*this, index); - } - - template - INLINE _private_bit_ref<_AP_W, _AP_S> operator[]( - const ap_private<_AP_W2, _AP_S2>& index) { - return _private_bit_ref<_AP_W, _AP_S>(*this, index.to_int()); - } - - template - INLINE const _private_bit_ref<_AP_W, _AP_S> operator[]( - const ap_private<_AP_W2, _AP_S2>& index) const { - return _private_bit_ref<_AP_W, _AP_S>( - const_cast&>(*this), index.to_int()); - } - - INLINE const _private_bit_ref<_AP_W, _AP_S> operator[](int index) const { - return _private_bit_ref<_AP_W, _AP_S>( - const_cast&>(*this), index); - } - - INLINE _private_bit_ref<_AP_W, _AP_S> bit(int index) { - return _private_bit_ref<_AP_W, _AP_S>(*this, index); - } - - template - INLINE _private_bit_ref<_AP_W, _AP_S> bit(const ap_private<_AP_W2, _AP_S2>& index) { - return _private_bit_ref<_AP_W, _AP_S>(*this, index.to_int()); - } - - INLINE const _private_bit_ref<_AP_W, _AP_S> bit(int index) const { - return _private_bit_ref<_AP_W, _AP_S>( - const_cast&>(*this), index); - } - - template - INLINE const _private_bit_ref<_AP_W, _AP_S> bit( - const ap_private<_AP_W2, _AP_S2>& index) const { - return _private_bit_ref<_AP_W, _AP_S>( - const_cast&>(*this), index.to_int()); - } - -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// ap_private<_AP_W2, _AP_S2> > -// concat(ap_private<_AP_W2, _AP_S2>& a2) { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >(*this, a2); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// ap_private<_AP_W2, _AP_S2> > -// concat(const ap_private<_AP_W2, _AP_S2>& a2) const { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >( -// const_cast&>(*this), -// const_cast&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > -// operator,(ap_private<_AP_W2, _AP_S2> &a2) { -// return ap_concat_ref<_AP_W, ap_private, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >(*this, a2); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > -// operator,(ap_private<_AP_W2, _AP_S2> &a2) const { -// return ap_concat_ref<_AP_W, ap_private, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >( -// const_cast&>(*this), a2); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > -// operator,(const ap_private<_AP_W2, _AP_S2> &a2) { -// return ap_concat_ref<_AP_W, ap_private, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >( -// *this, const_cast&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private, _AP_W2, ap_private<_AP_W2, _AP_S2> > -// operator,(const ap_private<_AP_W2, _AP_S2> &a2) const { -// return ap_concat_ref<_AP_W, ap_private, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >( -// const_cast&>(*this), -// const_cast&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// _private_range_ref<_AP_W2, _AP_S2> > -// operator,(const _private_range_ref<_AP_W2, _AP_S2> &a2) const { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// _private_range_ref<_AP_W2, _AP_S2> >( -// const_cast&>(*this), -// const_cast<_private_range_ref<_AP_W2, _AP_S2>&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// _private_range_ref<_AP_W2, _AP_S2> > -// operator,(_private_range_ref<_AP_W2, _AP_S2> &a2) { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2, -// _private_range_ref<_AP_W2, _AP_S2> >(*this, a2); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, -// _private_bit_ref<_AP_W2, _AP_S2> > -// operator,(const _private_bit_ref<_AP_W2, _AP_S2> &a2) const { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, -// _private_bit_ref<_AP_W2, _AP_S2> >( -// const_cast&>(*this), -// const_cast<_private_bit_ref<_AP_W2, _AP_S2>&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, -// _private_bit_ref<_AP_W2, _AP_S2> > -// operator,(_private_bit_ref<_AP_W2, _AP_S2> &a2) { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, 1, -// _private_bit_ref<_AP_W2, _AP_S2> >(*this, a2); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3, -// ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > -// operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3, -// ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >( -// const_cast&>(*this), -// const_cast&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3, -// ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > -// operator,(ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { -// return ap_concat_ref<_AP_W, ap_private<_AP_W, _AP_S>, _AP_W2 + _AP_W3, -// ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >(*this, -// a2); -// } -// -// template -// INLINE ap_concat_ref< -// _AP_W, ap_private, _AP_W2, -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > -// operator,(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> -// &a2) const { -// return ap_concat_ref< -// _AP_W, ap_private, _AP_W2, -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( -// const_cast&>(*this), -// const_cast< -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>&>(a2)); -// } -// -// template -// INLINE ap_concat_ref< -// _AP_W, ap_private, _AP_W2, -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > -// operator,(af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) { -// return ap_concat_ref< -// _AP_W, ap_private, _AP_W2, -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, -// a2); -// } -// -// template -// INLINE -// ap_concat_ref<_AP_W, ap_private, 1, -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > -// operator,(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> -// &a2) const { -// return ap_concat_ref< -// _AP_W, ap_private, 1, -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( -// const_cast&>(*this), -// const_cast&>( -// a2)); -// } -// -// template -// INLINE -// ap_concat_ref<_AP_W, ap_private, 1, -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > -// operator,( -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) { -// return ap_concat_ref< -// _AP_W, ap_private, 1, -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >(*this, a2); -// } - - INLINE ap_private<_AP_W, false> get() const { - ap_private<_AP_W, false> ret(*this); - return ret; - } - - template - INLINE void set(const ap_private<_AP_W3, false>& val) { - operator=(ap_private<_AP_W3, _AP_S>(val)); - } - - /// - /// @name Value Tests - /// - /// This tests the high bit of this ap_private to determine if it is set. - /// @returns true if this ap_private is negative, false otherwise - /// @brief Determine sign of this ap_private. - INLINE bool isNegative() const { - // just for get rid of warnings - enum { shift = (_AP_W - APINT_BITS_PER_WORD * (_AP_N - 1) - 1) }; - static const uint64_t mask = 1ULL << (shift); - return _AP_S && (pVal[_AP_N - 1] & mask); - } - - /// This tests the high bit of the ap_private to determine if it is unset. - /// @brief Determine if this ap_private Value is positive (not negative). - INLINE bool isPositive() const { return !isNegative(); } - - /// This tests if the value of this ap_private is strictly positive (> 0). - /// @returns true if this ap_private is Positive and not zero. - /// @brief Determine if this ap_private Value is strictly positive. - INLINE bool isStrictlyPositive() const { - return isPositive() && (*this) != 0; - } - - /// This checks to see if the value has all bits of the ap_private are set or - /// not. - /// @brief Determine if all bits are set - INLINE bool isAllOnesValue() const { return countPopulation() == _AP_W; } - - /// This checks to see if the value of this ap_private is the maximum unsigned - /// value for the ap_private's bit width. - /// @brief Determine if this is the largest unsigned value. - INLINE bool isMaxValue() const { return countPopulation() == _AP_W; } - - /// This checks to see if the value of this ap_private is the maximum signed - /// value for the ap_private's bit width. - /// @brief Determine if this is the largest signed value. - INLINE bool isMaxSignedValue() const { - return !isNegative() && countPopulation() == _AP_W - 1; - } - - /// This checks to see if the value of this ap_private is the minimum unsigned - /// value for the ap_private's bit width. - /// @brief Determine if this is the smallest unsigned value. - INLINE bool isMinValue() const { return countPopulation() == 0; } - - /// This checks to see if the value of this ap_private is the minimum signed - /// value for the ap_private's bit width. - /// @brief Determine if this is the smallest signed value. - INLINE bool isMinSignedValue() const { - return isNegative() && countPopulation() == 1; - } - - /// This function returns a pointer to the internal storage of the ap_private. - /// This is useful for writing out the ap_private in binary form without any - /// conversions. - INLINE const uint64_t* getRawData() const { return &pVal[0]; } - - // Square Root - this method computes and returns the square root of "this". - // Three mechanisms are used for computation. For small values (<= 5 bits), - // a table lookup is done. This gets some performance for common cases. For - // values using less than 52 bits, the value is converted to double and then - // the libc sqrt function is called. The result is rounded and then converted - // back to a uint64_t which is then used to construct the result. Finally, - // the Babylonian method for computing square roots is used. - INLINE ap_private sqrt() const { - // Determine the magnitude of the value. - uint32_t magnitude = getActiveBits(); - - // Use a fast table for some small values. This also gets rid of some - // rounding errors in libc sqrt for small values. - if (magnitude <= 5) { - static const uint8_t results[32] = { - /* 0 */ 0, - /* 1- 2 */ 1, 1, - /* 3- 6 */ 2, 2, 2, 2, - /* 7-12 */ 3, 3, 3, 3, 3, 3, - /* 13-20 */ 4, 4, 4, 4, 4, 4, 4, 4, - /* 21-30 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - /* 31 */ 6}; - return ap_private<_AP_W, _AP_S>(/*BitWidth,*/ results[get_VAL()]); - } - - // If the magnitude of the value fits in less than 52 bits (the precision of - // an IEEE double precision floating point value), then we can use the - // libc sqrt function which will probably use a hardware sqrt computation. - // This should be faster than the algorithm below. - if (magnitude < 52) { -#ifdef _MSC_VER - // Amazingly, VC++ doesn't have round(). - return ap_private<_AP_W, _AP_S>(/*BitWidth,*/ - uint64_t(::sqrt(double(get_VAL()))) + - 0.5); -#else - return ap_private<_AP_W, _AP_S>(/*BitWidth,*/ - uint64_t( - ::round(::sqrt(double(get_VAL()))))); -#endif - } - - // Okay, all the short cuts are exhausted. We must compute it. The following - // is a classical Babylonian method for computing the square root. This code - // was adapted to APINt from a wikipedia article on such computations. - // See http://www.wikipedia.org/ and go to the page named - // Calculate_an_integer_square_root. - uint32_t nbits = BitWidth, i = 4; - ap_private<_AP_W, _AP_S> testy(16); - ap_private<_AP_W, _AP_S> x_old(/*BitWidth,*/ 1); - ap_private<_AP_W, _AP_S> x_new(0); - ap_private<_AP_W, _AP_S> two(/*BitWidth,*/ 2); - - // Select a good starting value using binary logarithms. - for (;; i += 2, testy = testy.shl(2)) - if (i >= nbits || this->ule(testy)) { - x_old = x_old.shl(i / 2); - break; - } - - // Use the Babylonian method to arrive at the integer square root: - for (;;) { - x_new = (this->udiv(x_old) + x_old).udiv(two); - if (x_old.ule(x_new)) break; - x_old = x_new; - } - - // Make sure we return the closest approximation - // NOTE: The rounding calculation below is correct. It will produce an - // off-by-one discrepancy with results from pari/gp. That discrepancy has - // been - // determined to be a rounding issue with pari/gp as it begins to use a - // floating point representation after 192 bits. There are no discrepancies - // between this algorithm and pari/gp for bit widths < 192 bits. - ap_private<_AP_W, _AP_S> square(x_old * x_old); - ap_private<_AP_W, _AP_S> nextSquare((x_old + 1) * (x_old + 1)); - if (this->ult(square)) - return x_old; - else if (this->ule(nextSquare)) { - ap_private<_AP_W, _AP_S> midpoint((nextSquare - square).udiv(two)); - ap_private<_AP_W, _AP_S> offset(*this - square); - if (offset.ult(midpoint)) - return x_old; - else - return x_old + 1; - } else - assert(0 && "Error in ap_private<_AP_W, _AP_S>::sqrt computation"); - return x_old + 1; - } - - /// - /// @Assignment Operators - /// - /// @returns *this after assignment of RHS. - /// @brief Copy assignment operator. - INLINE ap_private& operator=(const ap_private& RHS) { - if (this != &RHS) memcpy(pVal, RHS.get_pVal(), _AP_N * APINT_WORD_SIZE); - clearUnusedBits(); - return *this; - } - INLINE ap_private& operator=(const volatile ap_private& RHS) { - if (this != &RHS) - for (int i = 0; i < _AP_N; ++i) pVal[i] = RHS.get_pVal(i); - clearUnusedBits(); - return *this; - } - INLINE void operator=(const ap_private& RHS) volatile { - if (this != &RHS) - for (int i = 0; i < _AP_N; ++i) pVal[i] = RHS.get_pVal(i); - clearUnusedBits(); - } - INLINE void operator=(const volatile ap_private& RHS) volatile { - if (this != &RHS) - for (int i = 0; i < _AP_N; ++i) pVal[i] = RHS.get_pVal(i); - clearUnusedBits(); - } - - template - INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1>& RHS) { - if (_AP_S1) - cpSextOrTrunc(RHS); - else - cpZextOrTrunc(RHS); - clearUnusedBits(); - return *this; - } - - template - INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1>& RHS) { - if (_AP_S1) - cpSextOrTrunc(RHS); - else - cpZextOrTrunc(RHS); - clearUnusedBits(); - return *this; - } - - template - INLINE ap_private& operator=(const _private_range_ref<_AP_W2, _AP_S2>& op2) { - *this = ap_private<_AP_W2, false>(op2); - return *this; - } - -#if 0 - template - INLINE ap_private& operator=(const ap_private<_AP_W1, _AP_S1, true>& RHS) { - static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); - if (RHS.isNegative()) { - pVal[0] = RHS.get_VAL() | that_sign_ext_mask; - memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); - } else { - pVal[0] = RHS.get_VAL(); - memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); - } - clearUnusedBits(); - return *this; - } - - template - INLINE ap_private& operator=(const volatile ap_private<_AP_W1, _AP_S1, true>& RHS) { - static const uint64_t that_sign_ext_mask = (_AP_W1==APINT_BITS_PER_WORD)?0:~0ULL>>(_AP_W1%APINT_BITS_PER_WORD)<<(_AP_W1%APINT_BITS_PER_WORD); - if (RHS.isNegative()) { - pVal[0] = RHS.get_VAL() | that_sign_ext_mask; - memset(pVal+1,~0, APINT_WORD_SIZE*(_AP_N-1)); - } else { - pVal[0] = RHS.get_VAL(); - memset(pVal+1, 0, APINT_WORD_SIZE*(_AP_N-1)); - } - clearUnusedBits(); - return *this; - } -#endif - -/// from all c types. -#define ASSIGN_OP_FROM_INT(C_TYPE, _AP_W2, _AP_S2) \ - INLINE ap_private& operator=(const C_TYPE rhs) { \ - ap_private<(_AP_W2), (_AP_S2)> tmp = rhs; \ - operator=(tmp); \ - return *this; \ - } - - ASSIGN_OP_FROM_INT(bool, 1, false) - ASSIGN_OP_FROM_INT(char, 8, CHAR_IS_SIGNED) - ASSIGN_OP_FROM_INT(signed char, 8, true) - ASSIGN_OP_FROM_INT(unsigned char, 8, false) - ASSIGN_OP_FROM_INT(short, sizeof(short) * 8, true) - ASSIGN_OP_FROM_INT(unsigned short, sizeof(unsigned short) * 8, false) - ASSIGN_OP_FROM_INT(int, sizeof(int) * 8, true) - ASSIGN_OP_FROM_INT(unsigned int, sizeof(unsigned int) * 8, false) - ASSIGN_OP_FROM_INT(long, sizeof(long) * 8, true) - ASSIGN_OP_FROM_INT(unsigned long, sizeof(unsigned long) * 8, false) - ASSIGN_OP_FROM_INT(ap_slong, sizeof(ap_slong) * 8, true) - ASSIGN_OP_FROM_INT(ap_ulong, sizeof(ap_ulong) * 8, false) -#undef ASSIGN_OP_FROM_INT - - /// from c string. - // XXX this is a must, to prevent pointer being converted to bool. - INLINE ap_private& operator=(const char* s) { - ap_private tmp(s); // XXX direct initialization, as ctor is explicit. - operator=(tmp); - return *this; - } - - /// - /// @name Unary Operators - /// - /// @returns a new ap_private value representing *this incremented by one - /// @brief Postfix increment operator. - INLINE const ap_private operator++(int) { - ap_private API(*this); - ++(*this); - return API; - } - - /// @returns *this incremented by one - /// @brief Prefix increment operator. - INLINE ap_private& operator++() { - ap_private_ops::add_1(pVal, pVal, _AP_N, 1); - clearUnusedBits(); - return *this; - } - - /// @returns a new ap_private representing *this decremented by one. - /// @brief Postfix decrement operator. - INLINE const ap_private operator--(int) { - ap_private API(*this); - --(*this); - return API; - } - - /// @returns *this decremented by one. - /// @brief Prefix decrement operator. - INLINE ap_private& operator--() { - ap_private_ops::sub_1(pVal, _AP_N, 1); - clearUnusedBits(); - return *this; - } - - /// Performs a bitwise complement operation on this ap_private. - /// @returns an ap_private that is the bitwise complement of *this - /// @brief Unary bitwise complement operator. - INLINE ap_private<_AP_W + !_AP_S, true> operator~() const { - ap_private<_AP_W + !_AP_S, true> Result(*this); - Result.flip(); - return Result; - } - - /// Negates *this using two's complement logic. - /// @returns An ap_private value representing the negation of *this. - /// @brief Unary negation operator - INLINE typename RType<1, false>::minus operator-() const { - return ap_private<1, false>(0) - (*this); - } - - /// Performs logical negation operation on this ap_private. - /// @returns true if *this is zero, false otherwise. - /// @brief Logical negation operator. - INLINE bool operator!() const { - for (int i = 0; i < _AP_N; ++i) - if (pVal[i]) return false; - return true; - } - - template - INLINE ap_private<_AP_W, _AP_S || _AP_S1> And( - const ap_private<_AP_W, _AP_S1>& RHS) const { - return this->operator&(RHS); - } - template - INLINE ap_private Or(const ap_private<_AP_W, _AP_S1>& RHS) const { - return this->operator|(RHS); - } - template - INLINE ap_private Xor(const ap_private<_AP_W, _AP_S1>& RHS) const { - return this->operator^(RHS); - } - - INLINE ap_private Mul(const ap_private& RHS) const { - ap_private Result(*this); - Result *= RHS; - return Result; - } - - INLINE ap_private Add(const ap_private& RHS) const { - ap_private Result(0); - ap_private_ops::add(Result.get_pVal(), pVal, RHS.get_pVal(), _AP_N, _AP_N, - _AP_N, _AP_S, _AP_S); - Result.clearUnusedBits(); - return Result; - } - - INLINE ap_private Sub(const ap_private& RHS) const { - ap_private Result(0); - ap_private_ops::sub(Result.get_pVal(), pVal, RHS.get_pVal(), _AP_N, _AP_N, - _AP_N, _AP_S, _AP_S); - Result.clearUnusedBits(); - return Result; - } - - /// Arithmetic right-shift this ap_private by shiftAmt. - /// @brief Arithmetic right-shift function. - INLINE ap_private ashr(uint32_t shiftAmt) const { - assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); - // Handle a degenerate case - if (shiftAmt == 0) return ap_private(*this); - - // If all the bits were shifted out, the result is, technically, undefined. - // We return -1 if it was negative, 0 otherwise. We check this early to - // avoid - // issues in the algorithm below. - if (shiftAmt == BitWidth) { - if (isNegative()) - return ap_private(-1); - else - return ap_private(0); - } - - // Create some space for the result. - ap_private Retval(0); - uint64_t* val = Retval.get_pVal(); - - // Compute some values needed by the following shift algorithms - uint32_t wordShift = - shiftAmt % APINT_BITS_PER_WORD; // bits to shift per word - uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; // word offset for shift - uint32_t breakWord = _AP_N - 1 - offset; // last word affected - uint32_t bitsInWord = whichBit(BitWidth); // how many bits in last word? - if (bitsInWord == 0) bitsInWord = APINT_BITS_PER_WORD; - - // If we are shifting whole words, just move whole words - if (wordShift == 0) { - // Move the words containing significant bits - for (uint32_t i = 0; i <= breakWord; ++i) - val[i] = pVal[i + offset]; // move whole word - - // Adjust the top significant word for sign bit fill, if negative - if (isNegative()) - if (bitsInWord < APINT_BITS_PER_WORD) - val[breakWord] |= ~0ULL << (bitsInWord); // set high bits - } else { - // Shift the low order words - for (uint32_t i = 0; i < breakWord; ++i) { - // This combines the shifted corresponding word with the low bits from - // the next word (shifted into this word's high bits). - val[i] = ((pVal[i + offset]) >> (wordShift)); - val[i] |= ((pVal[i + offset + 1]) << (APINT_BITS_PER_WORD - wordShift)); - } - - // Shift the break word. In this case there are no bits from the next word - // to include in this word. - val[breakWord] = (pVal[breakWord + offset]) >> (wordShift); - - // Deal with sign extenstion in the break word, and possibly the word - // before - // it. - if (isNegative()) { - if (wordShift > bitsInWord) { - if (breakWord > 0) - val[breakWord - 1] |= - ~0ULL << (APINT_BITS_PER_WORD - (wordShift - bitsInWord)); - val[breakWord] |= ~0ULL; - } else - val[breakWord] |= (~0ULL << (bitsInWord - wordShift)); - } - } - - // Remaining words are 0 or -1, just assign them. - uint64_t fillValue = (isNegative() ? ~0ULL : 0); - for (int i = breakWord + 1; i < _AP_N; ++i) val[i] = fillValue; - Retval.clearUnusedBits(); - return Retval; - } - - /// Logical right-shift this ap_private by shiftAmt. - /// @brief Logical right-shift function. - INLINE ap_private lshr(uint32_t shiftAmt) const { - // If all the bits were shifted out, the result is 0. This avoids issues - // with shifting by the size of the integer type, which produces undefined - // results. We define these "undefined results" to always be 0. - if (shiftAmt == BitWidth) return ap_private(0); - - // If none of the bits are shifted out, the result is *this. This avoids - // issues with shifting byt he size of the integer type, which produces - // undefined results in the code below. This is also an optimization. - if (shiftAmt == 0) return ap_private(*this); - - // Create some space for the result. - ap_private Retval(0); - uint64_t* val = Retval.get_pVal(); - - // If we are shifting less than a word, compute the shift with a simple - // carry - if (shiftAmt < APINT_BITS_PER_WORD) { - uint64_t carry = 0; - for (int i = _AP_N - 1; i >= 0; --i) { - val[i] = ((pVal[i]) >> (shiftAmt)) | carry; - carry = (pVal[i]) << (APINT_BITS_PER_WORD - shiftAmt); - } - Retval.clearUnusedBits(); - return Retval; - } - - // Compute some values needed by the remaining shift algorithms - uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; - uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; - - // If we are shifting whole words, just move whole words - if (wordShift == 0) { - for (uint32_t i = 0; i < _AP_N - offset; ++i) val[i] = pVal[i + offset]; - for (uint32_t i = _AP_N - offset; i < _AP_N; i++) val[i] = 0; - Retval.clearUnusedBits(); - return Retval; - } - - // Shift the low order words - uint32_t breakWord = _AP_N - offset - 1; - for (uint32_t i = 0; i < breakWord; ++i) - val[i] = ((pVal[i + offset]) >> (wordShift)) | - ((pVal[i + offset + 1]) << (APINT_BITS_PER_WORD - wordShift)); - // Shift the break word. - val[breakWord] = (pVal[breakWord + offset]) >> (wordShift); - - // Remaining words are 0 - for (int i = breakWord + 1; i < _AP_N; ++i) val[i] = 0; - Retval.clearUnusedBits(); - return Retval; - } - - /// Left-shift this ap_private by shiftAmt. - /// @brief Left-shift function. - INLINE ap_private shl(uint32_t shiftAmt) const { - assert(shiftAmt <= BitWidth && "Invalid shift amount, too big"); - // If all the bits were shifted out, the result is 0. This avoids issues - // with shifting by the size of the integer type, which produces undefined - // results. We define these "undefined results" to always be 0. - if (shiftAmt == BitWidth) return ap_private(0); - - // If none of the bits are shifted out, the result is *this. This avoids a - // lshr by the words size in the loop below which can produce incorrect - // results. It also avoids the expensive computation below for a common - // case. - if (shiftAmt == 0) return ap_private(*this); - - // Create some space for the result. - ap_private Retval(0); - uint64_t* val = Retval.get_pVal(); - // If we are shifting less than a word, do it the easy way - if (shiftAmt < APINT_BITS_PER_WORD) { - uint64_t carry = 0; - for (int i = 0; i < _AP_N; i++) { - val[i] = ((pVal[i]) << (shiftAmt)) | carry; - carry = (pVal[i]) >> (APINT_BITS_PER_WORD - shiftAmt); - } - Retval.clearUnusedBits(); - return Retval; - } - - // Compute some values needed by the remaining shift algorithms - uint32_t wordShift = shiftAmt % APINT_BITS_PER_WORD; - uint32_t offset = shiftAmt / APINT_BITS_PER_WORD; - - // If we are shifting whole words, just move whole words - if (wordShift == 0) { - for (uint32_t i = 0; i < offset; i++) val[i] = 0; - for (int i = offset; i < _AP_N; i++) val[i] = pVal[i - offset]; - Retval.clearUnusedBits(); - return Retval; - } - - // Copy whole words from this to Result. - uint32_t i = _AP_N - 1; - for (; i > offset; --i) - val[i] = (pVal[i - offset]) << (wordShift) | - (pVal[i - offset - 1]) >> (APINT_BITS_PER_WORD - wordShift); - val[offset] = (pVal[0]) << (wordShift); - for (i = 0; i < offset; ++i) val[i] = 0; - Retval.clearUnusedBits(); - return Retval; - } - - INLINE ap_private rotl(uint32_t rotateAmt) const { - if (rotateAmt == 0) return ap_private(*this); - // Don't get too fancy, just use existing shift/or facilities - ap_private hi(*this); - ap_private lo(*this); - hi.shl(rotateAmt); - lo.lshr(BitWidth - rotateAmt); - return hi | lo; - } - - INLINE ap_private rotr(uint32_t rotateAmt) const { - if (rotateAmt == 0) return ap_private(*this); - // Don't get too fancy, just use existing shift/or facilities - ap_private hi(*this); - ap_private lo(*this); - lo.lshr(rotateAmt); - hi.shl(BitWidth - rotateAmt); - return hi | lo; - } - - /// Perform an unsigned divide operation on this ap_private by RHS. Both this - /// and - /// RHS are treated as unsigned quantities for purposes of this division. - /// @returns a new ap_private value containing the division result - /// @brief Unsigned division operation. - INLINE ap_private udiv(const ap_private& RHS) const { - // Get some facts about the LHS and RHS number of bits and words - uint32_t rhsBits = RHS.getActiveBits(); - uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); - assert(rhsWords && "Divided by zero???"); - uint32_t lhsBits = this->getActiveBits(); - uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); - - // Deal with some degenerate cases - if (!lhsWords) - // 0 / X ===> 0 - return ap_private(0); - else if (lhsWords < rhsWords || this->ult(RHS)) { - // X / Y ===> 0, iff X < Y - return ap_private(0); - } else if (*this == RHS) { - // X / X ===> 1 - return ap_private(1); - } else if (lhsWords == 1 && rhsWords == 1) { - // All high words are zero, just use native divide - return ap_private(this->pVal[0] / RHS.get_pVal(0)); - } - - // We have to compute it the hard way. Invoke the Knuth divide algorithm. - ap_private Quotient(0); // to hold result. - ap_private_ops::divide(*this, lhsWords, RHS, rhsWords, &Quotient, - (ap_private*)0); - return Quotient; - } - - /// Signed divide this ap_private by ap_private RHS. - /// @brief Signed division function for ap_private. - INLINE ap_private sdiv(const ap_private& RHS) const { - if (isNegative()) - if (RHS.isNegative()) - return (-(*this)).udiv(-RHS); - else - return -((-(*this)).udiv(RHS)); - else if (RHS.isNegative()) - return -(this->udiv((ap_private)(-RHS))); - return this->udiv(RHS); - } - - /// Perform an unsigned remainder operation on this ap_private with RHS being - /// the - /// divisor. Both this and RHS are treated as unsigned quantities for purposes - /// of this operation. Note that this is a true remainder operation and not - /// a modulo operation because the sign follows the sign of the dividend - /// which is *this. - /// @returns a new ap_private value containing the remainder result - /// @brief Unsigned remainder operation. - INLINE ap_private urem(const ap_private& RHS) const { - // Get some facts about the LHS - uint32_t lhsBits = getActiveBits(); - uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); - - // Get some facts about the RHS - uint32_t rhsBits = RHS.getActiveBits(); - uint32_t rhsWords = !rhsBits ? 0 : (whichWord(rhsBits - 1) + 1); - assert(rhsWords && "Performing remainder operation by zero ???"); - - // Check the degenerate cases - if (lhsWords == 0) { - // 0 % Y ===> 0 - return ap_private(0); - } else if (lhsWords < rhsWords || this->ult(RHS)) { - // X % Y ===> X, iff X < Y - return *this; - } else if (*this == RHS) { - // X % X == 0; - return ap_private(0); - } else if (lhsWords == 1) { - // All high words are zero, just use native remainder - return ap_private(pVal[0] % RHS.get_pVal(0)); - } - - // We have to compute it the hard way. Invoke the Knuth divide algorithm. - ap_private Remainder(0); - ap_private_ops::divide(*this, lhsWords, RHS, rhsWords, (ap_private*)(0), - &Remainder); - return Remainder; - } - - INLINE ap_private urem(uint64_t RHS) const { - // Get some facts about the LHS - uint32_t lhsBits = getActiveBits(); - uint32_t lhsWords = !lhsBits ? 0 : (whichWord(lhsBits - 1) + 1); - // Get some facts about the RHS - uint32_t rhsWords = 1; //! rhsBits ? 0 : (ap_private<_AP_W, - //! _AP_S>::whichWord(rhsBits - 1) + 1); - assert(rhsWords && "Performing remainder operation by zero ???"); - // Check the degenerate cases - if (lhsWords == 0) { - // 0 % Y ===> 0 - return ap_private(0); - } else if (lhsWords < rhsWords || this->ult(RHS)) { - // X % Y ===> X, iff X < Y - return *this; - } else if (*this == RHS) { - // X % X == 0; - return ap_private(0); - } else if (lhsWords == 1) { - // All high words are zero, just use native remainder - return ap_private(pVal[0] % RHS); - } - - // We have to compute it the hard way. Invoke the Knuth divide algorithm. - ap_private Remainder(0); - divide(*this, lhsWords, RHS, (ap_private*)(0), &Remainder); - return Remainder; - } - - /// Signed remainder operation on ap_private. - /// @brief Function for signed remainder operation. - INLINE ap_private srem(const ap_private& RHS) const { - if (isNegative()) { - ap_private lhs = -(*this); - if (RHS.isNegative()) { - ap_private rhs = -RHS; - return -(lhs.urem(rhs)); - } else - return -(lhs.urem(RHS)); - } else if (RHS.isNegative()) { - ap_private rhs = -RHS; - return this->urem(rhs); - } - return this->urem(RHS); - } - - /// Signed remainder operation on ap_private. - /// @brief Function for signed remainder operation. - INLINE ap_private srem(int64_t RHS) const { - if (isNegative()) - if (RHS < 0) - return -((-(*this)).urem(-RHS)); - else - return -((-(*this)).urem(RHS)); - else if (RHS < 0) - return this->urem(-RHS); - return this->urem(RHS); - } - - /// Compares this ap_private with RHS for the validity of the equality - /// relationship. - /// @returns true if *this == Val - /// @brief Equality comparison. - template - INLINE bool eq(const ap_private<_AP_W, _AP_S1>& RHS) const { - return (*this) == RHS; - } - - /// Compares this ap_private with RHS for the validity of the inequality - /// relationship. - /// @returns true if *this != Val - /// @brief Inequality comparison - template - INLINE bool ne(const ap_private<_AP_W, _AP_S1>& RHS) const { - return !((*this) == RHS); - } - - /// Regards both *this and RHS as unsigned quantities and compares them for - /// the validity of the less-than relationship. - /// @returns true if *this < RHS when both are considered unsigned. - /// @brief Unsigned less than comparison - template - INLINE bool ult(const ap_private<_AP_W, _AP_S1>& RHS) const { - // Get active bit length of both operands - uint32_t n1 = getActiveBits(); - uint32_t n2 = RHS.getActiveBits(); - - // If magnitude of LHS is less than RHS, return true. - if (n1 < n2) return true; - - // If magnitude of RHS is greather than LHS, return false. - if (n2 < n1) return false; - - // If they bot fit in a word, just compare the low order word - if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) - return pVal[0] < RHS.get_pVal(0); - - // Otherwise, compare all words - uint32_t topWord = whichWord(AESL_std::max(n1, n2) - 1); - for (int i = topWord; i >= 0; --i) { - if (pVal[i] > RHS.get_pVal(i)) return false; - if (pVal[i] < RHS.get_pVal(i)) return true; - } - return false; - } - - INLINE bool ult(uint64_t RHS) const { - // Get active bit length of both operands - uint32_t n1 = getActiveBits(); - uint32_t n2 = - 64 - ap_private_ops::CountLeadingZeros_64(RHS); // RHS.getActiveBits(); - - // If magnitude of LHS is less than RHS, return true. - if (n1 < n2) return true; - - // If magnitude of RHS is greather than LHS, return false. - if (n2 < n1) return false; - - // If they bot fit in a word, just compare the low order word - if (n1 <= APINT_BITS_PER_WORD && n2 <= APINT_BITS_PER_WORD) - return pVal[0] < RHS; - assert(0); - } - - template - INLINE bool slt(const ap_private<_AP_W, _AP_S1>& RHS) const { - ap_private lhs(*this); - ap_private<_AP_W, _AP_S1> rhs(RHS); - bool lhsNeg = isNegative(); - bool rhsNeg = rhs.isNegative(); - if (lhsNeg) { - // Sign bit is set so perform two's complement to make it positive - lhs.flip(); - lhs++; - } - if (rhsNeg) { - // Sign bit is set so perform two's complement to make it positive - rhs.flip(); - rhs++; - } - - // Now we have unsigned values to compare so do the comparison if necessary - // based on the negativeness of the values. - if (lhsNeg) - if (rhsNeg) - return lhs.ugt(rhs); - else - return true; - else if (rhsNeg) - return false; - else - return lhs.ult(rhs); - } - - /// Regards both *this and RHS as unsigned quantities and compares them for - /// validity of the less-or-equal relationship. - /// @returns true if *this <= RHS when both are considered unsigned. - /// @brief Unsigned less or equal comparison - template - INLINE bool ule(const ap_private<_AP_W, _AP_S1>& RHS) const { - return ult(RHS) || eq(RHS); - } - - /// Regards both *this and RHS as signed quantities and compares them for - /// validity of the less-or-equal relationship. - /// @returns true if *this <= RHS when both are considered signed. - /// @brief Signed less or equal comparison - template - INLINE bool sle(const ap_private<_AP_W, _AP_S1>& RHS) const { - return slt(RHS) || eq(RHS); - } - - /// Regards both *this and RHS as unsigned quantities and compares them for - /// the validity of the greater-than relationship. - /// @returns true if *this > RHS when both are considered unsigned. - /// @brief Unsigned greather than comparison - template - INLINE bool ugt(const ap_private<_AP_W, _AP_S1>& RHS) const { - return !ult(RHS) && !eq(RHS); - } - - /// Regards both *this and RHS as signed quantities and compares them for - /// the validity of the greater-than relationship. - /// @returns true if *this > RHS when both are considered signed. - /// @brief Signed greather than comparison - template - INLINE bool sgt(const ap_private<_AP_W, _AP_S1>& RHS) const { - return !slt(RHS) && !eq(RHS); - } - - /// Regards both *this and RHS as unsigned quantities and compares them for - /// validity of the greater-or-equal relationship. - /// @returns true if *this >= RHS when both are considered unsigned. - /// @brief Unsigned greater or equal comparison - template - INLINE bool uge(const ap_private<_AP_W, _AP_S>& RHS) const { - return !ult(RHS); - } - - /// Regards both *this and RHS as signed quantities and compares them for - /// validity of the greater-or-equal relationship. - /// @returns true if *this >= RHS when both are considered signed. - /// @brief Signed greather or equal comparison - template - INLINE bool sge(const ap_private<_AP_W, _AP_S1>& RHS) const { - return !slt(RHS); - } - - // Sign extend to a new width. - template - INLINE void cpSext(const ap_private<_AP_W1, _AP_S1>& that) { - assert(_AP_W1 < BitWidth && "Invalid ap_private SignExtend request"); - assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); - // If the sign bit isn't set, this is the same as zext. - if (!that.isNegative()) { - cpZext(that); - return; - } - - // The sign bit is set. First, get some facts - enum { wordBits = _AP_W1 % APINT_BITS_PER_WORD }; - const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N; - // Mask the high order word appropriately - if (_AP_N1 == _AP_N) { - enum { newWordBits = _AP_W % APINT_BITS_PER_WORD }; - // The extension is contained to the wordsBefore-1th word. - static const uint64_t mask = wordBits ? (~0ULL << (wordBits)) : 0ULL; - for (int i = 0; i < _AP_N; ++i) pVal[i] = that.get_pVal(i); - pVal[_AP_N - 1] |= mask; - return; - } - - enum { newWordBits = _AP_W % APINT_BITS_PER_WORD }; - // The extension is contained to the wordsBefore-1th word. - static const uint64_t mask = wordBits ? (~0ULL << (wordBits)) : 0ULL; - int i; - for (i = 0; i < _AP_N1; ++i) pVal[i] = that.get_pVal(i); - pVal[i - 1] |= mask; - for (; i < _AP_N - 1; i++) pVal[i] = ~0ULL; - pVal[i] = ~0ULL; - clearUnusedBits(); - return; - } - - // Zero extend to a new width. - template - INLINE void cpZext(const ap_private<_AP_W1, _AP_S1>& that) { - assert(_AP_W1 < BitWidth && "Invalid ap_private ZeroExtend request"); - assert(_AP_W1 <= MAX_INT_BITS && "Too many bits"); - const int _AP_N1 = ap_private<_AP_W1, _AP_S1>::_AP_N; - int i = 0; - for (; i < _AP_N1; ++i) pVal[i] = that.get_pVal(i); - for (; i < _AP_N; ++i) pVal[i] = 0; - clearUnusedBits(); - } - - template - INLINE void cpZextOrTrunc(const ap_private<_AP_W1, _AP_S1>& that) { - if (BitWidth > _AP_W1) - cpZext(that); - else { - for (int i = 0; i < _AP_N; ++i) pVal[i] = that.get_pVal(i); - clearUnusedBits(); - } - } - - template - INLINE void cpSextOrTrunc(const ap_private<_AP_W1, _AP_S1>& that) { - if (BitWidth > _AP_W1) - cpSext(that); - else { - for (int i = 0; i < _AP_N; ++i) pVal[i] = that.get_pVal(i); - clearUnusedBits(); - } - } - - /// @} - /// @name Value Characterization Functions - /// @{ - - /// @returns the total number of bits. - INLINE uint32_t getBitWidth() const { return BitWidth; } - - /// Here one word's bitwidth equals to that of uint64_t. - /// @returns the number of words to hold the integer value of this ap_private. - /// @brief Get the number of words. - INLINE uint32_t getNumWords() const { - return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; - } - - /// This function returns the number of active bits which is defined as the - /// bit width minus the number of leading zeros. This is used in several - /// computations to see how "wide" the value is. - /// @brief Compute the number of active bits in the value - INLINE uint32_t getActiveBits() const { - uint32_t bits = BitWidth - countLeadingZeros(); - return bits ? bits : 1; - } - - /// This method attempts to return the value of this ap_private as a zero - /// extended - /// uint64_t. The bitwidth must be <= 64 or the value must fit within a - /// uint64_t. Otherwise an assertion will result. - /// @brief Get zero extended value - INLINE uint64_t getZExtValue() const { - assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); - return *pVal; - } - - /// This method attempts to return the value of this ap_private as a sign - /// extended - /// int64_t. The bit width must be <= 64 or the value must fit within an - /// int64_t. Otherwise an assertion will result. - /// @brief Get sign extended value - INLINE int64_t getSExtValue() const { - assert(getActiveBits() <= 64 && "Too many bits for int64_t"); - return int64_t(pVal[0]); - } - - /// This method determines how many bits are required to hold the ap_private - /// equivalent of the string given by \p str of length \p slen. - /// @brief Get bits required for string value. - INLINE static uint32_t getBitsNeeded(const char* str, uint32_t slen, - uint8_t radix) { - assert(str != 0 && "Invalid value string"); - assert(slen > 0 && "Invalid string length"); - - // Each computation below needs to know if its negative - uint32_t isNegative = str[0] == '-'; - if (isNegative) { - slen--; - str++; - } - // For radixes of power-of-two values, the bits required is accurately and - // easily computed - if (radix == 2) return slen + isNegative; - if (radix == 8) return slen * 3 + isNegative; - if (radix == 16) return slen * 4 + isNegative; - - // Otherwise it must be radix == 10, the hard case - assert(radix == 10 && "Invalid radix"); - - // Convert to the actual binary value. - // ap_private<_AP_W, _AP_S> tmp(sufficient, str, slen, radix); - - // Compute how many bits are required. - // return isNegative + tmp.logBase2() + 1; - return isNegative + slen * 4; - } - - /// countLeadingZeros - This function is an ap_private version of the - /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number - /// of zeros from the most significant bit to the first one bit. - /// @returns BitWidth if the value is zero. - /// @returns the number of zeros from the most significant bit to the first - /// one bits. - INLINE uint32_t countLeadingZeros() const { - enum { - msw_bits = (BitWidth % APINT_BITS_PER_WORD) - ? (BitWidth % APINT_BITS_PER_WORD) - : APINT_BITS_PER_WORD, - excessBits = APINT_BITS_PER_WORD - msw_bits - }; - uint32_t Count = ap_private_ops::CountLeadingZeros_64(pVal[_AP_N - 1]); - if (Count >= excessBits) Count -= excessBits; - if (!pVal[_AP_N - 1]) { - for (int i = _AP_N - 1; i; --i) { - if (!pVal[i - 1]) - Count += APINT_BITS_PER_WORD; - else { - Count += ap_private_ops::CountLeadingZeros_64(pVal[i - 1]); - break; - } - } - } - return Count; - } - - /// countLeadingOnes - This function counts the number of contiguous 1 bits - /// in the high order bits. The count stops when the first 0 bit is reached. - /// @returns 0 if the high order bit is not set - /// @returns the number of 1 bits from the most significant to the least - /// @brief Count the number of leading one bits. - INLINE uint32_t countLeadingOnes() const { - if (isSingleWord()) - return countLeadingOnes_64(get_VAL(), APINT_BITS_PER_WORD - BitWidth); - - uint32_t highWordBits = BitWidth % APINT_BITS_PER_WORD; - uint32_t shift = - (highWordBits == 0 ? 0 : APINT_BITS_PER_WORD - highWordBits); - int i = _AP_N - 1; - uint32_t Count = countLeadingOnes_64(get_pVal(i), shift); - if (Count == highWordBits) { - for (i--; i >= 0; --i) { - if (get_pVal(i) == ~0ULL) - Count += APINT_BITS_PER_WORD; - else { - Count += countLeadingOnes_64(get_pVal(i), 0); - break; - } - } - } - return Count; - } - - /// countTrailingZeros - This function is an ap_private version of the - /// countTrailingZoers_{32,64} functions in MathExtras.h. It counts - /// the number of zeros from the least significant bit to the first set bit. - /// @returns BitWidth if the value is zero. - /// @returns the number of zeros from the least significant bit to the first - /// one bit. - /// @brief Count the number of trailing zero bits. - INLINE uint32_t countTrailingZeros() const { - uint32_t Count = 0; - uint32_t i = 0; - for (; i < _AP_N && get_pVal(i) == 0; ++i) Count += APINT_BITS_PER_WORD; - if (i < _AP_N) Count += ap_private_ops::CountTrailingZeros_64(get_pVal(i)); - return AESL_std::min(Count, BitWidth); - } - /// countPopulation - This function is an ap_private version of the - /// countPopulation_{32,64} functions in MathExtras.h. It counts the number - /// of 1 bits in the ap_private value. - /// @returns 0 if the value is zero. - /// @returns the number of set bits. - /// @brief Count the number of bits set. - INLINE uint32_t countPopulation() const { - uint32_t Count = 0; - for (int i = 0; i < _AP_N - 1; ++i) - Count += ap_private_ops::CountPopulation_64(pVal[i]); - Count += ap_private_ops::CountPopulation_64(pVal[_AP_N - 1] & mask); - return Count; - } - - /// @} - /// @name Conversion Functions - /// @ - - /// This is used internally to convert an ap_private to a string. - /// @brief Converts an ap_private to a std::string - INLINE std::string toString(uint8_t radix, bool wantSigned) const; - - /// Considers the ap_private to be unsigned and converts it into a string in - /// the - /// radix given. The radix can be 2, 8, 10 or 16. - /// @returns a character interpretation of the ap_private - /// @brief Convert unsigned ap_private to string representation. - INLINE std::string toStringUnsigned(uint8_t radix = 10) const { - return toString(radix, false); - } - - /// Considers the ap_private to be unsigned and converts it into a string in - /// the - /// radix given. The radix can be 2, 8, 10 or 16. - /// @returns a character interpretation of the ap_private - /// @brief Convert unsigned ap_private to string representation. - INLINE std::string toStringSigned(uint8_t radix = 10) const { - return toString(radix, true); - } - - /// @brief Converts this ap_private to a double value. - INLINE double roundToDouble(bool isSigned) const { - // Handle the simple case where the value is contained in one uint64_t. - if (isSingleWord() || getActiveBits() <= APINT_BITS_PER_WORD) { - uint64_t val = pVal[0]; - if (isSigned) { - int64_t sext = ((int64_t(val)) << (64 - BitWidth)) >> (64 - BitWidth); - return double(sext); - } else - return double(val); - } - - // Determine if the value is negative. - bool isNeg = isSigned ? (*this)[BitWidth - 1] : false; - - // Construct the absolute value if we're negative. - ap_private<_AP_W, _AP_S> Tmp(isNeg ? -(*this) : (*this)); - - // Figure out how many bits we're using. - uint32_t n = Tmp.getActiveBits(); - - // The exponent (without bias normalization) is just the number of bits - // we are using. Note that the sign bit is gone since we constructed the - // absolute value. - uint64_t exp = n; - - // Return infinity for exponent overflow - if (exp > 1023) { - if (!isSigned || !isNeg) - return std::numeric_limits::infinity(); - else - return -std::numeric_limits::infinity(); - } - exp += 1023; // Increment for 1023 bias - - // Number of bits in mantissa is 52. To obtain the mantissa value, we must - // extract the high 52 bits from the correct words in pVal. - uint64_t mantissa; - unsigned hiWord = whichWord(n - 1); - if (hiWord == 0) { - mantissa = Tmp.get_pVal(0); - if (n > 52) - (mantissa) >>= (n - 52); // shift down, we want the top 52 bits. - } else { - assert(hiWord > 0 && "High word is negative?"); - uint64_t hibits = (Tmp.get_pVal(hiWord)) - << (52 - n % APINT_BITS_PER_WORD); - uint64_t lobits = - (Tmp.get_pVal(hiWord - 1)) >> (11 + n % APINT_BITS_PER_WORD); - mantissa = hibits | lobits; - } - - // The leading bit of mantissa is implicit, so get rid of it. - uint64_t sign = isNeg ? (1ULL << (APINT_BITS_PER_WORD - 1)) : 0; - union { - double __D; - uint64_t __I; - } __T; - __T.__I = sign | ((exp) << 52) | mantissa; - return __T.__D; - } - - /// @brief Converts this unsigned ap_private to a double value. - INLINE double roundToDouble() const { return roundToDouble(false); } - - /// @brief Converts this signed ap_private to a double value. - INLINE double signedRoundToDouble() const { return roundToDouble(true); } - - /// The conversion does not do a translation from integer to double, it just - /// re-interprets the bits as a double. Note that it is valid to do this on - /// any bit width. Exactly 64 bits will be translated. - /// @brief Converts ap_private bits to a double - INLINE double bitsToDouble() const { - union { - uint64_t __I; - double __D; - } __T; - __T.__I = pVal[0]; - return __T.__D; - } - - /// The conversion does not do a translation from integer to float, it just - /// re-interprets the bits as a float. Note that it is valid to do this on - /// any bit width. Exactly 32 bits will be translated. - /// @brief Converts ap_private bits to a double - INLINE float bitsToFloat() const { - union { - uint32_t __I; - float __F; - } __T; - __T.__I = uint32_t(pVal[0]); - return __T.__F; - } - - /// The conversion does not do a translation from double to integer, it just - /// re-interprets the bits of the double. Note that it is valid to do this on - /// any bit width but bits from V may get truncated. - /// @brief Converts a double to ap_private bits. - INLINE ap_private& doubleToBits(double __V) { - union { - uint64_t __I; - double __D; - } __T; - __T.__D = __V; - pVal[0] = __T.__I; - return *this; - } - - /// The conversion does not do a translation from float to integer, it just - /// re-interprets the bits of the float. Note that it is valid to do this on - /// any bit width but bits from V may get truncated. - /// @brief Converts a float to ap_private bits. - INLINE ap_private& floatToBits(float __V) { - union { - uint32_t __I; - float __F; - } __T; - __T.__F = __V; - pVal[0] = __T.__I; - } - - // Reduce operation - //----------------------------------------------------------- - INLINE bool and_reduce() const { return isMaxValue(); } - - INLINE bool nand_reduce() const { return isMinValue(); } - - INLINE bool or_reduce() const { return (bool)countPopulation(); } - - INLINE bool nor_reduce() const { return countPopulation() == 0; } - - INLINE bool xor_reduce() const { - unsigned int i = countPopulation(); - return (i % 2) ? true : false; - } - - INLINE bool xnor_reduce() const { - unsigned int i = countPopulation(); - return (i % 2) ? false : true; - } - INLINE std::string to_string(uint8_t radix = 16, bool sign = false) const { - return toString(radix, radix == 10 ? _AP_S : sign); - } -}; // End of class ap_private <_AP_W, _AP_S, false> - -namespace ap_private_ops { - -enum { APINT_BITS_PER_WORD = 64 }; -template -INLINE bool operator==(uint64_t V1, const ap_private<_AP_W, _AP_S>& V2) { - return V2 == V1; -} - -template -INLINE bool operator!=(uint64_t V1, const ap_private<_AP_W, _AP_S>& V2) { - return V2 != V1; -} - -template -INLINE bool get(const ap_private<_AP_W, _AP_S>& a) { - static const uint64_t mask = 1ULL << (index & 0x3f); - return ((mask & a.get_pVal((index) >> 6)) != 0); -} - -template -INLINE void set(ap_private<_AP_W, _AP_S>& a, - const ap_private& mark1 = 0, - const ap_private& mark2 = 0) { - enum { - APINT_BITS_PER_WORD = 64, - lsb_word = lsb_index / APINT_BITS_PER_WORD, - msb_word = msb_index / APINT_BITS_PER_WORD, - msb = msb_index % APINT_BITS_PER_WORD, - lsb = lsb_index % APINT_BITS_PER_WORD - }; - if (msb_word == lsb_word) { - const uint64_t mask = ~0ULL >> - (lsb) << (APINT_BITS_PER_WORD - msb + lsb - 1) >> - (APINT_BITS_PER_WORD - msb - 1); - // a.set_pVal(msb_word, a.get_pVal(msb_word) | mask); - a.get_pVal(msb_word) |= mask; - } else { - const uint64_t lsb_mask = ~0ULL >> (lsb) << (lsb); - const uint64_t msb_mask = ~0ULL << (APINT_BITS_PER_WORD - msb - 1) >> - (APINT_BITS_PER_WORD - msb - 1); - // a.set_pVal(lsb_word, a.get_pVal(lsb_word) | lsb_mask); - a.get_pVal(lsb_word) |= lsb_mask; - for (int i = lsb_word + 1; i < msb_word; i++) { - a.set_pVal(i, ~0ULL); - // a.get_pVal(i)=0; - } - // a.set_pVal(msb_word, a.get_pVal(msb_word) | msb_mask); - - a.get_pVal(msb_word) |= msb_mask; - } - a.clearUnusedBits(); -} - -template -INLINE void clear(ap_private<_AP_W, _AP_S>& a, - const ap_private& mark1 = 0, - const ap_private& mark2 = 0) { - enum { - APINT_BITS_PER_WORD = 64, - lsb_word = lsb_index / APINT_BITS_PER_WORD, - msb_word = msb_index / APINT_BITS_PER_WORD, - msb = msb_index % APINT_BITS_PER_WORD, - lsb = lsb_index % APINT_BITS_PER_WORD - }; - if (msb_word == lsb_word) { - const uint64_t mask = - ~(~0ULL >> (lsb) << (APINT_BITS_PER_WORD - msb + lsb - 1) >> - (APINT_BITS_PER_WORD - msb - 1)); - // a.set_pVal(msb_word, a.get_pVal(msb_word) & mask); - a.get_pVal(msb_word) &= mask; - } else { - const uint64_t lsb_mask = ~(~0ULL >> (lsb) << (lsb)); - const uint64_t msb_mask = ~(~0ULL << (APINT_BITS_PER_WORD - msb - 1) >> - (APINT_BITS_PER_WORD - msb - 1)); - // a.set_pVal(lsb_word, a.get_pVal(lsb_word) & lsb_mask); - a.get_pVal(lsb_word) &= lsb_mask; - for (int i = lsb_word + 1; i < msb_word; i++) { - // a.set_pVal(i, 0); - a.get_pVal(i) = 0; - } - // a.set_pVal(msb_word, a.get_pVal(msb_word) & msb_mask); - a.get_pVal(msb_word) &= msb_mask; - } - a.clearUnusedBits(); -} - -template -INLINE void set(ap_private<_AP_W, _AP_S>& a, - const ap_private& mark = 0) { - enum { APINT_BITS_PER_WORD = 64, word = index / APINT_BITS_PER_WORD }; - static const uint64_t mask = 1ULL << (index % APINT_BITS_PER_WORD); - // a.set_pVal(word, a.get_pVal(word) | mask); - a.get_pVal(word) |= mask; - a.clearUnusedBits(); -} - -template -INLINE void clear(ap_private<_AP_W, _AP_S>& a, - const ap_private& mark = 0) { - enum { APINT_BITS_PER_WORD = 64, word = index / APINT_BITS_PER_WORD }; - static const uint64_t mask = ~(1ULL << (index % APINT_BITS_PER_WORD)); - // a.set_pVal(word, a.get_pVal(word) & mask); - a.get_pVal(word) &= mask; - a.clearUnusedBits(); -} - -} // End of ap_private_ops namespace - -template -INLINE std::string ap_private<_AP_W, _AP_S, false>::toString( - uint8_t radix, bool wantSigned) const { - assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) && - "Radix should be 2, 8, 10, or 16!"); - static const char* digits[] = {"0", "1", "2", "3", "4", "5", "6", "7", - "8", "9", "A", "B", "C", "D", "E", "F"}; - std::string result; - - if (radix != 10) { - // For the 2, 8 and 16 bit cases, we can just shift instead of divide - // because the number of bits per digit (1,3 and 4 respectively) divides - // equaly. We just shift until there value is zero. - - // First, check for a zero value and just short circuit the logic below. - if (*this == (uint64_t)(0)) - result = "0"; - else { - ap_private<_AP_W, false> tmp(*this); - size_t insert_at = 0; - bool leading_zero = true; - if (wantSigned && isNegative()) { - // They want to print the signed version and it is a negative value - // Flip the bits and add one to turn it into the equivalent positive - // value and put a '-' in the result. - tmp.flip(); - tmp++; - tmp.clearUnusedBitsToZero(); - result = "-"; - insert_at = 1; - leading_zero = false; - } - switch (radix) { - case 2: - result += "0b"; - break; - case 8: - result += "0o"; - break; - case 16: - result += "0x"; - break; - default: - assert("invalid radix" && 0); - } - insert_at += 2; - // Just shift tmp right for each digit width until it becomes zero - uint32_t shift = (radix == 16 ? 4 : (radix == 8 ? 3 : 1)); - uint64_t mask = radix - 1; - ap_private<_AP_W, false> zero(0); - unsigned bits = 0; - while (tmp.ne(zero)) { - uint64_t digit = tmp.get_VAL() & mask; - result.insert(insert_at, digits[digit]); - tmp = tmp.lshr(shift); - ++bits; - } - bits *= shift; - if (bits < _AP_W && leading_zero) result.insert(insert_at, digits[0]); - } - return result; - } - - ap_private<_AP_W, false> tmp(*this); - ap_private<_AP_W, false> divisor(radix); - ap_private<_AP_W, false> zero(0); - size_t insert_at = 0; - if (wantSigned && isNegative()) { - // They want to print the signed version and it is a negative value - // Flip the bits and add one to turn it into the equivalent positive - // value and put a '-' in the result. - tmp.flip(); - tmp++; - tmp.clearUnusedBitsToZero(); - result = "-"; - insert_at = 1; - } - if (tmp == ap_private<_AP_W, false>(0)) - result = "0"; - else - while (tmp.ne(zero)) { - ap_private<_AP_W, false> APdigit(0); - ap_private<_AP_W, false> tmp2(0); - ap_private_ops::divide(tmp, tmp.getNumWords(), divisor, - divisor.getNumWords(), &tmp2, &APdigit); - uint64_t digit = APdigit.getZExtValue(); - assert(digit < radix && "divide failed"); - result.insert(insert_at, digits[digit]); - tmp = tmp2; - } - - return result; -} // End of ap_private<_AP_W, _AP_S, false>::toString() - -template -std::ostream &operator<<(std::ostream &os, const ap_private<_AP_W, _AP_S> &x) { - std::ios_base::fmtflags ff = std::cout.flags(); - if (ff & std::cout.hex) { - os << x.toString(16, false); // don't print sign - } else if (ff & std::cout.oct) { - os << x.toString(8, false); // don't print sign - } else { - os << x.toString(10, _AP_S); - } - return os; -} - -// ------------------------------------------------------------ // -// XXX moved here from ap_int_sim.h XXX // -// ------------------------------------------------------------ // - -/// Concatination reference. -/// Proxy class which allows concatination to be used as rvalue(for reading) and -/// lvalue(for writing) -// ---------------------------------------------------------------- -// template -// struct ap_concat_ref { -//#ifdef _MSC_VER -//#pragma warning(disable : 4521 4522) -//#endif -// enum { -// _AP_WR = _AP_W1 + _AP_W2, -// }; -// _AP_T1& mbv1; -// _AP_T2& mbv2; -// -// INLINE ap_concat_ref(const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& -// ref) -// : mbv1(ref.mbv1), mbv2(ref.mbv2) {} -// -// INLINE ap_concat_ref(_AP_T1& bv1, _AP_T2& bv2) : mbv1(bv1), mbv2(bv2) {} -// -// template -// INLINE ap_concat_ref& operator=(const ap_private<_AP_W3, _AP_S3>& val) { -// ap_private<_AP_W1 + _AP_W2, false> vval(val); -// int W_ref1 = mbv1.length(); -// int W_ref2 = mbv2.length(); -// ap_private<_AP_W1, false> mask1(-1); -// mask1 >>= _AP_W1 - W_ref1; -// ap_private<_AP_W2, false> mask2(-1); -// mask2 >>= _AP_W2 - W_ref2; -// mbv1.set(ap_private<_AP_W1, false>((vval >> W_ref2) & mask1)); -// mbv2.set(ap_private<_AP_W2, false>(vval & mask2)); -// return *this; -// } -// -// INLINE ap_concat_ref& operator=(unsigned long long val) { -// ap_private<_AP_W1 + _AP_W2, false> tmpVal(val); -// return operator=(tmpVal); -// } -// -// template -// INLINE ap_concat_ref& operator=( -// const ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { -// ap_private<_AP_W1 + _AP_W2, false> tmpVal(val); -// return operator=(tmpVal); -// } -// -// INLINE ap_concat_ref& operator=( -// const ap_concat_ref<_AP_W1, _AP_T1, _AP_W2, _AP_T2>& val) { -// ap_private<_AP_W1 + _AP_W2, false> tmpVal(val); -// return operator=(tmpVal); -// } -// -// template -// INLINE ap_concat_ref& operator=(const _private_bit_ref<_AP_W3, _AP_S3>& -// val) { -// ap_private<_AP_W1 + _AP_W2, false> tmpVal(val); -// return operator=(tmpVal); -// } -// -// template -// INLINE ap_concat_ref& operator=(const _private_range_ref<_AP_W3, _AP_S3>& -// val) { -// ap_private<_AP_W1 + _AP_W2, false> tmpVal(val); -// return operator=(tmpVal); -// } -// -// template -// INLINE ap_concat_ref& operator=( -// const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>& val) -// { -// return operator=((const ap_private<_AP_W3, false>)(val)); -// } -// -// template -// INLINE ap_concat_ref& operator=( -// const ap_fixed_base<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>& -// val) { -// return operator=(val.to_ap_private()); -// } -// -// template -// INLINE ap_concat_ref& operator=( -// const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3>& val) { -// return operator=((unsigned long long)(bool)(val)); -// } -// -// INLINE operator ap_private<_AP_WR, false>() const { return get(); } -// -// INLINE operator unsigned long long() const { return get().to_uint64(); } -// -// template -// INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, -// _private_range_ref<_AP_W3, _AP_S3> > -// operator,(const _private_range_ref<_AP_W3, _AP_S3> &a2) { -// return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, -// _private_range_ref<_AP_W3, _AP_S3> >( -// *this, const_cast<_private_range_ref<_AP_W3, _AP_S3>&>(a2)); -// } -// -// template -// INLINE -// ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> -// > -// operator,(ap_private<_AP_W3, _AP_S3> &a2) { -// return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, -// ap_private<_AP_W3, _AP_S3> >(*this, a2); -// } -// -// template -// INLINE -// ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, ap_private<_AP_W3, _AP_S3> -// > -// operator,(const ap_private<_AP_W3, _AP_S3> &a2) { -// return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3, -// ap_private<_AP_W3, _AP_S3> >( -// *this, const_cast&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_WR, ap_concat_ref, 1, _private_bit_ref<_AP_W3, -// _AP_S3> > -// operator,(const _private_bit_ref<_AP_W3, _AP_S3> &a2) { -// return ap_concat_ref<_AP_WR, ap_concat_ref, 1, _private_bit_ref<_AP_W3, -// _AP_S3> >( -// *this, const_cast<_private_bit_ref<_AP_W3, _AP_S3>&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3 + _AP_W4, -// ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4> > -// operator,(const ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4> &a2) { -// return ap_concat_ref<_AP_WR, ap_concat_ref, _AP_W3 + _AP_W4, -// ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4> >( -// *this, const_cast&>(a2)); -// } -// -// template -// INLINE ap_concat_ref< -// _AP_WR, ap_concat_ref, _AP_W3, -// af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> > -// operator,( -// const af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> &a2) -// { -// return ap_concat_ref< -// _AP_WR, ap_concat_ref, _AP_W3, -// af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >( -// *this, -// const_cast< -// af_range_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, -// _AP_N3>&>(a2)); -// } -// -// template -// INLINE -// ap_concat_ref<_AP_WR, ap_concat_ref, 1, -// af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> -// > -// operator,(const af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, -// _AP_N3> -// &a2) { -// return ap_concat_ref< -// _AP_WR, ap_concat_ref, 1, -// af_bit_ref<_AP_W3, _AP_I3, _AP_S3, _AP_Q3, _AP_O3, _AP_N3> >( -// *this, -// const_cast&>( -// a2)); -// } -// -// template -// INLINE ap_private operator&( -// const ap_private<_AP_W3, _AP_S3>& a2) { -// return get() & a2; -// } -// -// template -// INLINE ap_private operator|( -// const ap_private<_AP_W3, _AP_S3>& a2) { -// return get() | a2; -// } -// -// template -// INLINE ap_private operator^( -// const ap_private<_AP_W3, _AP_S3>& a2) { -// return ap_private(get() ^ a2); -// } -// -// INLINE const ap_private<_AP_WR, false> get() const { -// ap_private<_AP_W1 + _AP_W2, false> tmpVal = -// ap_private<_AP_W1 + _AP_W2, false>(mbv1.get()); -// ap_private<_AP_W1 + _AP_W2, false> tmpVal2 = -// ap_private<_AP_W1 + _AP_W2, false>(mbv2.get()); -// int W_ref2 = mbv2.length(); -// tmpVal <<= W_ref2; -// tmpVal |= tmpVal2; -// return tmpVal; -// } -// -// INLINE const ap_private<_AP_WR, false> get() { -// ap_private<_AP_W1 + _AP_W2, false> tmpVal = -// ap_private<_AP_W1 + _AP_W2, false>(mbv1.get()); -// ap_private<_AP_W1 + _AP_W2, false> tmpVal2 = -// ap_private<_AP_W1 + _AP_W2, false>(mbv2.get()); -// int W_ref2 = mbv2.length(); -// tmpVal <<= W_ref2; -// tmpVal |= tmpVal2; -// return tmpVal; -// } -// -// template -// INLINE void set(const ap_private<_AP_W3, false>& val) { -// ap_private<_AP_W1 + _AP_W2, false> vval(val); -// int W_ref1 = mbv1.length(); -// int W_ref2 = mbv2.length(); -// ap_private<_AP_W1, false> mask1(-1); -// mask1 >>= _AP_W1 - W_ref1; -// ap_private<_AP_W2, false> mask2(-1); -// mask2 >>= _AP_W2 - W_ref2; -// mbv1.set(ap_private<_AP_W1, false>((vval >> W_ref2) & mask1)); -// mbv2.set(ap_private<_AP_W2, false>(vval & mask2)); -// } -// -// INLINE int length() const { return mbv1.length() + mbv2.length(); } -// -// INLINE std::string to_string(uint8_t radix = 2) const { -// return get().to_string(radix); -// } -//}; // struct ap_concat_ref. - -/// Range(slice) reference -/// Proxy class, which allows part selection to be used as rvalue(for reading) -/// and lvalue(for writing) -//------------------------------------------------------------ -template -struct _private_range_ref { -#ifdef _MSC_VER -#pragma warning(disable : 4521 4522) -#endif - ap_private<_AP_W, _AP_S>& d_bv; - int l_index; - int h_index; - - public: - /// copy ctor. - INLINE _private_range_ref(const _private_range_ref<_AP_W, _AP_S>& ref) - : d_bv(ref.d_bv), l_index(ref.l_index), h_index(ref.h_index) {} - - /// direct ctor. - INLINE _private_range_ref(ap_private<_AP_W, _AP_S>* bv, int h, int l) - : d_bv(*bv), l_index(l), h_index(h) { - _AP_WARNING(h < 0 || l < 0, - "Higher bound (%d) and lower bound (%d) cannot be " - "negative.", - h, l); - _AP_WARNING(h >= _AP_W || l >= _AP_W, - "Higher bound (%d) or lower bound (%d) out of range (%d).", h, l, - _AP_W); - } - - /// compound or assignment. - template - INLINE _private_range_ref<_AP_W, _AP_S>& operator|=( - const _private_range_ref<_AP_W2, _AP_S2>& ref) { - _AP_WARNING((h_index - l_index) != (ref.h_index - ref.l_index), - "Bitsize mismach for ap_private<>.range() &= " - "ap_private<>.range()."); - this->d_bv |= ref.d_bv; - return *this; - } - - /// compound or assignment with root type. - template - INLINE _private_range_ref<_AP_W, _AP_S>& operator|=( - const _AP_ROOT_TYPE<_AP_W2, _AP_S2>& ref) { - _AP_WARNING((h_index - l_index + 1) != _AP_W2, - "Bitsize mismach for ap_private<>.range() |= _AP_ROOT_TYPE<>."); - this->d_bv |= ref.V; - return *this; - } - - /// compound and assignment. - template - INLINE _private_range_ref<_AP_W, _AP_S>& operator&=( - const _private_range_ref<_AP_W2, _AP_S2>& ref) { - _AP_WARNING((h_index - l_index) != (ref.h_index - ref.l_index), - "Bitsize mismach for ap_private<>.range() &= " - "ap_private<>.range()."); - this->d_bv &= ref.d_bv; - return *this; - }; - - /// compound and assignment with root type. - template - INLINE _private_range_ref<_AP_W, _AP_S>& operator&=( - const _AP_ROOT_TYPE<_AP_W2, _AP_S2>& ref) { - _AP_WARNING((h_index - l_index + 1) != _AP_W2, - "Bitsize mismach for ap_private<>.range() &= _AP_ROOT_TYPE<>."); - this->d_bv &= ref.V; - return *this; - } - - /// compound xor assignment. - template - INLINE _private_range_ref<_AP_W, _AP_S>& operator^=( - const _private_range_ref<_AP_W2, _AP_S2>& ref) { - _AP_WARNING((h_index - l_index) != (ref.h_index - ref.l_index), - "Bitsize mismach for ap_private<>.range() ^= " - "ap_private<>.range()."); - this->d_bv ^= ref.d_bv; - return *this; - }; - - /// compound xor assignment with root type. - template - INLINE _private_range_ref<_AP_W, _AP_S>& operator^=( - const _AP_ROOT_TYPE<_AP_W2, _AP_S2>& ref) { - _AP_WARNING((h_index - l_index + 1) != _AP_W2, - "Bitsize mismach for ap_private<>.range() ^= _AP_ROOT_TYPE<>."); - this->d_bv ^= ref.V; - return *this; - } - - /// @name convertors. - // @{ - INLINE operator ap_private<_AP_W, false>() const { - ap_private<_AP_W, false> val(0); - if (h_index >= l_index) { - if (_AP_W > 64) { - val = d_bv; - ap_private<_AP_W, false> mask(-1); - mask >>= _AP_W - (h_index - l_index + 1); - val >>= l_index; - val &= mask; - } else { - const static uint64_t mask = (~0ULL >> (64 > _AP_W ? (64 - _AP_W) : 0)); - val = (d_bv >> l_index) & (mask >> (_AP_W - (h_index - l_index + 1))); - } - } else { - for (int i = 0, j = l_index; j >= 0 && j >= h_index; j--, i++) - if ((d_bv)[j]) val.set(i); - } - return val; - } - - INLINE operator unsigned long long() const { return to_uint64(); } - // @} - - template - INLINE _private_range_ref& operator=(const ap_private<_AP_W2, _AP_S2>& val) { - ap_private<_AP_W, false> vval = ap_private<_AP_W, false>(val); - if (l_index > h_index) { - for (int i = 0, j = l_index; j >= 0 && j >= h_index; j--, i++) - (vval)[i] ? d_bv.set(j) : d_bv.clear(j); - } else { - if (_AP_W > 64) { - ap_private<_AP_W, false> mask(-1); - if (l_index > 0) { - mask <<= l_index; - vval <<= l_index; - } - if (h_index < _AP_W - 1) { - ap_private<_AP_W, false> mask2(-1); - mask2 >>= _AP_W - h_index - 1; - mask &= mask2; - vval &= mask2; - } - mask.flip(); - d_bv &= mask; - d_bv |= vval; - } else { - unsigned shift = 64 - _AP_W; - uint64_t mask = ~0ULL >> (shift); - if (l_index > 0) { - vval = mask & vval << l_index; - mask = mask & mask << l_index; - } - if (h_index < _AP_W - 1) { - uint64_t mask2 = mask; - mask2 >>= (_AP_W - h_index - 1); - mask &= mask2; - vval &= mask2; - } - mask = ~mask; - d_bv &= mask; - d_bv |= vval; - } - } - return *this; - } // operator=(const ap_private<>&) - - INLINE _private_range_ref& operator=(unsigned long long val) { - const ap_private<_AP_W, _AP_S> vval = val; - return operator=(vval); - } - - template - INLINE _private_range_ref& operator=( - const _private_bit_ref<_AP_W2, _AP_S2>& val) { - return operator=((unsigned long long)(bool)val); - } - - template - INLINE _private_range_ref& operator=( - const _private_range_ref<_AP_W2, _AP_S2>& val) { - const ap_private<_AP_W, false> tmpVal(val); - return operator=(tmpVal); - } - -// template -// INLINE _private_range_ref& operator=( -// const ap_concat_ref<_AP_W3, _AP_T3, _AP_W4, _AP_T4>& val) { -// const ap_private<_AP_W, false> tmpVal(val); -// return operator=(tmpVal); -// } - - // TODO from ap_int_base, ap_bit_ref and ap_range_ref. - - template - INLINE _private_range_ref& operator=( - const ap_fixed_base<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - return operator=(val.to_ap_int_base().V); - } - - template - INLINE _private_range_ref& operator=( - const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - return operator=(val.operator ap_int_base<_AP_W2, false>().V); - } - - template - INLINE _private_range_ref& operator=( - const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>& val) { - return operator=((unsigned long long)(bool)val); - } - -// template -// INLINE ap_concat_ref<_AP_W, _private_range_ref, _AP_W2, -// _private_range_ref<_AP_W2, _AP_S2> > -// operator,(const _private_range_ref<_AP_W2, _AP_S2> &a2) { -// return ap_concat_ref<_AP_W, _private_range_ref, _AP_W2, -// _private_range_ref<_AP_W2, _AP_S2> >( -// *this, const_cast<_private_range_ref<_AP_W2, _AP_S2>&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, _private_range_ref, _AP_W2, -// ap_private<_AP_W2, _AP_S2> > -// operator,(ap_private<_AP_W2, _AP_S2> &a2) { -// return ap_concat_ref<_AP_W, _private_range_ref, _AP_W2, -// ap_private<_AP_W2, _AP_S2> >(*this, a2); -// } -// -// INLINE -// ap_concat_ref<_AP_W, _private_range_ref, _AP_W, ap_private<_AP_W, _AP_S> > -// operator,(ap_private<_AP_W, _AP_S>& a2) { -// return ap_concat_ref<_AP_W, _private_range_ref, _AP_W, -// ap_private<_AP_W, _AP_S> >(*this, a2); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, _private_range_ref, 1, -// _private_bit_ref<_AP_W2, _AP_S2> > -// operator,(const _private_bit_ref<_AP_W2, _AP_S2> &a2) { -// return ap_concat_ref<_AP_W, _private_range_ref, 1, -// _private_bit_ref<_AP_W2, _AP_S2> >( -// *this, const_cast<_private_bit_ref<_AP_W2, _AP_S2>&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<_AP_W, _private_range_ref, _AP_W2 + _AP_W3, -// ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > -// operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) { -// return ap_concat_ref<_AP_W, _private_range_ref, _AP_W2 + _AP_W3, -// ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >( -// *this, const_cast&>(a2)); -// } -// -// template -// INLINE ap_concat_ref< -// _AP_W, _private_range_ref, _AP_W2, -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > -// operator,( -// const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> &a2) { -// return ap_concat_ref< -// _AP_W, _private_range_ref, _AP_W2, -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( -// *this, -// const_cast< -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2>&>(a2)); -// } -// -// template -// INLINE -// ap_concat_ref<_AP_W, _private_range_ref, 1, -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > -// operator,(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> -// &a2) { -// return ap_concat_ref< -// _AP_W, _private_range_ref, 1, -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( -// *this, -// const_cast&>( -// a2)); -// } - - template - INLINE bool operator==(const _private_range_ref<_AP_W2, _AP_S2>& op2) { - ap_private<_AP_W, false> lhs = get(); - ap_private<_AP_W2, false> rhs = op2.get(); - return lhs == rhs; - } - - template - INLINE bool operator!=(const _private_range_ref<_AP_W2, _AP_S2>& op2) { - ap_private<_AP_W, false> lhs = get(); - ap_private<_AP_W2, false> rhs = op2.get(); - return lhs != rhs; - } - - template - INLINE bool operator>(const _private_range_ref<_AP_W2, _AP_S2>& op2) { - ap_private<_AP_W, false> lhs = get(); - ap_private<_AP_W2, false> rhs = op2.get(); - return lhs > rhs; - } - - template - INLINE bool operator>=(const _private_range_ref<_AP_W2, _AP_S2>& op2) { - ap_private<_AP_W, false> lhs = get(); - ap_private<_AP_W2, false> rhs = op2.get(); - return lhs >= rhs; - } - - template - INLINE bool operator<(const _private_range_ref<_AP_W2, _AP_S2>& op2) { - ap_private<_AP_W, false> lhs = get(); - ap_private<_AP_W2, false> rhs = op2.get(); - return lhs < rhs; - } - - template - INLINE bool operator<=(const _private_range_ref<_AP_W2, _AP_S2>& op2) { - ap_private<_AP_W, false> lhs = get(); - ap_private<_AP_W2, false> rhs = op2.get(); - return lhs <= rhs; - } - - template - INLINE void set(const ap_private<_AP_W2, false>& val) { - ap_private<_AP_W, _AP_S> vval = val; - if (l_index > h_index) { - for (int i = 0, j = l_index; j >= 0 && j >= h_index; j--, i++) - (vval)[i] ? d_bv.set(j) : d_bv.clear(j); - } else { - if (_AP_W > 64) { - ap_private<_AP_W, _AP_S> mask(-1); - if (l_index > 0) { - ap_private<_AP_W, false> mask1(-1); - mask1 >>= _AP_W - l_index; - mask1.flip(); - mask = mask1; - // vval&=mask1; - vval <<= l_index; - } - if (h_index < _AP_W - 1) { - ap_private<_AP_W, false> mask2(-1); - mask2 <<= h_index + 1; - mask2.flip(); - mask &= mask2; - vval &= mask2; - } - mask.flip(); - d_bv &= mask; - d_bv |= vval; - } else { - uint64_t mask = ~0ULL >> (64 - _AP_W); - if (l_index > 0) { - uint64_t mask1 = mask; - mask1 = mask & (mask1 >> (_AP_W - l_index)); - vval = mask & (vval << l_index); - mask = ~mask1 & mask; - // vval&=mask1; - } - if (h_index < _AP_W - 1) { - uint64_t mask2 = ~0ULL >> (64 - _AP_W); - mask2 = mask & (mask2 << (h_index + 1)); - mask &= ~mask2; - vval &= ~mask2; - } - d_bv &= (~mask & (~0ULL >> (64 - _AP_W))); - d_bv |= vval; - } - } - } - - INLINE ap_private<_AP_W, false> get() const { - ap_private<_AP_W, false> val(0); - if (h_index < l_index) { - for (int i = 0, j = l_index; j >= 0 && j >= h_index; j--, i++) - if ((d_bv)[j]) val.set(i); - } else { - val = d_bv; - val >>= l_index; - if (h_index < _AP_W - 1) { - if (_AP_W <= 64) { - const static uint64_t mask = - (~0ULL >> (64 > _AP_W ? (64 - _AP_W) : 0)); - val &= (mask >> (_AP_W - (h_index - l_index + 1))); - } else { - ap_private<_AP_W, false> mask(-1); - mask >>= _AP_W - (h_index - l_index + 1); - val &= mask; - } - } - } - return val; - } - - INLINE ap_private<_AP_W, false> get() { - ap_private<_AP_W, false> val(0); - if (h_index < l_index) { - for (int i = 0, j = l_index; j >= 0 && j >= h_index; j--, i++) - if ((d_bv)[j]) val.set(i); - } else { - val = d_bv; - val >>= l_index; - if (h_index < _AP_W - 1) { - if (_AP_W <= 64) { - static const uint64_t mask = ~0ULL >> (64 > _AP_W ? (64 - _AP_W) : 0); - return val &= ((mask) >> (_AP_W - (h_index - l_index + 1))); - } else { - ap_private<_AP_W, false> mask(-1); - mask >>= _AP_W - (h_index - l_index + 1); - val &= mask; - } - } - } - return val; - } - - INLINE int length() const { - return h_index >= l_index ? h_index - l_index + 1 : l_index - h_index + 1; - } - - INLINE int to_int() const { - ap_private<_AP_W, false> val = get(); - return val.to_int(); - } - - INLINE unsigned int to_uint() const { - ap_private<_AP_W, false> val = get(); - return val.to_uint(); - } - - INLINE long to_long() const { - ap_private<_AP_W, false> val = get(); - return val.to_long(); - } - - INLINE unsigned long to_ulong() const { - ap_private<_AP_W, false> val = get(); - return val.to_ulong(); - } - - INLINE ap_slong to_int64() const { - ap_private<_AP_W, false> val = get(); - return val.to_int64(); - } - - INLINE ap_ulong to_uint64() const { - ap_private<_AP_W, false> val = get(); - return val.to_uint64(); - } - - INLINE std::string to_string(uint8_t radix = 2) const { - return get().to_string(radix); - } - - INLINE bool and_reduce() { - bool ret = true; - bool reverse = l_index > h_index; - unsigned low = reverse ? h_index : l_index; - unsigned high = reverse ? l_index : h_index; - for (unsigned i = low; i != high; ++i) ret &= d_bv[i]; - return ret; - } - - INLINE bool or_reduce() { - bool ret = false; - bool reverse = l_index > h_index; - unsigned low = reverse ? h_index : l_index; - unsigned high = reverse ? l_index : h_index; - for (unsigned i = low; i != high; ++i) ret |= d_bv[i]; - return ret; - } - - INLINE bool xor_reduce() { - bool ret = false; - bool reverse = l_index > h_index; - unsigned low = reverse ? h_index : l_index; - unsigned high = reverse ? l_index : h_index; - for (unsigned i = low; i != high; ++i) ret ^= d_bv[i]; - return ret; - } -}; // struct _private_range_ref. - -/// Bit reference -/// Proxy class, which allows bit selection to be used as rvalue(for reading) -/// and lvalue(for writing) -//-------------------------------------------------------------- -template -struct _private_bit_ref { -#ifdef _MSC_VER -#pragma warning(disable : 4521 4522) -#endif - ap_private<_AP_W, _AP_S>& d_bv; - int d_index; - - public: - // copy ctor. - INLINE _private_bit_ref(const _private_bit_ref<_AP_W, _AP_S>& ref) - : d_bv(ref.d_bv), d_index(ref.d_index) {} - - // director ctor. - INLINE _private_bit_ref(ap_private<_AP_W, _AP_S>& bv, int index = 0) - : d_bv(bv), d_index(index) { - _AP_WARNING(d_index < 0, "Index of bit vector (%d) cannot be negative.\n", - d_index); - _AP_WARNING(d_index >= _AP_W, - "Index of bit vector (%d) out of range (%d).\n", d_index, _AP_W); - } - - INLINE operator bool() const { return d_bv.get_bit(d_index); } - - INLINE bool to_bool() const { return operator bool(); } - - template - INLINE _private_bit_ref& operator=(const T& val) { - if (!!val) - d_bv.set(d_index); - else - d_bv.clear(d_index); - return *this; - } - -// template -// INLINE ap_concat_ref<1, _private_bit_ref, _AP_W2, ap_private<_AP_W2, -// _AP_S2> > -// operator,(ap_private<_AP_W2, _AP_S2> &a2) const { -// return ap_concat_ref<1, _private_bit_ref, _AP_W2, ap_private<_AP_W2, -// _AP_S2> >( -// const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this), a2); -// } -// -// template -// INLINE ap_concat_ref<1, _private_bit_ref, _AP_W2, -// _private_range_ref<_AP_W2, -// _AP_S2> > -// operator,(const _private_range_ref<_AP_W2, _AP_S2> &a2) const { -// return ap_concat_ref<1, _private_bit_ref, _AP_W2, -// _private_range_ref<_AP_W2, -// _AP_S2> >( -// const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this), -// const_cast<_private_range_ref<_AP_W2, _AP_S2>&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<1, _private_bit_ref, 1, _private_bit_ref<_AP_W2, -// _AP_S2> > operator,( -// const _private_bit_ref<_AP_W2, _AP_S2> &a2) const { -// return ap_concat_ref<1, _private_bit_ref, 1, -// _private_bit_ref<_AP_W2, _AP_S2> >( -// const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this), -// const_cast<_private_bit_ref<_AP_W2, _AP_S2>&>(a2)); -// } -// -// INLINE ap_concat_ref<1, _private_bit_ref, 1, _private_bit_ref> -// operator,( -// const _private_bit_ref &a2) const { -// return ap_concat_ref<1, _private_bit_ref, 1, _private_bit_ref>( -// const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this), -// const_cast<_private_bit_ref&>(a2)); -// } -// -// template -// INLINE ap_concat_ref<1, _private_bit_ref, _AP_W2 + _AP_W3, -// ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> > -// operator,(const ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> &a2) const { -// return ap_concat_ref<1, _private_bit_ref, _AP_W2 + _AP_W3, -// ap_concat_ref<_AP_W2, _AP_T2, _AP_W3, _AP_T3> >( -// const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this), -// const_cast&>(a2)); -// } -// -// template -// INLINE ap_concat_ref< -// 1, _private_bit_ref, _AP_W2, -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> > -// operator,(const af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, -// _AP_N2> -// &a2) const { -// return ap_concat_ref< -// 1, _private_bit_ref, _AP_W2, -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, _AP_N2> >( -// const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this), -// const_cast< -// af_range_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, -// _AP_N2>&>(a2)); -// } -// -// template -// INLINE -// ap_concat_ref<1, _private_bit_ref, 1, -// af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, -// _AP_N2> > -// operator,(const af_bit_ref<_AP_W2, _AP_I2, _AP_S2, _AP_Q2, _AP_O2, -// _AP_N2> -// &a2) const { -// return ap_concat_ref<1, _private_bit_ref, 1, af_bit_ref<_AP_W2, -// _AP_I2, _AP_S2, -// _AP_Q2, _AP_O2, -// _AP_N2> >( -// const_cast<_private_bit_ref<_AP_W, _AP_S>&>(*this), -// const_cast&>( -// a2)); -// } - - template - INLINE bool operator==(const _private_bit_ref<_AP_W2, _AP_S2>& op) const { - return get() == op.get(); - } - - template - INLINE bool operator!=(const _private_bit_ref<_AP_W2, _AP_S2>& op) const { - return get() != op.get(); - } - - INLINE bool get() const { return operator bool(); } - - // template - // INLINE void set(const ap_private<_AP_W3, false>& val) { - // operator=(val); - // } - - // INLINE bool operator~() const { - // bool bit = (d_bv)[d_index]; - // return bit ? false : true; - // } - - INLINE int length() const { return 1; } - - // INLINE std::string to_string() const { - // bool val = get(); - // return val ? "1" : "0"; - // } - -}; // struct _private_bit_ref. - -// char a[100]; -// char* ptr = a; -// ap_int<2> n = 3; -// char* ptr2 = ptr + n*2; -// avoid ambiguous errors -#define OP_BIN_MIX_PTR(BIN_OP) \ - template \ - INLINE PTR_TYPE* operator BIN_OP(PTR_TYPE* i_op, \ - const ap_private<_AP_W, _AP_S>& op) { \ - typename ap_private<_AP_W, _AP_S>::ValType op2 = op; \ - return i_op BIN_OP op2; \ - } \ - template \ - INLINE PTR_TYPE* operator BIN_OP(const ap_private<_AP_W, _AP_S>& op, \ - PTR_TYPE* i_op) { \ - typename ap_private<_AP_W, _AP_S>::ValType op2 = op; \ - return op2 BIN_OP i_op; \ - } - -OP_BIN_MIX_PTR(+) -OP_BIN_MIX_PTR(-) -#undef OP_BIN_MIX_PTR - -// float OP ap_int -// when ap_int's width > 64, then trunc ap_int to ap_int<64> -#define OP_BIN_MIX_FLOAT(BIN_OP, C_TYPE) \ - template \ - INLINE C_TYPE operator BIN_OP(C_TYPE i_op, \ - const ap_private<_AP_W, _AP_S>& op) { \ - typename ap_private<_AP_W, _AP_S>::ValType op2 = op; \ - return i_op BIN_OP op2; \ - } \ - template \ - INLINE C_TYPE operator BIN_OP(const ap_private<_AP_W, _AP_S>& op, \ - C_TYPE i_op) { \ - typename ap_private<_AP_W, _AP_S>::ValType op2 = op; \ - return op2 BIN_OP i_op; \ - } - -#define OPS_MIX_FLOAT(C_TYPE) \ - OP_BIN_MIX_FLOAT(*, C_TYPE) \ - OP_BIN_MIX_FLOAT(/, C_TYPE) \ - OP_BIN_MIX_FLOAT(+, C_TYPE) \ - OP_BIN_MIX_FLOAT(-, C_TYPE) - -OPS_MIX_FLOAT(float) -OPS_MIX_FLOAT(double) -#undef OP_BIN_MIX_FLOAT -#undef OPS_MIX_FLOAT - -/// Operators mixing Integers with AP_Int -// ---------------------------------------------------------------- - -// partially specialize template argument _AP_C in order that: -// for _AP_W > 64, we will explicitly convert operand with native data type -// into corresponding ap_private -// for _AP_W <= 64, we will implicitly convert operand with ap_private into -// (unsigned) long long -#define OP_BIN_MIX_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ - template \ - INLINE \ - typename ap_private<_AP_WI, _AP_SI>::template RType<_AP_W, _AP_S>::RTYPE \ - operator BIN_OP(C_TYPE i_op, const ap_private<_AP_W, _AP_S>& op) { \ - return ap_private<_AP_WI, _AP_SI>(i_op).operator BIN_OP(op); \ - } \ - template \ - INLINE \ - typename ap_private<_AP_W, _AP_S>::template RType<_AP_WI, _AP_SI>::RTYPE \ - operator BIN_OP(const ap_private<_AP_W, _AP_S>& op, C_TYPE i_op) { \ - return op.operator BIN_OP(ap_private<_AP_WI, _AP_SI>(i_op)); \ - } - -#define OP_REL_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE bool operator REL_OP(const ap_private<_AP_W, _AP_S>& op, \ - C_TYPE op2) { \ - return op.operator REL_OP(ap_private<_AP_W2, _AP_S2>(op2)); \ - } \ - template \ - INLINE bool operator REL_OP(C_TYPE op2, \ - const ap_private<_AP_W, _AP_S, false>& op) { \ - return ap_private<_AP_W2, _AP_S2>(op2).operator REL_OP(op); \ - } - -#define OP_ASSIGN_MIX_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE ap_private<_AP_W, _AP_S>& operator ASSIGN_OP( \ - ap_private<_AP_W, _AP_S>& op, C_TYPE op2) { \ - return op.operator ASSIGN_OP(ap_private<_AP_W2, _AP_S2>(op2)); \ - } - -#define OP_BIN_SHIFT_INT(BIN_OP, C_TYPE, _AP_WI, _AP_SI, RTYPE) \ - template \ - C_TYPE operator BIN_OP(C_TYPE i_op, \ - const ap_private<_AP_W, _AP_S, false>& op) { \ - return i_op BIN_OP(op.get_VAL()); \ - } \ - template \ - INLINE \ - typename ap_private<_AP_W, _AP_S>::template RType<_AP_WI, _AP_SI>::RTYPE \ - operator BIN_OP(const ap_private<_AP_W, _AP_S>& op, C_TYPE i_op) { \ - return op.operator BIN_OP(i_op); \ - } - -#define OP_ASSIGN_RSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE ap_private<_AP_W, _AP_S>& operator ASSIGN_OP( \ - ap_private<_AP_W, _AP_S>& op, C_TYPE op2) { \ - op = op.operator>>(op2); \ - return op; \ - } - -#define OP_ASSIGN_LSHIFT_INT(ASSIGN_OP, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE ap_private<_AP_W, _AP_S>& operator ASSIGN_OP( \ - ap_private<_AP_W, _AP_S>& op, C_TYPE op2) { \ - op = op.operator<<(op2); \ - return op; \ - } - -#define OPS_MIX_INT(C_TYPE, _AP_W2, _AP_S2) \ - OP_BIN_MIX_INT(*, C_TYPE, (_AP_W2), (_AP_S2), mult) \ - OP_BIN_MIX_INT(+, C_TYPE, (_AP_W2), (_AP_S2), plus) \ - OP_BIN_MIX_INT(-, C_TYPE, (_AP_W2), (_AP_S2), minus) \ - OP_BIN_MIX_INT(/, C_TYPE, (_AP_W2), (_AP_S2), div) \ - OP_BIN_MIX_INT(%, C_TYPE, (_AP_W2), (_AP_S2), mod) \ - OP_BIN_MIX_INT(&, C_TYPE, (_AP_W2), (_AP_S2), logic) \ - OP_BIN_MIX_INT(|, C_TYPE, (_AP_W2), (_AP_S2), logic) \ - OP_BIN_MIX_INT (^, C_TYPE, (_AP_W2), (_AP_S2), logic) \ - OP_BIN_SHIFT_INT(>>, C_TYPE, (_AP_W2), (_AP_S2), arg1) \ - OP_BIN_SHIFT_INT(<<, C_TYPE, (_AP_W2), (_AP_S2), arg1) \ - \ - OP_ASSIGN_MIX_INT(+=, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_ASSIGN_MIX_INT(-=, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_ASSIGN_MIX_INT(*=, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_ASSIGN_MIX_INT(/=, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_ASSIGN_MIX_INT(%=, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_ASSIGN_MIX_INT(&=, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_ASSIGN_MIX_INT(|=, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_ASSIGN_MIX_INT(^=, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_ASSIGN_RSHIFT_INT(>>=, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_ASSIGN_LSHIFT_INT(<<=, C_TYPE, (_AP_W2), (_AP_S2)) \ - \ - OP_REL_MIX_INT(>, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_REL_MIX_INT(<, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_REL_MIX_INT(>=, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_REL_MIX_INT(<=, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_REL_MIX_INT(==, C_TYPE, (_AP_W2), (_AP_S2)) \ - OP_REL_MIX_INT(!=, C_TYPE, (_AP_W2), (_AP_S2)) - -OPS_MIX_INT(bool, 1, false) -OPS_MIX_INT(char, 8, CHAR_IS_SIGNED) -OPS_MIX_INT(signed char, 8, true) -OPS_MIX_INT(unsigned char, 8, false) -OPS_MIX_INT(short, sizeof(short) * 8, true) -OPS_MIX_INT(unsigned short, sizeof(unsigned short) * 8, false) -OPS_MIX_INT(int, sizeof(int) * 8, true) -OPS_MIX_INT(unsigned int, sizeof(unsigned int) * 8, false) -OPS_MIX_INT(long, sizeof(long) * 8, true) -OPS_MIX_INT(unsigned long, sizeof(unsigned long) * 8, false) -OPS_MIX_INT(ap_slong, sizeof(ap_slong) * 8, true) -OPS_MIX_INT(ap_ulong, sizeof(ap_ulong) * 8, false) - -#undef OP_BIN_MIX_INT -#undef OP_BIN_SHIFT_INT -#undef OP_ASSIGN_MIX_INT -#undef OP_ASSIGN_RSHIFT_INT -#undef OP_ASSIGN_LSHIFT_INT -#undef OP_REL_MIX_INT -#undef OPS_MIX_INT - -#define OP_BIN_MIX_RANGE(BIN_OP, RTYPE) \ - template \ - INLINE typename ap_private<_AP_W1, _AP_S1>::template RType<_AP_W2, \ - _AP_S2>::RTYPE \ - operator BIN_OP(const _private_range_ref<_AP_W1, _AP_S1>& op1, \ - const ap_private<_AP_W2, _AP_S2>& op2) { \ - return ap_private<_AP_W1, false>(op1).operator BIN_OP(op2); \ - } \ - template \ - INLINE typename ap_private<_AP_W1, _AP_S1>::template RType<_AP_W2, \ - _AP_S2>::RTYPE \ - operator BIN_OP(const ap_private<_AP_W1, _AP_S1>& op1, \ - const _private_range_ref<_AP_W2, _AP_S2>& op2) { \ - return op1.operator BIN_OP(ap_private<_AP_W2, false>(op2)); \ - } - -#define OP_ASSIGN_MIX_RANGE(ASSIGN_OP) \ - template \ - INLINE ap_private<_AP_W1, _AP_S1>& operator ASSIGN_OP( \ - ap_private<_AP_W1, _AP_S1>& op1, \ - const _private_range_ref<_AP_W2, _AP_S2>& op2) { \ - return op1.operator ASSIGN_OP(ap_private<_AP_W2, false>(op2)); \ - } \ - template \ - INLINE _private_range_ref<_AP_W1, _AP_S1>& operator ASSIGN_OP( \ - _private_range_ref<_AP_W1, _AP_S1>& op1, \ - ap_private<_AP_W2, _AP_S2>& op2) { \ - ap_private<_AP_W1, false> tmp(op1); \ - tmp.operator ASSIGN_OP(op2); \ - op1 = tmp; \ - return op1; \ - } - -#define OP_REL_MIX_RANGE(REL_OP) \ - template \ - INLINE bool operator REL_OP(const _private_range_ref<_AP_W1, _AP_S1>& op1, \ - const ap_private<_AP_W2, _AP_S2>& op2) { \ - return ap_private<_AP_W1, false>(op1).operator REL_OP(op2); \ - } \ - template \ - INLINE bool operator REL_OP(const ap_private<_AP_W1, _AP_S1>& op1, \ - const _private_range_ref<_AP_W2, _AP_S2>& op2) { \ - return op1.operator REL_OP(op2.operator ap_private<_AP_W2, false>()); \ - } - -OP_BIN_MIX_RANGE(+, plus) -OP_BIN_MIX_RANGE(-, minus) -OP_BIN_MIX_RANGE(*, mult) -OP_BIN_MIX_RANGE(/, div) -OP_BIN_MIX_RANGE(%, mod) -OP_BIN_MIX_RANGE(&, logic) -OP_BIN_MIX_RANGE(|, logic) -OP_BIN_MIX_RANGE(^, logic) -OP_BIN_MIX_RANGE(>>, arg1) -OP_BIN_MIX_RANGE(<<, arg1) -#undef OP_BIN_MIX_RANGE - -OP_ASSIGN_MIX_RANGE(+=) -OP_ASSIGN_MIX_RANGE(-=) -OP_ASSIGN_MIX_RANGE(*=) -OP_ASSIGN_MIX_RANGE(/=) -OP_ASSIGN_MIX_RANGE(%=) -OP_ASSIGN_MIX_RANGE(&=) -OP_ASSIGN_MIX_RANGE(|=) -OP_ASSIGN_MIX_RANGE(^=) -OP_ASSIGN_MIX_RANGE(>>=) -OP_ASSIGN_MIX_RANGE(<<=) -#undef OP_ASSIGN_MIX_RANGE - -OP_REL_MIX_RANGE(>) -OP_REL_MIX_RANGE(<) -OP_REL_MIX_RANGE(>=) -OP_REL_MIX_RANGE(<=) -OP_REL_MIX_RANGE(==) -OP_REL_MIX_RANGE(!=) -#undef OP_REL_MIX_RANGE - -#define OP_BIN_MIX_BIT(BIN_OP, RTYPE) \ - template \ - INLINE typename ap_private<1, false>::template RType<_AP_W2, _AP_S2>::RTYPE \ - operator BIN_OP(const _private_bit_ref<_AP_W1, _AP_S1>& op1, \ - const ap_private<_AP_W2, _AP_S2>& op2) { \ - return ap_private<1, false>(op1).operator BIN_OP(op2); \ - } \ - template \ - INLINE typename ap_private<_AP_W1, _AP_S1>::template RType<1, false>::RTYPE \ - operator BIN_OP(const ap_private<_AP_W1, _AP_S1>& op1, \ - const _private_bit_ref<_AP_W2, _AP_S2>& op2) { \ - return op1.operator BIN_OP(ap_private<1, false>(op2)); \ - } - -#define OP_ASSIGN_MIX_BIT(ASSIGN_OP) \ - template \ - INLINE ap_private<_AP_W1, _AP_S1>& operator ASSIGN_OP( \ - ap_private<_AP_W1, _AP_S1>& op1, \ - _private_bit_ref<_AP_W2, _AP_S2>& op2) { \ - return op1.operator ASSIGN_OP(ap_private<1, false>(op2)); \ - } \ - template \ - INLINE _private_bit_ref<_AP_W1, _AP_S1>& operator ASSIGN_OP( \ - _private_bit_ref<_AP_W1, _AP_S1>& op1, \ - ap_private<_AP_W2, _AP_S2>& op2) { \ - ap_private<1, false> tmp(op1); \ - tmp.operator ASSIGN_OP(op2); \ - op1 = tmp; \ - return op1; \ - } - -#define OP_REL_MIX_BIT(REL_OP) \ - template \ - INLINE bool operator REL_OP(const _private_bit_ref<_AP_W1, _AP_S1>& op1, \ - const ap_private<_AP_W2, _AP_S2>& op2) { \ - return ap_private<_AP_W1, false>(op1).operator REL_OP(op2); \ - } \ - template \ - INLINE bool operator REL_OP(const ap_private<_AP_W1, _AP_S1>& op1, \ - const _private_bit_ref<_AP_W2, _AP_S2>& op2) { \ - return op1.operator REL_OP(ap_private<1, false>(op2)); \ - } - -OP_ASSIGN_MIX_BIT(+=) -OP_ASSIGN_MIX_BIT(-=) -OP_ASSIGN_MIX_BIT(*=) -OP_ASSIGN_MIX_BIT(/=) -OP_ASSIGN_MIX_BIT(%=) -OP_ASSIGN_MIX_BIT(&=) -OP_ASSIGN_MIX_BIT(|=) -OP_ASSIGN_MIX_BIT(^=) -OP_ASSIGN_MIX_BIT(>>=) -OP_ASSIGN_MIX_BIT(<<=) -#undef OP_ASSIGN_MIX_BIT - -OP_BIN_MIX_BIT(+, plus) -OP_BIN_MIX_BIT(-, minus) -OP_BIN_MIX_BIT(*, mult) -OP_BIN_MIX_BIT(/, div) -OP_BIN_MIX_BIT(%, mod) -OP_BIN_MIX_BIT(&, logic) -OP_BIN_MIX_BIT(|, logic) -OP_BIN_MIX_BIT(^, logic) -OP_BIN_MIX_BIT(>>, arg1) -OP_BIN_MIX_BIT(<<, arg1) -#undef OP_BIN_MIX_BIT - -OP_REL_MIX_BIT(>) -OP_REL_MIX_BIT(<) -OP_REL_MIX_BIT(<=) -OP_REL_MIX_BIT(>=) -OP_REL_MIX_BIT(==) -OP_REL_MIX_BIT(!=) -#undef OP_REL_MIX_BIT - -#define REF_REL_OP_MIX_INT(REL_OP, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE bool operator REL_OP(const _private_range_ref<_AP_W, _AP_S>& op, \ - C_TYPE op2) { \ - return (ap_private<_AP_W, false>(op)) \ - . \ - operator REL_OP(ap_private<_AP_W2, _AP_S2>(op2)); \ - } \ - template \ - INLINE bool operator REL_OP(C_TYPE op2, \ - const _private_range_ref<_AP_W, _AP_S>& op) { \ - return ap_private<_AP_W2, _AP_S2>(op2).operator REL_OP( \ - ap_private<_AP_W, false>(op)); \ - } \ - template \ - INLINE bool operator REL_OP(const _private_bit_ref<_AP_W, _AP_S>& op, \ - C_TYPE op2) { \ - return (bool(op))REL_OP op2; \ - } \ - template \ - INLINE bool operator REL_OP(C_TYPE op2, \ - const _private_bit_ref<_AP_W, _AP_S>& op) { \ - return op2 REL_OP(bool(op)); \ - } - -#define REF_REL_MIX_INT(C_TYPE, _AP_W2, _AP_S2) \ - REF_REL_OP_MIX_INT(>, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_REL_OP_MIX_INT(<, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_REL_OP_MIX_INT(>=, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_REL_OP_MIX_INT(<=, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_REL_OP_MIX_INT(==, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_REL_OP_MIX_INT(!=, C_TYPE, (_AP_W2), (_AP_S2)) - -REF_REL_MIX_INT(bool, 1, false) -REF_REL_MIX_INT(char, 8, CHAR_IS_SIGNED) -REF_REL_MIX_INT(signed char, 8, true) -REF_REL_MIX_INT(unsigned char, 8, false) -REF_REL_MIX_INT(short, sizeof(short) * 8, true) -REF_REL_MIX_INT(unsigned short, sizeof(unsigned short) * 8, false) -REF_REL_MIX_INT(int, sizeof(int) * 8, true) -REF_REL_MIX_INT(unsigned int, sizeof(unsigned int) * 8, false) -REF_REL_MIX_INT(long, sizeof(long) * 8, true) -REF_REL_MIX_INT(unsigned long, sizeof(unsigned long) * 8, false) -REF_REL_MIX_INT(ap_slong, sizeof(ap_slong) * 8, true) -REF_REL_MIX_INT(ap_ulong, sizeof(ap_ulong) * 8, false) -#undef REF_REL_OP_MIX_INT -#undef REF_REL_MIX_INT - -#define REF_BIN_OP_MIX_INT(BIN_OP, RTYPE, C_TYPE, _AP_W2, _AP_S2) \ - template \ - INLINE \ - typename ap_private<_AP_W, false>::template RType<_AP_W2, _AP_S2>::RTYPE \ - operator BIN_OP(const _private_range_ref<_AP_W, _AP_S>& op, \ - C_TYPE op2) { \ - return (ap_private<_AP_W, false>(op)) \ - . \ - operator BIN_OP(ap_private<_AP_W2, _AP_S2>(op2)); \ - } \ - template \ - INLINE \ - typename ap_private<_AP_W2, _AP_S2>::template RType<_AP_W, false>::RTYPE \ - operator BIN_OP(C_TYPE op2, \ - const _private_range_ref<_AP_W, _AP_S>& op) { \ - return ap_private<_AP_W2, _AP_S2>(op2).operator BIN_OP( \ - ap_private<_AP_W, false>(op)); \ - } - -#define REF_BIN_MIX_INT(C_TYPE, _AP_W2, _AP_S2) \ - REF_BIN_OP_MIX_INT(+, plus, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_MIX_INT(-, minus, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_MIX_INT(*, mult, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_MIX_INT(/, div, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_MIX_INT(%, mod, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_MIX_INT(&, logic, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_MIX_INT(|, logic, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_MIX_INT(^, logic, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_MIX_INT(>>, arg1, C_TYPE, (_AP_W2), (_AP_S2)) \ - REF_BIN_OP_MIX_INT(<<, arg1, C_TYPE, (_AP_W2), (_AP_S2)) - -REF_BIN_MIX_INT(bool, 1, false) -REF_BIN_MIX_INT(char, 8, CHAR_IS_SIGNED) -REF_BIN_MIX_INT(signed char, 8, true) -REF_BIN_MIX_INT(unsigned char, 8, false) -REF_BIN_MIX_INT(short, sizeof(short) * 8, true) -REF_BIN_MIX_INT(unsigned short, sizeof(unsigned short) * 8, false) -REF_BIN_MIX_INT(int, sizeof(int) * 8, true) -REF_BIN_MIX_INT(unsigned int, sizeof(unsigned int) * 8, false) -REF_BIN_MIX_INT(long, sizeof(long) * 8, true) -REF_BIN_MIX_INT(unsigned long, sizeof(unsigned long) * 8, false) -REF_BIN_MIX_INT(ap_slong, sizeof(ap_slong) * 8, true) -REF_BIN_MIX_INT(ap_ulong, sizeof(ap_ulong) * 8, false) -#undef REF_BIN_OP_MIX_INT -#undef REF_BIN_MIX_INT - -#define REF_BIN_OP(BIN_OP, RTYPE) \ - template \ - INLINE \ - typename ap_private<_AP_W, false>::template RType<_AP_W2, false>::RTYPE \ - operator BIN_OP(const _private_range_ref<_AP_W, _AP_S>& lhs, \ - const _private_range_ref<_AP_W2, _AP_S2>& rhs) { \ - return ap_private<_AP_W, false>(lhs).operator BIN_OP( \ - ap_private<_AP_W2, false>(rhs)); \ - } - -REF_BIN_OP(+, plus) -REF_BIN_OP(-, minus) -REF_BIN_OP(*, mult) -REF_BIN_OP(/, div) -REF_BIN_OP(%, mod) -REF_BIN_OP(&, logic) -REF_BIN_OP(|, logic) -REF_BIN_OP(^, logic) -REF_BIN_OP(>>, arg1) -REF_BIN_OP(<<, arg1) -#undef REF_BIN_OP - -//************************************************************************ -// Implement -// ap_private = ap_concat_ref OP ap_concat_ref -// for operators +, -, *, /, %, >>, <<, &, |, ^ -// Without these operators the operands are converted to int64 and -// larger results lose informations (higher order bits). -// -// operand OP -// / | -// left-concat right-concat -// / | / | -// -// -// _AP_LW1, _AP_LT1 (width and type of left-concat's left side) -// _AP_LW2, _AP_LT2 (width and type of left-concat's right side) -// Similarly for RHS of operand OP: _AP_RW1, AP_RW2, _AP_RT1, _AP_RT2 -// -// In Verilog 2001 result of concatenation is always unsigned even -// when both sides are signed. -//************************************************************************ - -#endif // ifndef __AP_PRIVATE_H__ - -// -*- cpp -*- diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/hls_stream.h b/model/AE_model/hls4ml_prj/firmware/ap_types/hls_stream.h deleted file mode 100644 index f516c39..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/hls_stream.h +++ /dev/null @@ -1,263 +0,0 @@ -/* -#- (c) Copyright 2011-2018 Xilinx, Inc. All rights reserved. -#- -#- This file contains confidential and proprietary information -#- of Xilinx, Inc. and is protected under U.S. and -#- international copyright and other intellectual property -#- laws. -#- -#- DISCLAIMER -#- This disclaimer is not a license and does not grant any -#- rights to the materials distributed herewith. Except as -#- otherwise provided in a valid license issued to you by -#- Xilinx, and to the maximum extent permitted by applicable -#- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND -#- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES -#- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING -#- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- -#- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and -#- (2) Xilinx shall not be liable (whether in contract or tort, -#- including negligence, or under any other theory of -#- liability) for any loss or damage of any kind or nature -#- related to, arising under or in connection with these -#- materials, including for any direct, or any indirect, -#- special, incidental, or consequential loss or damage -#- (including loss of data, profits, goodwill, or any type of -#- loss or damage suffered as a result of any action brought -#- by a third party) even if such damage or loss was -#- reasonably foreseeable or Xilinx had been advised of the -#- possibility of the same. -#- -#- CRITICAL APPLICATIONS -#- Xilinx products are not designed or intended to be fail- -#- safe, or for use in any application requiring fail-safe -#- performance, such as life-support or safety devices or -#- systems, Class III medical devices, nuclear facilities, -#- applications related to the deployment of airbags, or any -#- other applications that could lead to death, personal -#- injury, or severe property or environmental damage -#- (individually and collectively, "Critical -#- Applications"). Customer assumes the sole risk and -#- liability of any use of Xilinx products in Critical -#- Applications, subject only to applicable laws and -#- regulations governing limitations on product liability. -#- -#- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS -#- PART OF THIS FILE AT ALL TIMES. -#- ************************************************************************ - - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#ifndef X_HLS_STREAM_SIM_H -#define X_HLS_STREAM_SIM_H - -/* - * This file contains a C++ model of hls::stream. - * It defines C simulation model. - */ -#ifndef __cplusplus - -#error C++ is required to include this header file - -#else - -////////////////////////////////////////////// -// C level simulation models for hls::stream -////////////////////////////////////////////// -#include -#include -#include -#include -#include - -#ifdef HLS_STREAM_THREAD_SAFE -#include -#include -#endif - -#ifndef _MSC_VER -#include -#include -#endif - -namespace hls { - -template -class stream -{ - protected: - std::string _name; - std::deque<__STREAM_T__> _data; // container for the elements -#ifdef HLS_STREAM_THREAD_SAFE - std::mutex _mutex; - std::condition_variable _condition_var; -#endif - - public: - /// Constructors - // Keep consistent with the synthesis model's constructors - stream() { - static unsigned _counter = 1; - std::stringstream ss; -#ifndef _MSC_VER - char* _demangle_name = abi::__cxa_demangle(typeid(*this).name(), 0, 0, 0); - if (_demangle_name) { - _name = _demangle_name; - free(_demangle_name); - } - else { - _name = "hls_stream"; - } -#else - _name = typeid(*this).name(); -#endif - - ss << _counter++; - _name += "." + ss.str(); - } - - stream(const std::string name) { - // default constructor, - // capacity set to predefined maximum - _name = name; - } - - /// Make copy constructor and assignment operator private - private: - stream(const stream< __STREAM_T__ >& chn): - _name(chn._name), _data(chn._data) { - } - - stream& operator = (const stream< __STREAM_T__ >& chn) { - _name = chn._name; - _data = chn._data; - return *this; - } - - public: - /// Overload >> and << operators to implement read() and write() - void operator >> (__STREAM_T__& rdata) { - read(rdata); - } - - void operator << (const __STREAM_T__& wdata) { - write(wdata); - } - - - public: - /// Destructor - /// Check status of the queue - virtual ~stream() { - if (!_data.empty()) - { - std::cout << "WARNING: Hls::stream '" - << _name - << "' contains leftover data," - << " which may result in RTL simulation hanging." - << std::endl; - } - } - - /// Status of the queue - bool empty() { -#ifdef HLS_STREAM_THREAD_SAFE - std::lock_guard lg(_mutex); -#endif - return _data.empty(); - } - - bool full() const { return false; } - - /// Blocking read - void read(__STREAM_T__& head) { - head = read(); - } - -#ifdef HLS_STREAM_THREAD_SAFE - __STREAM_T__ read() { - std::unique_lock ul(_mutex); - while (_data.empty()) { - _condition_var.wait(ul); - } - - __STREAM_T__ elem; - elem = _data.front(); - _data.pop_front(); - return elem; - } -#else - __STREAM_T__ read() { - __STREAM_T__ elem; - if (_data.empty()) { - std::cout << "WARNING: Hls::stream '" - << _name - << "' is read while empty," - << " which may result in RTL simulation hanging." - << std::endl; - elem = __STREAM_T__(); - } else { - elem = _data.front(); - _data.pop_front(); - } - return elem; - } -#endif - - /// Blocking write - void write(const __STREAM_T__& tail) { -#ifdef HLS_STREAM_THREAD_SAFE - std::unique_lock ul(_mutex); -#endif - _data.push_back(tail); -#ifdef HLS_STREAM_THREAD_SAFE - _condition_var.notify_one(); -#endif - } - - /// Nonblocking read - bool read_nb(__STREAM_T__& head) { -#ifdef HLS_STREAM_THREAD_SAFE - std::lock_guard lg(_mutex); -#endif - bool is_empty = _data.empty(); - if (is_empty) { - head = __STREAM_T__(); - } else { - __STREAM_T__ elem(_data.front()); - _data.pop_front(); - head = elem; - } - return !is_empty; - } - - /// Nonblocking write - bool write_nb(const __STREAM_T__& tail) { - bool is_full = full(); - write(tail); - return !is_full; - } - - /// Fifo size - size_t size() { - return _data.size(); - } -}; - -} // namespace hls - -#endif // __cplusplus -#endif // X_HLS_STREAM_SIM_H - diff --git a/model/AE_model/hls4ml_prj/firmware/ap_types/utils/x_hls_utils.h b/model/AE_model/hls4ml_prj/firmware/ap_types/utils/x_hls_utils.h deleted file mode 100644 index 3e751c3..0000000 --- a/model/AE_model/hls4ml_prj/firmware/ap_types/utils/x_hls_utils.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef X_HLS_UTILS_H -#define X_HLS_UTILS_H -#include "ap_fixed.h" -#include - -namespace hls { - - template - class numeric_limits { - public: - static T max() { return std::numeric_limits::max(); } - static T min() { return std::numeric_limits::min(); } - static T epsilon() { return std::numeric_limits::epsilon(); } - }; - - template - class numeric_limits > { - public: - static ap_fixed max() { - ap_int m = ::hls::numeric_limits >::max(); - ap_fixed x; - x(W-1,0) = m(W-1,0); - return x; - } - static ap_fixed min() { - ap_int m = ::hls::numeric_limits >::min(); - ap_fixed x; - x(W-1,0) = m(W-1,0); - return x; - } - static ap_fixed epsilon() { - ap_fixed x = 0; - x[0] = 1; - return x; - } - }; - - template - class numeric_limits > { - public: - static ap_ufixed max() { - ap_uint m = ::hls::numeric_limits >::max(); - ap_ufixed x; - x(W-1,0) = m(W-1,0); - return x; - } - static ap_ufixed min() { return 0; } - static ap_ufixed epsilon() { - ap_ufixed x = 0; - x[0] = 1; - return x; - } - }; - - template - class numeric_limits > { - public: - static ap_int max() { ap_int m = min(); return ~m; } - static ap_int min() { ap_int m = 0; m[W-1] = 1; return m; } - static ap_int epsilon() { - ap_int x = 0; - x[0] = 1; - return x; - } - }; - - template - class numeric_limits > { - public: - static ap_uint max() { ap_uint zero = 0; return ~zero; } - static ap_uint min() { return 0; } - static ap_uint epsilon() { - ap_uint x = 0; - x[0] = 1; - return x; - } - }; -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/defines.h b/model/AE_model/hls4ml_prj/firmware/defines.h deleted file mode 100644 index bb8945e..0000000 --- a/model/AE_model/hls4ml_prj/firmware/defines.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef DEFINES_H_ -#define DEFINES_H_ - -#include "ap_int.h" -#include "ap_fixed.h" -#include "nnet_utils/nnet_types.h" -#include -#include - -//hls-fpga-machine-learning insert numbers -#define N_INPUT_1_1 100 -#define N_LAYER_2 32 -#define N_LAYER_4 16 -#define N_LAYER_6 2 -#define N_LAYER_8 16 -#define N_LAYER_10 32 -#define N_LAYER_12 100 - -//hls-fpga-machine-learning insert layer-precision -typedef ap_fixed<16,6> model_default_t; -typedef ap_fixed<16,6> input_t; -typedef ap_fixed<16,6> layer2_t; -typedef ap_fixed<16,6> layer3_t; -typedef ap_fixed<16,6> layer4_t; -typedef ap_fixed<16,6> layer5_t; -typedef ap_fixed<16,6> layer6_t; -typedef ap_fixed<16,6> layer7_t; -typedef ap_fixed<16,6> layer8_t; -typedef ap_fixed<16,6> layer9_t; -typedef ap_fixed<16,6> layer10_t; -typedef ap_fixed<16,6> layer11_t; -typedef ap_fixed<16,6> layer12_t; -typedef ap_fixed<16,6> result_t; - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/myproject.cpp b/model/AE_model/hls4ml_prj/firmware/myproject.cpp deleted file mode 100644 index 01d1ae0..0000000 --- a/model/AE_model/hls4ml_prj/firmware/myproject.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -#include - -#include "myproject.h" -#include "parameters.h" - -void myproject( - input_t encoder_input[N_INPUT_1_1], - result_t layer13_out[N_LAYER_12], - unsigned short &const_size_in_1, - unsigned short &const_size_out_1 -) { - - //hls-fpga-machine-learning insert IO - #pragma HLS ARRAY_RESHAPE variable=encoder_input complete dim=0 - #pragma HLS ARRAY_PARTITION variable=layer13_out complete dim=0 - #pragma HLS INTERFACE ap_vld port=encoder_input,layer13_out - #pragma HLS PIPELINE - - const_size_in_1 = N_INPUT_1_1; - const_size_out_1 = N_LAYER_12; - -#ifndef __SYNTHESIS__ - static bool loaded_weights = false; - if (!loaded_weights) { - //hls-fpga-machine-learning insert load weights - nnet::load_weights_from_txt(w2, "w2.txt"); - nnet::load_weights_from_txt(b2, "b2.txt"); - nnet::load_weights_from_txt(w4, "w4.txt"); - nnet::load_weights_from_txt(b4, "b4.txt"); - nnet::load_weights_from_txt(w6, "w6.txt"); - nnet::load_weights_from_txt(b6, "b6.txt"); - nnet::load_weights_from_txt(w8, "w8.txt"); - nnet::load_weights_from_txt(b8, "b8.txt"); - nnet::load_weights_from_txt(w10, "w10.txt"); - nnet::load_weights_from_txt(b10, "b10.txt"); - nnet::load_weights_from_txt(w12, "w12.txt"); - nnet::load_weights_from_txt(b12, "b12.txt"); - loaded_weights = true; - } -#endif - - // **************************************** - // NETWORK INSTANTIATION - // **************************************** - - //hls-fpga-machine-learning insert layers - - layer2_t layer2_out[N_LAYER_2]; - #pragma HLS ARRAY_PARTITION variable=layer2_out complete dim=0 - nnet::dense(encoder_input, layer2_out, w2, b2); // dense_12 - - layer3_t layer3_out[N_LAYER_2]; - #pragma HLS ARRAY_PARTITION variable=layer3_out complete dim=0 - nnet::relu(layer2_out, layer3_out); // dense_12_relu - - layer4_t layer4_out[N_LAYER_4]; - #pragma HLS ARRAY_PARTITION variable=layer4_out complete dim=0 - nnet::dense(layer3_out, layer4_out, w4, b4); // dense_13 - - layer5_t layer5_out[N_LAYER_4]; - #pragma HLS ARRAY_PARTITION variable=layer5_out complete dim=0 - nnet::relu(layer4_out, layer5_out); // dense_13_relu - - layer6_t layer6_out[N_LAYER_6]; - #pragma HLS ARRAY_PARTITION variable=layer6_out complete dim=0 - nnet::dense(layer5_out, layer6_out, w6, b6); // encoder_output - - layer7_t layer7_out[N_LAYER_6]; - #pragma HLS ARRAY_PARTITION variable=layer7_out complete dim=0 - nnet::relu(layer6_out, layer7_out); // encoder_output_relu - - layer8_t layer8_out[N_LAYER_8]; - #pragma HLS ARRAY_PARTITION variable=layer8_out complete dim=0 - nnet::dense(layer7_out, layer8_out, w8, b8); // dense_14 - - layer9_t layer9_out[N_LAYER_8]; - #pragma HLS ARRAY_PARTITION variable=layer9_out complete dim=0 - nnet::relu(layer8_out, layer9_out); // dense_14_relu - - layer10_t layer10_out[N_LAYER_10]; - #pragma HLS ARRAY_PARTITION variable=layer10_out complete dim=0 - nnet::dense(layer9_out, layer10_out, w10, b10); // dense_15 - - layer11_t layer11_out[N_LAYER_10]; - #pragma HLS ARRAY_PARTITION variable=layer11_out complete dim=0 - nnet::relu(layer10_out, layer11_out); // dense_15_relu - - layer12_t layer12_out[N_LAYER_12]; - #pragma HLS ARRAY_PARTITION variable=layer12_out complete dim=0 - nnet::dense(layer11_out, layer12_out, w12, b12); // ecoder_output - - nnet::sigmoid(layer12_out, layer13_out); // ecoder_output_sigmoid - -} diff --git a/model/AE_model/hls4ml_prj/firmware/myproject.h b/model/AE_model/hls4ml_prj/firmware/myproject.h deleted file mode 100644 index 7c6a081..0000000 --- a/model/AE_model/hls4ml_prj/firmware/myproject.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef MYPROJECT_H_ -#define MYPROJECT_H_ - -#include "ap_int.h" -#include "ap_fixed.h" -#include "hls_stream.h" - -#include "defines.h" - -// Prototype of top level function for C-synthesis -void myproject( - input_t encoder_input[N_INPUT_1_1], - result_t layer13_out[N_LAYER_12], - unsigned short &const_size_in_1, - unsigned short &const_size_out_1 -); - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_activation.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_activation.h deleted file mode 100644 index 83f73ad..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_activation.h +++ /dev/null @@ -1,861 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_ACTIVATION_H_ -#define NNET_ACTIVATION_H_ - -#include -#include "ap_fixed.h" -#include "nnet_common.h" - -namespace nnet { - -struct activ_config -{ - // IO size - static const unsigned n_in = 10; - - // Internal info - static const unsigned table_size = 1024; - - // Resource reuse info - static const unsigned io_type = io_parallel; - static const unsigned reuse_factor = 1; - - // Internal data type definitions - typedef ap_fixed<18,8> table_t; -}; - -// ************************************************* -// LINEAR Activation -- See Issue 53 -// ************************************************* -template -void linear(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - for (int ii=0; ii -void relu(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - data_T datareg; - for (int ii=0; ii 0) res[ii] = datareg; - else res[ii] = 0; - } -} - -template -void relu_max(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - data_T datareg; - for (int ii=0; ii MAX_INT) res[ii] = MAX_INT; - else res[ii] = datareg; - } -} - -template -void relu6(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - relu_max(data, res); -} - -template -void relu1(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - relu_max(data, res); -} - -// ************************************************* -// Sigmoid Activation -// ************************************************* -inline float sigmoid_fcn_float(float input) { - return 1.0 / (1 + std::exp(-input)); -} - -template -void init_sigmoid_table(typename CONFIG_T::table_t table_out[N_TABLE]) -{ - // Default logistic sigmoid function: - // result = 1/(1+e^(-x)) - for (int ii = 0; ii < N_TABLE; ii++) { - // First, convert from table index to X-value (signed 8-bit, range -8 to +8) - float in_val = 2*8.0*(ii-float(N_TABLE)/2.0)/float(N_TABLE); - // Next, compute lookup table function - typename CONFIG_T::table_t real_val = sigmoid_fcn_float(in_val); - //std::cout << "Lookup table In Value: " << in_val << " Result: " << real_val << std::endl; - table_out[ii] = real_val; - } -} - -template -void sigmoid(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t sigmoid_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t sigmoid_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_sigmoid_table(sigmoid_table); - initialized = true; - } - - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - // Index into the lookup table based on data - int data_round; - int index; - for (int ii=0; ii CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - res[ii] = (res_T) sigmoid_table[index]; - } -} - -// ************************************************* -// Softmax Activation -// ************************************************* - -enum class softmax_implementation {latency=0, legacy=1, stable=2}; - -inline float exp_fcn_float(float input) { - return std::exp(input); -} - -template -inline float softmax_real_val_from_idx(unsigned i){ - // Treat the index as the top N bits - static constexpr int N = ceillog2(CONFIG_T::table_size); // number of address bits for table - data_T x(0); - x(x.width-1, x.width-N) = i; - return (float) x; -} - -template -inline unsigned softmax_idx_from_real_val(data_T x){ - // Slice the top N bits to get an index into the table - static constexpr int N = ceillog2(CONFIG_T::table_size); // number of address bits for table - ap_uint y = x(x.width-1, x.width-N); // slice the top N bits of input - return (unsigned) y(N-1, 0); -} - -template -void init_exp_table(typename CONFIG_T::exp_table_t table_out[CONFIG_T::table_size]){ - // The template data_T is the data type used to address the table - for(unsigned i = 0; i < CONFIG_T::table_size; i++){ - // Slicing bits for address is going to round towards 0, so take the central value - float x = softmax_real_val_from_idx(i); - typename CONFIG_T::exp_table_t exp_x = exp_fcn_float(x); - table_out[i] = exp_x; - } -} - -template -void init_invert_table(typename CONFIG_T::inv_table_t table_out[CONFIG_T::table_size]){ - // The template data_T is the data type used to address the table - for(unsigned i = 0; i < CONFIG_T::table_size; i++){ - float x = softmax_real_val_from_idx(i); - typename CONFIG_T::inv_table_t inv_x = 1 / x; - table_out[i] = inv_x; - } -} - -template -void softmax_latency(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]){ - #pragma HLS pipeline - // Initialize the lookup tables -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::exp_table_t exp_table[CONFIG_T::table_size]; - typename CONFIG_T::inv_table_t invert_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::exp_table_t exp_table[CONFIG_T::table_size]; - static typename CONFIG_T::inv_table_t invert_table[CONFIG_T::table_size]; - -#endif - if (!initialized) { - // Note we are exponentiating the inputs, which have type data_T - init_exp_table(exp_table); - // Note we are inverting the exponentials, which have type exp_table_t - init_invert_table(invert_table); - initialized = true; - } - - // Calculate all the e^x's - typename CONFIG_T::exp_table_t exp_res[CONFIG_T::n_in]; - #pragma HLS array_partition variable=exp_res complete - typename CONFIG_T::exp_table_t exp_sum(0); - for(unsigned i = 0; i < CONFIG_T::n_in; i++){ - #pragma HLS unroll - unsigned x = softmax_idx_from_real_val(data[i]); - exp_res[i] = exp_table[x]; - } - - // Explicitly sum the results with an adder tree. - // Rounding & Saturation mode, which improve accuracy, prevent Vivado from expression balancing - Op_add op_add; - exp_sum = reduce>(exp_res, op_add); - - typename CONFIG_T::inv_table_t inv_exp_sum = invert_table[softmax_idx_from_real_val(exp_sum)]; - for(unsigned i = 0; i < CONFIG_T::n_in; i++){ - #pragma HLS unroll - res[i] = exp_res[i] * inv_exp_sum; - } -} - -template -void softmax_stable(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]){ - #pragma HLS pipeline - // Initialize the lookup tables -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::exp_table_t exp_table[CONFIG_T::table_size]; - typename CONFIG_T::inv_table_t invert_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::exp_table_t exp_table[CONFIG_T::table_size]; - static typename CONFIG_T::inv_table_t invert_table[CONFIG_T::table_size]; - -#endif - if (!initialized) { - // Note we are exponentiating the inputs, which have type data_T - init_exp_table(exp_table); - // Note we are inverting the exponentials, which have type exp_table_t - init_invert_table(invert_table); - initialized = true; - } - - // Find the max and compute all delta(x_i, x_max) - Op_max op_max; - data_T x_max = reduce>(data, op_max); - - // For the diffs, use the same type as the input but force rounding and saturation - ap_fixed d_xi_xmax[CONFIG_T::n_in]; - for(unsigned i = 0; i < CONFIG_T::n_in; i++){ - #pragma HLS unroll - d_xi_xmax[i] = data[i] - x_max; - } - - // Calculate all the e^x's - typename CONFIG_T::exp_table_t exp_res[CONFIG_T::n_in]; - #pragma HLS array_partition variable=exp_res complete - typename CONFIG_T::exp_table_t exp_sum(0); - for(unsigned i = 0; i < CONFIG_T::n_in; i++){ - #pragma HLS unroll - unsigned x = softmax_idx_from_real_val(d_xi_xmax[i]); - exp_res[i] = exp_table[x]; - } - - // Explicitly sum the results with an adder tree. - // Rounding & Saturation mode, which improve accuracy, prevent Vivado from expression balancing - Op_add op_add; - exp_sum = reduce>(exp_res, op_add); - - typename CONFIG_T::inv_table_t inv_exp_sum = invert_table[softmax_idx_from_real_val(exp_sum)]; - for(unsigned i = 0; i < CONFIG_T::n_in; i++){ - #pragma HLS unroll - res[i] = exp_res[i] * inv_exp_sum; - } -} - -template -void init_exp_table_legacy(typename CONFIG_T::table_t table_out[N_TABLE]) -{ - for (int ii = 0; ii < N_TABLE; ii++) { - // First, convert from table index to X-value (signed 8-bit, range -8 to +8) - float in_val = 2*8.0*(ii-float(N_TABLE)/2.0)/float(N_TABLE); - // Next, compute lookup table function - typename CONFIG_T::table_t real_val = exp_fcn_float(in_val); - //std::cout << "Lookup table In Value: " << in_val << " Result: " << real_val << std::endl; - table_out[ii] = real_val; - } -} - -template -void init_invert_table_legacy(typename CONFIG_T::table_t table_out[N_TABLE]) -{ - // Inversion function: - // result = 1/x - for (int ii = 0; ii < N_TABLE; ii++) { - // First, convert from table index to X-value (signed 8-bit, range 0 to +64) - float in_val = 64.0*ii/float(N_TABLE); - // Next, compute lookup table function - if (in_val > 0.0) table_out[ii] = 1.0/in_val; - else table_out[ii] = 0.0; - } -} - -template -void softmax_legacy(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t exp_table[CONFIG_T::table_size]; - typename CONFIG_T::table_t invert_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t exp_table[CONFIG_T::table_size]; - static typename CONFIG_T::table_t invert_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_exp_table_legacy(exp_table); - init_invert_table_legacy(invert_table); - initialized = true; - } - - if (CONFIG_T::io_type == io_parallel){ - // Note: This is going to be a resource hog to run with pipeline, but hey, whatever - #pragma HLS PIPELINE - } - - // Index into the lookup table based on data for exponentials - typename CONFIG_T::table_t exp_res[CONFIG_T::n_in];// different, independent, fixed point precision - typename CONFIG_T::table_t exp_diff_res;// different, independent, fixed point precision - data_T data_cache[CONFIG_T::n_in]; - int data_round; - int index; - for (int ii=0; ii CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - exp_diff_res = exp_table[index]; - } - exp_res[ii] += exp_diff_res; - } - } - - //Second loop to invert - for (int ii=0; ii CONFIG_T::table_size-1) exp_res_index = CONFIG_T::table_size-1; - //typename CONFIG_T::table_t exp_res_invert = invert_table[exp_res_index]; - res[ii] = (res_T) invert_table[exp_res_index]; - } - -} - -template -void softmax(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]){ - #pragma HLS inline - switch(CONFIG_T::implementation){ - case softmax_implementation::latency: - softmax_latency(data, res); - break; - case softmax_implementation::stable: - softmax_stable(data, res); - break; - case softmax_implementation::legacy: - softmax_legacy(data, res); - break; - } -} - -// ************************************************* -// TanH Activation -// ************************************************* -template -void init_tanh_table(typename CONFIG_T::table_t table_out[N_TABLE]) -{ - // Implement tanh lookup - for (int ii = 0; ii < N_TABLE; ii++) { - // First, convert from table index to X-value (signed 8-bit, range -4 to +4) - float in_val = 2*4.0*(ii-float(N_TABLE)/2.0)/float(N_TABLE); - // Next, compute lookup table function - typename CONFIG_T::table_t real_val = tanh(in_val); - //std::cout << "Tanh: Lookup table Index: " << ii<< " In Value: " << in_val << " Result: " << real_val << std::endl; - table_out[ii] = real_val; - } -} - - -template -void tanh(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t tanh_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t tanh_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_tanh_table(tanh_table); - initialized = true; - } - - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - // Index into the lookup table based on data - int data_round; - int index; - for (int ii=0; ii CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - res[ii] = (res_T) tanh_table[index]; - } -} - -// ************************************************* -// Hard sigmoid Activation -// ************************************************* -template -void hard_sigmoid(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - data_T datareg; - data_T slope = (data_T) 0.2; - data_T shift = (data_T) 0.5; - for (int ii=0; ii 1) datareg = 1; - else if (datareg < 0) datareg = 0; - res[ii] = datareg; - } -} - -// ************************************************* -// Leaky RELU Activation -// ************************************************* -template -void leaky_relu(data_T data[CONFIG_T::n_in], data_T alpha, res_T res[CONFIG_T::n_in]) -{ - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - data_T datareg; - for (int ii=0; ii 0) res[ii] = datareg; - else res[ii] = alpha * datareg; - } -} - -// ************************************************* -// Thresholded RELU Activation -// ************************************************* -template -void thresholded_relu(data_T data[CONFIG_T::n_in], data_T theta, res_T res[CONFIG_T::n_in]) -{ - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - data_T datareg; - for (int ii=0; ii theta) res[ii] = datareg; - else res[ii] = 0; - } -} - -// ************************************************* -// Softplus Activation -// ************************************************* -inline float softplus_fcn_float(float input) { - return std::log(std::exp(input) + 1.); -} - -template -void init_softplus_table(typename CONFIG_T::table_t table_out[N_TABLE]) -{ - // Default softplus function: - // result = log(exp(x) + 1) - for (int ii = 0; ii < N_TABLE; ii++) { - // First, convert from table index to X-value (signed 8-bit, range -8 to +8) - float in_val = 2*8.0*(ii-float(N_TABLE)/2.0)/float(N_TABLE); - // Next, compute lookup table function - typename CONFIG_T::table_t real_val = softplus_fcn_float(in_val); - //std::cout << "Lookup table In Value: " << in_val << " Result: " << real_val << std::endl; - table_out[ii] = real_val; - } -} - -template -void softplus(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t softplus_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t softplus_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_softplus_table(softplus_table); - initialized = true; - } - - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - // Index into the lookup table based on data - int data_round; - int index; - for (int ii=0; ii CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - res[ii] = (res_T) softplus_table[index]; - } -} - -// ************************************************* -// Softsign Activation -// ************************************************* -inline float softsign_fcn_float(float input) { - return input / (std::abs(input) + 1.); -} - -template -void init_softsign_table(typename CONFIG_T::table_t table_out[N_TABLE]) -{ - // Default softsign function: - // result = x / (abs(x) + 1) - for (int ii = 0; ii < N_TABLE; ii++) { - // First, convert from table index to X-value (signed 8-bit, range -8 to +8) - float in_val = 2*8.0*(ii-float(N_TABLE)/2.0)/float(N_TABLE); - // Next, compute lookup table function - typename CONFIG_T::table_t real_val = softsign_fcn_float(in_val); - //std::cout << "Lookup table In Value: " << in_val << " Result: " << real_val << std::endl; - table_out[ii] = real_val; - } -} - -template -void softsign(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t softsign_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t softsign_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_softsign_table(softsign_table); - initialized = true; - } - - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - // Index into the lookup table based on data - int data_round; - int index; - for (int ii=0; ii CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - res[ii] = (res_T) softsign_table[index]; - } -} - -// ************************************************* -// ELU Activation -// ************************************************* -inline float elu_fcn_float(float input) { - return std::exp(input) - 1.; -} - -template -void init_elu_table(typename CONFIG_T::table_t table_out[N_TABLE]) -{ - // Default ELU function: - // result = alpha * (e^(x) - 1) - for (int ii = 0; ii < N_TABLE; ii++) { - // First, convert from table index to X-value (signed 8-bit, range -8 to 0) - float in_val = -8.0*ii/float(N_TABLE); - // Next, compute lookup table function - typename CONFIG_T::table_t real_val = elu_fcn_float(in_val); - //std::cout << "Lookup table In Value: " << in_val << " Result: " << real_val << std::endl; - table_out[ii] = real_val; - } -} - -template -void elu(data_T data[CONFIG_T::n_in], const res_T alpha, res_T res[CONFIG_T::n_in]) -{ - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t elu_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t elu_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_elu_table(elu_table); - initialized = true; - } - - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - data_T datareg; - // Index into the lookup table based on data - int index; - for (int ii=0; ii= 0) { - res[ii] = datareg; - } else { - index = datareg*CONFIG_T::table_size/-8; - if (index > CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - res[ii] = alpha * elu_table[index]; - } - } -} - -template -void elu(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - elu(data, 1.0, res); -} - -// ************************************************* -// SELU Activation -// ************************************************* -inline float selu_fcn_float(float input) { - return 1.0507009873554804934193349852946 * (1.6732632423543772848170429916717 * (std::exp(input) - 1.)); -} - -template -void init_selu_table(typename CONFIG_T::table_t table_out[N_TABLE]) -{ - // Default SELU function: - // result = 1.05 * (1.673 * (e^(x) - 1)) - for (int ii = 0; ii < N_TABLE; ii++) { - // First, convert from table index to X-value (signed 8-bit, range -8 to 0) - float in_val = -8.0*ii/float(N_TABLE); - // Next, compute lookup table function - typename CONFIG_T::table_t real_val = selu_fcn_float(in_val); - //std::cout << "Lookup table In Value: " << in_val << " Result: " << real_val << std::endl; - table_out[ii] = real_val; - } -} - -template -void selu(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t selu_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t selu_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_selu_table(selu_table); - initialized = true; - } - - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - data_T datareg; - // Index into the lookup table based on data - int index; - for (int ii=0; ii= 0) { - res[ii] = res_T(1.0507009873554804934193349852946) * datareg; - } else { - index = datareg*CONFIG_T::table_size/-8; - if (index > CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - res[ii] = selu_table[index]; - } - } -} - -// ************************************************* -// PReLU Activation -// ************************************************* -template -void prelu(data_T data[CONFIG_T::n_in], data_T alpha[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - data_T datareg; - for (int ii=0; ii 0) res[ii] = datareg; - else res[ii] = alpha[ii] * datareg; - } -} - -// ************************************************* -// Binary TanH Activation -// ************************************************* -template -void binary_tanh(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - data_T datareg; - res_T cache; - for (int ii=0; ii 0 ) cache = 1; - else cache = -1; - - res[ii] = (res_T) cache; - } -} - -// ************************************************* -// Ternary TanH Activation -// ************************************************* -template -void ternary_tanh(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in]) -{ - - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - } - - data_T datareg; - res_T cache; - for (int ii=0; ii 1 ) cache = 1; - else if( datareg > -1 && datareg <= 1) cache=0; - else cache = -1; - - res[ii] = (res_T) cache; - } - -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_activation_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_activation_stream.h deleted file mode 100644 index e213803..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_activation_stream.h +++ /dev/null @@ -1,643 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_ACTIVATION_STREAM_H_ -#define NNET_ACTIVATION_STREAM_H_ - -#include -#include "ap_fixed.h" -#include "hls_stream.h" -#include "nnet_common.h" -#include "nnet_types.h" -#include "nnet_stream.h" -#include "nnet_activation.h" - -namespace nnet { - -// ************************************************* -// LINEAR Activation -// ************************************************* -template -void linear(hls::stream &data, hls::stream &res) { - LinearActLoop: for (int i = 0; i < CONFIG_T::n_in / res_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - LinearPackLoop: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - out_data[j] = in_data[j]; - } - - res.write(out_data); - } -} - - -// ************************************************* -// RELU Activation -// ************************************************* -template -void relu(hls::stream &data, hls::stream &res) { - ReLUActLoop: for (int i = 0; i < CONFIG_T::n_in / res_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - ReLUPackLoop: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - if (in_data[j] > 0) out_data[j] = in_data[j]; - else out_data[j] = 0; - } - - res.write(out_data); - } -} - -// ************************************************* -// Sigmoid Activation -// ************************************************* - -template -void sigmoid(hls::stream &data, hls::stream &res) { - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t sigmoid_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t sigmoid_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_sigmoid_table(sigmoid_table); - initialized = true; - } - - SigmoidActLoop: for (int i = 0; i < CONFIG_T::n_in / res_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - SigmoidPackLoop: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - int data_round = in_data[j]*CONFIG_T::table_size/16; - int index = data_round + 8*CONFIG_T::table_size/16; - if (index < 0) index = 0; - else if (index > CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - out_data[j] = sigmoid_table[index]; - } - - res.write(out_data); - } -} - - -// ************************************************* -// Softmax Activation -// ************************************************* - -template -void softmax_latency(hls::stream &data, hls::stream &res){ - // Initialize the lookup tables -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::exp_table_t exp_table[CONFIG_T::table_size]; - typename CONFIG_T::inv_table_t invert_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::exp_table_t exp_table[CONFIG_T::table_size]; - static typename CONFIG_T::inv_table_t invert_table[CONFIG_T::table_size]; - -#endif - if (!initialized) { - // Note we are exponentiating the inputs, which have type data_T - init_exp_table(exp_table); - // Note we are inverting the exponentials, which have type exp_table_t - init_invert_table(invert_table); - initialized = true; - } - - constexpr unsigned multiplier_limit = DIV_ROUNDUP(data_T::size, CONFIG_T::reuse_factor); - constexpr unsigned ii = data_T::size / multiplier_limit; - - // Calculate all the e^x's - typename CONFIG_T::exp_table_t exp_res[data_T::size]; - #pragma HLS array_partition variable=exp_res complete - typename CONFIG_T::exp_table_t exp_sum(0); - SoftmaxExpLoop: for(unsigned i = 0; i < CONFIG_T::n_in / data_T::size; i++){ - #pragma HLS PIPELINE II=ii - - data_T in_pack = data.read(); - SoftmaxExpPackLoop: for(unsigned j = 0; j < data_T::size; j++){ - #pragma HLS UNROLL - unsigned x = softmax_idx_from_real_val(in_pack[j]); - exp_res[j] = exp_table[x]; - } - - // Explicitly sum the results with an adder tree. - // Rounding & Saturation mode, which improve accuracy, prevent Vivado from expression balancing - Op_add op_add; - exp_sum = reduce>(exp_res, op_add); - - typename CONFIG_T::inv_table_t inv_exp_sum = invert_table[softmax_idx_from_real_val(exp_sum)]; - - res_T out_pack; - #pragma HLS DATA_PACK variable=out_pack - SoftmaxInvPackLoop: for(unsigned j = 0; j < res_T::size; j++){ - #pragma HLS UNROLL - #pragma HLS ALLOCATION instances=mul limit=multiplier_limit operation - out_pack[j] = exp_res[j] * inv_exp_sum; - } - res.write(out_pack); - } -} - -template -void softmax_stable(hls::stream &data, hls::stream &res){ - // Initialize the lookup tables -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::exp_table_t exp_table[CONFIG_T::table_size]; - typename CONFIG_T::inv_table_t invert_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::exp_table_t exp_table[CONFIG_T::table_size]; - static typename CONFIG_T::inv_table_t invert_table[CONFIG_T::table_size]; - -#endif - if (!initialized) { - // Note we are exponentiating the inputs, which have type data_T - init_exp_table(exp_table); - // Note we are inverting the exponentials, which have type exp_table_t - init_invert_table(invert_table); - initialized = true; - } - - constexpr unsigned multiplier_limit = DIV_ROUNDUP(data_T::size, CONFIG_T::reuse_factor); - constexpr unsigned ii = data_T::size / multiplier_limit; - - typename data_T::value_type data_array[data_T::size]; - #pragma HLS ARRAY_PARTITION variable=data_array complete - SoftmaxArrayLoop: for(unsigned i = 0; i < CONFIG_T::n_in / data_T::size; i++){ - #pragma HLS PIPELINE II=ii - - data_T in_pack = data.read(); - SoftmaxArrayPackLoop: for(unsigned j = 0; j < data_T::size; j++){ - #pragma HLS UNROLL - data_array[j] = in_pack[j]; - } - - // Find the max and compute all delta(x_i, x_max) - Op_max op_max; - typename data_T::value_type x_max = reduce>(data_array, op_max); - - // For the diffs, use the same type as the input but force rounding and saturation - ap_fixed d_xi_xmax[data_T::size]; - for(unsigned j = 0; j < data_T::size; j++){ - #pragma HLS UNROLL - d_xi_xmax[j] = data_array[j] - x_max; - } - - // Calculate all the e^x's - typename CONFIG_T::exp_table_t exp_res[data_T::size]; - #pragma HLS ARRAY_PARTITION variable=exp_res complete - typename CONFIG_T::exp_table_t exp_sum(0); - for(unsigned j = 0; j < data_T::size; j++){ - #pragma HLS UNROLL - unsigned x = softmax_idx_from_real_val(d_xi_xmax[j]); - exp_res[j] = exp_table[x]; - } - - // Explicitly sum the results with an adder tree. - // Rounding & Saturation mode, which improve accuracy, prevent Vivado from expression balancing - Op_add op_add; - exp_sum = reduce>(exp_res, op_add); - - typename CONFIG_T::inv_table_t inv_exp_sum = invert_table[softmax_idx_from_real_val(exp_sum)]; - - res_T out_pack; - #pragma HLS DATA_PACK variable=out_pack - SoftmaxInvPackLoop: for(unsigned j = 0; j < res_T::size; j++){ - #pragma HLS UNROLL - #pragma HLS ALLOCATION instances=mul limit=multiplier_limit operation - out_pack[j] = exp_res[j] * inv_exp_sum; - } - res.write(out_pack); - } -} - -template -void softmax_legacy(hls::stream &data, hls::stream &res) { - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t exp_table[CONFIG_T::table_size]; - typename CONFIG_T::table_t invert_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t exp_table[CONFIG_T::table_size]; - static typename CONFIG_T::table_t invert_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_exp_table_legacy(exp_table); - init_invert_table_legacy(invert_table); - initialized = true; - } - - // Index into the lookup table based on data for exponentials - typename CONFIG_T::table_t exp_res[data_T::size]; - typename CONFIG_T::table_t exp_diff_res; - typename data_T::value_type data_cache[data_T::size]; - - SoftmaxInitLoop: for(unsigned s = 0; s < CONFIG_T::n_in / data_T::size; s++) { - #pragma HLS PIPELINE - data_T in_pack = data.read(); - SoftmaxInitPackLoop: for(unsigned j = 0; j < data_T::size; j++) { - #pragma HLS UNROLL - data_cache[j] = in_pack[j]; - exp_res[j] = 0; - } - - SoftmaxExpLoop: for (int i = 0; i < data_T::size; i++) { - #pragma HLS UNROLL - SoftmaxExpInner: for (int j = 0; j < data_T::size; j++) { - #pragma HLS UNROLL - - if (i == j) { - exp_diff_res = 1; - } else { - int data_round = (data_cache[j] - data_cache[i]) * CONFIG_T::table_size / 16; - int index = data_round + 8 * CONFIG_T::table_size / 16; - if (index < 0) index = 0; - if (index > CONFIG_T::table_size - 1) index = CONFIG_T::table_size - 1; - exp_diff_res = exp_table[index]; - } - - exp_res[i] += exp_diff_res; - } - } - - res_T out_pack; - #pragma HLS DATA_PACK variable=out_pack - SoftmaxInvPackLoop: for(unsigned j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - - int exp_res_index = exp_res[j] * CONFIG_T::table_size / 64; - if (exp_res_index < 0) exp_res_index = 0; - if (exp_res_index > CONFIG_T::table_size - 1) exp_res_index = CONFIG_T::table_size - 1; - - out_pack[j] = (typename res_T::value_type) invert_table[exp_res_index]; - } - res.write(out_pack); - } -} - -template -void softmax(hls::stream &data, hls::stream &res){ - assert(CONFIG_T::axis == -1); - - switch(CONFIG_T::implementation){ - case softmax_implementation::latency: - softmax_latency(data, res); - break; - case softmax_implementation::stable: - softmax_stable(data, res); - break; - case softmax_implementation::legacy: - softmax_legacy(data, res); - break; - } -} - -// ************************************************* -// TanH Activation -// ************************************************* - - -template -void tanh(hls::stream &data, hls::stream &res) { - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t tanh_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t tanh_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_tanh_table(tanh_table); - initialized = true; - } - - TanHActLoop: for (int i = 0; i < CONFIG_T::n_in / res_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - TanHPackLoop: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - int data_round = in_data[j]*CONFIG_T::table_size/8; - int index = data_round + 4*CONFIG_T::table_size/8; - if (index < 0) index = 0; - else if (index > CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - out_data[j] = tanh_table[index]; - } - - res.write(out_data); - } -} - - -// ************************************************* -// Hard sigmoid Activation -// ************************************************* - -template -void hard_sigmoid(hls::stream &data, hls::stream &res) { - typename data_T::value_type slope = (typename data_T::value_type) 0.2; - typename data_T::value_type shift = (typename data_T::value_type) 0.5; - - HardSigmoidActLoop: for (int i = 0; i < CONFIG_T::n_in / res_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - HardSigmoidPackLoop: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - typename data_T::value_type datareg = slope * in_data[j] + shift; - if (datareg > 1) datareg = 1; - else if (datareg < 0) datareg = 0; - out_data[j] = datareg; - } - - res.write(out_data); - } -} - - -// ************************************************* -// Leaky RELU Activation -// ************************************************* - -template -void leaky_relu(hls::stream &data, typename data_T::value_type alpha, hls::stream &res) { - LeakyReLUActLoop: for (int i = 0; i < CONFIG_T::n_in / res_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - LeakyReLUPackLoop: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - if (in_data[j] > 0) out_data[j] = in_data[j]; - else out_data[j] = alpha * in_data[j]; - } - res.write(out_data); - } -} - - -// ************************************************* -// Thresholded RELU Activation -// ************************************************* - -template -void thresholded_relu(hls::stream &data, typename data_T::value_type theta, hls::stream &res) { - ThresholdedReLUActLoop: for (int i = 0; i < CONFIG_T::n_in / res_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - ThresholdedReLUPackLoop: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - if (in_data[j] > theta) out_data[j] = in_data[j]; - else out_data[j] = 0; - } - - res.write(out_data); - } -} - - -// ************************************************* -// Softplus Activation -// ************************************************* - -template -void softplus(hls::stream &data, hls::stream &res) { - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t softplus_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t softplus_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_softplus_table(softplus_table); - initialized = true; - } - - SoftplusActLoop: for (int i = 0; i < CONFIG_T::n_in / res_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - SoftplusPackLoop: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - int data_round = in_data[j]*CONFIG_T::table_size/16; - int index = data_round + 8*CONFIG_T::table_size/16; - if (index < 0) index = 0; - else if (index > CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - out_data[j] = softplus_table[index]; - } - res.write(out_data); - } -} - - -// ************************************************* -// Softsign Activation -// ************************************************* - -template -void softsign(hls::stream &data, hls::stream &res) { - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t softsign_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t softsign_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_softsign_table(softsign_table); - initialized = true; - } - - SoftsignActLoop: for (int i = 0; i < CONFIG_T::n_in / res_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - SoftsignPackLoop: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - int data_round = in_data[j]*CONFIG_T::table_size/16; - int index = data_round + 8*CONFIG_T::table_size/16; - if (index < 0) index = 0; - else if (index > CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - out_data[j] = softsign_table[index]; - } - res.write(out_data); - } -} - - -// ************************************************* -// ELU Activation -// ************************************************* -template -void elu(hls::stream &data, typename data_T::value_type alpha, hls::stream &res) { - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t elu_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t elu_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_elu_table(elu_table); - initialized = true; - } - - EluActLoop: for (int i = 0; i < CONFIG_T::n_in / res_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - EluPackLoop: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - - typename data_T::value_type datareg = in_data[j]; - if (datareg >= 0) { - out_data[j] = datareg; - } else { - int index = datareg*CONFIG_T::table_size/-8; - if (index > CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - out_data[j] = alpha * elu_table[index]; - } - } - res.write(out_data); - } -} - -template -void elu(hls::stream &data, hls::stream &res) { - elu(data, 1.0, res); -} - -// ************************************************* -// SELU Activation -// ************************************************* - -template -void selu(hls::stream &data, hls::stream &res) { - // Initialize the lookup table -#ifdef __HLS_SYN__ - bool initialized = false; - typename CONFIG_T::table_t selu_table[CONFIG_T::table_size]; -#else - static bool initialized = false; - static typename CONFIG_T::table_t selu_table[CONFIG_T::table_size]; -#endif - if (!initialized) { - init_selu_table(selu_table); - initialized = true; - } - - SeluActLoop: for (int i = 0; i < CONFIG_T::n_in / res_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - SeluPackLoop: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - - typename data_T::value_type datareg = in_data[j]; - if (datareg >= 0) { - out_data[j] = (typename data_T::value_type) 1.0507009873554804934193349852946 * datareg; - } else { - int index = datareg*CONFIG_T::table_size/-8; - if (index > CONFIG_T::table_size-1) index = CONFIG_T::table_size-1; - out_data[j] = selu_table[index]; - } - } - res.write(out_data); - } -} - - -// ************************************************* -// PReLU Activation -// ************************************************* - -template -void prelu(hls::stream &data, typename data_T::value_type alpha[CONFIG_T::n_in], hls::stream &res) { - PReLUActLoop: for (int i = 0; i < CONFIG_T::n_in / res_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - PReLUPackLoop: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - if (in_data[j] > 0) out_data[j] = in_data[j]; - else out_data[j] = alpha[i*res_T::size+j] * in_data[j]; - } - res.write(out_data); - } -} - - -} - -#endif \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_array.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_array.h deleted file mode 100644 index e39c534..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_array.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef NNET_ARRAY_H_ -#define NNET_ARRAY_H_ - -#include - -namespace nnet { - -struct transpose_config { - static const unsigned height = 10; - static const unsigned width = 10; - static const unsigned depth = 10; - static constexpr unsigned perm[3] = {2, 0, 1}; -}; - -template -void transpose_2d( - data_T data[CONFIG_T::height * CONFIG_T::width], - data_T data_t[CONFIG_T::height * CONFIG_T::width] -) { - #pragma HLS PIPELINE - - for (int i = 0; i < CONFIG_T::height; i++) { - for (int j = 0; j < CONFIG_T::width; j++) { - data_t[j * CONFIG_T::height + i] = data[i * CONFIG_T::width + j]; - } - } -} - -template -void transpose_3d( - data_T data[CONFIG_T::depth * CONFIG_T::height * CONFIG_T::width], - data_T data_t[CONFIG_T::depth * CONFIG_T::height * CONFIG_T::width] -) { - unsigned dims[3] = { CONFIG_T::depth, CONFIG_T::height, CONFIG_T::width }; - unsigned dims_t[3]; - dims_t[0] = dims[CONFIG_T::perm[0]]; - dims_t[1] = dims[CONFIG_T::perm[1]]; - dims_t[2] = dims[CONFIG_T::perm[2]]; - - int idx[3] = {0}, idx_t[3] = {0}; - for (idx[0] = 0; idx[0] < dims[0]; idx[0]++) { - for (idx[1] = 0; idx[1] < dims[1]; idx[1]++) { - for (idx[2] = 0; idx[2] < dims[2]; idx[2]++) { - idx_t[0] = idx[CONFIG_T::perm[0]]; - idx_t[1] = idx[CONFIG_T::perm[1]]; - idx_t[2] = idx[CONFIG_T::perm[2]]; - - data_t[idx_t[0] * dims_t[1] * dims_t[2] + idx_t[1] * dims_t[2] + idx_t[2]] = data[idx[0] * dims[1] * dims[2] + idx[1] * dims[2] + idx[2]]; - } - } - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_batchnorm.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_batchnorm.h deleted file mode 100644 index 9a5cff0..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_batchnorm.h +++ /dev/null @@ -1,164 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_BATCHNORM_H_ -#define NNET_BATCHNORM_H_ - -#include "nnet_common.h" -#include "nnet_dense.h" -#include "hls_stream.h" -#include - -namespace nnet { - -struct batchnorm_config -{ - // Internal data type definitions - typedef float bias_t; - typedef float scale_t; - - // Layer Sizes - static const unsigned n_in = 10; - static const unsigned n_filt = -1; - - // Resource reuse info - static const unsigned io_type = io_parallel; - static const unsigned reuse_factor = 1; - static const bool store_weights_in_bram = false; - static const unsigned n_zeros = 0; - // partitioning arrays cyclically to go with roll factors? - template - using product = nnet::product::mult; -}; - -template -void normalize( - data_T data[CONFIG_T::n_in], - res_T res[CONFIG_T::n_in], - typename CONFIG_T::scale_t scale[CONFIG_T::n_in], - typename CONFIG_T::bias_t bias[CONFIG_T::n_in] -) -{ - data_T cache; - - // Use a function_instantiate in case it helps to explicitly optimize unchanging weights/biases - #pragma HLS function_instantiate variable=scale,bias - - if (CONFIG_T::io_type == io_parallel) { - // For parallel inputs: - // - completely partition arrays -- target fabric - // - if we have an unroll factor, limit number of multipliers - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - - // #pragma HLS ARRAY_PARTITION variable=weights complete // remove this line for now, it breaks compression sometimes - #pragma HLS ARRAY_PARTITION variable=scale complete - #pragma HLS ARRAY_PARTITION variable=bias complete - - int multiplier_limit = ceil(float(CONFIG_T::n_in) / float(CONFIG_T::reuse_factor)); - CONFIG_T::template product::limit(multiplier_limit); - - } else if (CONFIG_T::io_type == io_serial) { - #pragma HLS ARRAY_RESHAPE variable=scale complete dim=1 - #pragma HLS ARRAY_RESHAPE variable=bias complete dim=1 - #pragma HLS DATAFLOW - } - - // Calcuate result - Result: for (int ires = 0; ires < CONFIG_T::n_in; ires++) { - if (CONFIG_T::io_type == io_serial){ - #pragma HLS UNROLL - #pragma HLS PIPELINE - } - - if (CONFIG_T::n_filt==-1) { - res[ires] = CONFIG_T::template product::product(data[ires], scale[ires]) + bias[ires]; - } else { - int norm_index = ires%CONFIG_T::n_filt; - res[ires] = CONFIG_T::template product::product(data[ires], scale[norm_index]) + bias[norm_index]; - } - } -} - -// **************************************************** -// Merged Batch Normalization and Quantized Tanh -// **************************************************** -struct batchnorm_quantized_tanh_config -{ - // Layer Sizes - static const unsigned n_in = 10; - static const unsigned n_filt = -1; - - // Resource reuse info - static const unsigned io_type = io_parallel; - static const unsigned reuse_factor = 1; - static const unsigned n_zeros = 0; -}; - -template -void normalize_binary_tanh(data_T data[CONFIG_T::n_in], ap_uint<1> res[CONFIG_T::n_in], data_T threshold[CONFIG_T::n_in]) -{ - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - #pragma HLS ARRAY_PARTITION variable=res complete - } - - data_T datareg; - ap_uint<1> cache; - for (int ii=0; ii threshold[norm_index] ) cache = 1; - else cache = 0; - - res[ii] = (ap_uint<1>) cache; - - } -} - -template -void normalize_ternary_tanh(data_T data[CONFIG_T::n_in], ap_int<2> res[CONFIG_T::n_in], data_T threshold_hi[CONFIG_T::n_in], data_T threshold_lo[CONFIG_T::n_in]) -{ - if (CONFIG_T::io_type == io_parallel){ - #pragma HLS PIPELINE - #pragma HLS ARRAY_PARTITION variable=res complete - } - - data_T datareg; - ap_int<2> cache; - for (int ii=0; ii threshold_hi[norm_index] ) cache = 1; - else if( datareg <= threshold_lo[norm_index]) cache = -1; - else cache = 0; - - res[ii] = (ap_int<2>) cache; - - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_batchnorm_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_batchnorm_stream.h deleted file mode 100644 index 382887f..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_batchnorm_stream.h +++ /dev/null @@ -1,134 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_BATCHNORM_STREAM_H_ -#define NNET_BATCHNORM_STREAM_H_ - -#include "nnet_common.h" -#include "nnet_mult.h" -#include "nnet_types.h" -#include "hls_stream.h" - -namespace nnet { - -// **************************************************** -// Streaming Batch Normalization -// **************************************************** - -template -void normalize( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::scale_t scale[CONFIG_T::n_in], - typename CONFIG_T::bias_t bias[CONFIG_T::n_in] -) { - #pragma HLS ARRAY_PARTITION variable=scale complete - #pragma HLS ARRAY_PARTITION variable=bias complete - - constexpr unsigned multiplier_limit = DIV_ROUNDUP(CONFIG_T::n_in, CONFIG_T::reuse_factor); - constexpr unsigned ii = CONFIG_T::n_in / multiplier_limit; - CONFIG_T::template product::limit(multiplier_limit); - - BatchNormLoop: for (int i = 0; i < CONFIG_T::n_in / data_T::size; i++) { - #pragma HLS PIPELINE II=ii - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - BatchNormpack: for (int j = 0; j < data_T::size; j++) { - #pragma HLS UNROLL - int norm_index; - if (CONFIG_T::n_filt==-1) { - norm_index = i * data_T::size + j; - } else { - norm_index = j % CONFIG_T::n_filt; - } - out_data[j] = CONFIG_T::template product::product(in_data[j], scale[norm_index]) + bias[norm_index]; - } - - res.write(out_data); - } -} - -// **************************************************** -// Merged Batch Normalization and Quantized Tanh -// **************************************************** -template -void normalize_binary_tanh( - hls::stream &data, - hls::stream, CONFIG_T::n_in>> &res, - typename data_T::value_type threshold[CONFIG_T::n_in] -) { - #pragma HLS ARRAY_PARTITION variable=threshold complete - - BinaryNormLoop: for (int i = 0; i < CONFIG_T::n_in / data_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - nnet::array, CONFIG_T::n_in> out_data; - #pragma HLS DATA_PACK variable=out_data - - BatchNormPack: for (int j = 0; j < data_T::size; j++) { - #pragma HLS UNROLL - out_data[j] = (in_data[j] > threshold[i * data_T::size + j]) ? 1 : 0; - } - - res.write(out_data); - } -} - -template -void normalize_ternary_tanh( - hls::stream &data, - hls::stream, CONFIG_T::n_in>> &res, - typename data_T::value_type threshold_hi[CONFIG_T::n_in], - typename data_T::value_type threshold_lo[CONFIG_T::n_in] -) { - #pragma HLS ARRAY_PARTITION variable=threshold_hi complete - #pragma HLS ARRAY_PARTITION variable=threshold_lo complete - - TernaryNormLoop: for (int i = 0; i < CONFIG_T::n_in / data_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - nnet::array, CONFIG_T::n_in> out_data; - #pragma HLS DATA_PACK variable=out_data - - BatchNormPack: for (int j = 0; j < data_T::size; j++) { - #pragma HLS UNROLL - - int norm_index = i * data_T::size + j; - - if (in_data[j] > threshold_hi[norm_index]) { - out_data[j] = 1; - } else if (in_data[j] <= threshold_lo[norm_index]) { - out_data[j] = -1; - } else { - out_data[j] = 0; - } - } - - res.write(out_data); - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_common.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_common.h deleted file mode 100644 index 7ad303d..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_common.h +++ /dev/null @@ -1,100 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_COMMON_H_ -#define NNET_COMMON_H_ - -#include "ap_fixed.h" - -// This is a substitute for "ceil(n/(float)d)". -#define DIV_ROUNDUP(n,d) ((n + d - 1) / d) -#define MIN(n,d) (n > d ? d : n) -#define MAX(n,d) (n > d ? n : d) - -namespace nnet { - -// Common type definitions -enum io_type {io_parallel = 0, io_serial, io_stream}; -enum strategy { latency, resource }; - - /* --- - * Balanced tree reduce implementation. - * For use in scenarios where Vivado cannot expression balance - * Reduces an array of inputs to a single value using the template binary operator 'Op', - * for example summing all elements with Op_add, or finding the maximum with Op_max - * Use only when the input array is fully unrolled. Or, slice out a fully unrolled section - * before applying and accumulate the result over the rolled dimension. - * --- */ - template - T reduce(const T* x, Op op) - { - static constexpr int leftN = pow2(floorlog2(N - 1)) > 0 ? pow2(floorlog2(N - 1)) : 0; - static constexpr int rightN = N - leftN > 0 ? N - leftN : 0; - if (N == 1){ - return x[0]; - } - if (N == 2){ - return op(x[0],x[1]); - } - return op(reduce(x, op), reduce(x+leftN, op)); - } - - template - class Op_add{ - public: - T operator()(T a, T b){ - return a + b; - } - }; - - template - class Op_and{ - public: - T operator()(T a, T b){ - return a && b; - } - }; - - template - class Op_or{ - public: - T operator()(T a, T b){ - return a || b; - } - }; - - template - class Op_max{ - public: - T operator()(T a, T b){ - return a >= b ? a : b; - } - }; - - template - class Op_min{ - public: - T operator()(T a, T b){ - return a <= b ? a : b; - } - }; - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv1d.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv1d.h deleted file mode 100644 index fcc1644..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv1d.h +++ /dev/null @@ -1,70 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_CONV1D_H_ -#define NNET_CONV1D_H_ - -#include "nnet_common.h" -#include "nnet_conv1d_latency.h" -#include "nnet_conv1d_resource.h" -#include - -namespace nnet { - -struct conv1d_config -{ - // Internal data type definitions - typedef float bias_t; - typedef float weight_t; - typedef float accum_t; - - // Convolutional parameters - static const unsigned pad_left = 0; - static const unsigned pad_right = 0; - static const unsigned in_width = 10; - static const unsigned n_chan = 0; - static const unsigned filt_width = 1; - static const unsigned kernel_size = filt_width; - static const unsigned n_filt = 1; - static const unsigned stride_width = 1; - static const unsigned dilation = 1; - static const unsigned out_width = 10; //(N_IN + PAD_LEFT * PAD_RIGHT - (DILATION * (FILT_WIDTH - 1) + 1)) / STRIDE + 1 - - static const unsigned reuse_factor = 1; - static const bool store_weights_in_bram = false; - static const unsigned n_zeros = 0; // not used yet -}; - -template -void conv_1d_cl( - data_T data[CONFIG_T::in_width * CONFIG_T::n_chan], - res_T res[CONFIG_T::out_width * CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - if (CONFIG_T::strategy == nnet::latency) { - conv_1d_latency_cl(data, res, weights, biases); - } else { - conv_1d_resource_cl(data, res, weights, biases); - } -} - -}//end namespace - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv1d_latency.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv1d_latency.h deleted file mode 100644 index d4f4d5f..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv1d_latency.h +++ /dev/null @@ -1,195 +0,0 @@ -#ifndef NNET_CONV1D_LATENCY_H_ -#define NNET_CONV1D_LATENCY_H_ - -#include "nnet_common.h" -#include - -namespace nnet { - -//Computes multiplier limit -//This function should not be synthesized into firmware -template -int compute_multiplier_limit( - typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt] -) -{ - int n_mult = 0; - for(int ii = 0; ii < CONFIG_T::out_width; ii++) { - for(int ff = 0; ff < CONFIG_T::n_filt; ff++){ - for(int cc = 0; cc < CONFIG_T::n_chan; cc++){ - for(int jj = 0; jj < CONFIG_T::filt_width; jj++){ - - int index_weight = jj*CONFIG_T::n_chan*CONFIG_T::n_filt + cc*CONFIG_T::n_filt + ff; - - if((ii*CONFIG_T::stride_width+jj) < CONFIG_T::pad_left || (ii*CONFIG_T::stride_width+jj) >= (CONFIG_T::pad_left + CONFIG_T::in_width)){ - //padded -- do nothing - continue; - } else { - //need to tune this cut? - if( weights[index_weight] > 1e-20 || weights[index_weight] < -1e-20 ){ - n_mult++; - }//end if nonzero weight - }//end not padding - }//end loop accross filter - }//end channel loop - }//end filter loop - }//end output loop - - return ceil( float(n_mult) / float(CONFIG_T::reuse_factor) ); - -}//end compute_n_mult - - -template -void conv_1d_latency_cl( - data_T data[CONFIG_T::in_width * CONFIG_T::n_chan], - res_T res[CONFIG_T::out_width * CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt] -) -{ - - typename CONFIG_T::accum_t mult[CONFIG_T::out_width * CONFIG_T::n_filt * CONFIG_T::n_chan * CONFIG_T::filt_width]; - typename CONFIG_T::accum_t acc[CONFIG_T::out_width][CONFIG_T::n_filt]; - - #pragma HLS ARRAY_PARTITION variable=mult complete dim=0 - #pragma HLS ARRAY_PARTITION variable=acc complete dim=0 - - // Use a function_instantiate in case it helps to explicitly optimize unchanging weights/biases - #pragma HLS function_instantiate variable=weights,biases - - // Parallel mode - #pragma HLS PIPELINE - #pragma HLS ARRAY_PARTITION variable=biases complete dim=0 - - // Limit multipliers to control parallelization - const int multiplier_limit = compute_multiplier_limit(weights); - #pragma HLS ALLOCATION instances=mul limit=multiplier_limit operation - - // Convolve, saving all multiplication results to accumulate later - ConvOut: for(int ii = 0; ii < CONFIG_T::out_width; ii++) { - ConvFilt: for(int ff = 0; ff < CONFIG_T::n_filt; ff++){ - ConvChan: for(int cc = 0; cc < CONFIG_T::n_chan; cc++){ - ConvMult: for(int jj = 0; jj < CONFIG_T::filt_width; jj++){ - - int index_mult = ii*CONFIG_T::n_filt*CONFIG_T::n_chan*CONFIG_T::filt_width + ff*CONFIG_T::n_chan*CONFIG_T::filt_width + cc*CONFIG_T::filt_width + jj; - int index_weight = jj*CONFIG_T::n_chan*CONFIG_T::n_filt + cc*CONFIG_T::n_filt + ff; - int index_data = (ii*CONFIG_T::stride_width+jj-CONFIG_T::pad_left) * CONFIG_T::n_chan + cc; - - if((ii*CONFIG_T::stride_width+jj) < CONFIG_T::pad_left || (ii*CONFIG_T::stride_width+jj) >= (CONFIG_T::pad_left + CONFIG_T::in_width)){ - mult[index_mult] = 0; - } - else { - mult[index_mult] = data[index_data] * weights[index_weight]; - } - } - }//end channel loop - }//end filter loop - }//end output loop - - - // Initialize accumulator with input biases - for(int ii = 0; ii < CONFIG_T::out_width; ii++) { - for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - acc[ii][ff]=biases[ff]; - } - } - - - // Accumulate multiplication result - AccumOut: for(int ii = 0; ii < CONFIG_T::out_width; ii++) { - AccumFilt: for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - //Do "dot product" sum within filter and sum over channels - AccumChan: for(int cc = 0; cc < CONFIG_T::n_chan; cc++){ - AccumDot: for(int jj = 0; jj < CONFIG_T::filt_width; jj++){ - int index_mult = ii*CONFIG_T::n_filt*CONFIG_T::n_chan*CONFIG_T::filt_width + ff*CONFIG_T::n_chan*CONFIG_T::filt_width + cc*CONFIG_T::filt_width + jj; - acc[ii][ff] += mult[index_mult]; - }//end dot product loop - }//end channel loop - }//end filter loop - }//end output loop - - - // Cast to "res_t" type - for(int ii = 0; ii < CONFIG_T::out_width; ii++) { - for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - res[ii * CONFIG_T::n_filt + ff] = (res_T)(acc[ii][ff]); - } - } -} - -template -void pointwise_conv_1d_cl( - data_T data[CONFIG_T::in_width * CONFIG_T::n_chan], - res_T res[CONFIG_T::out_width * CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - assert(CONFIG_T::filt_width == 1); - - typename CONFIG_T::accum_t mult[CONFIG_T::out_width * CONFIG_T::n_filt * CONFIG_T::n_chan]; - typename CONFIG_T::accum_t acc[CONFIG_T::out_width][CONFIG_T::n_filt]; - - #pragma HLS ARRAY_PARTITION variable=mult complete dim=0 - #pragma HLS ARRAY_PARTITION variable=acc complete dim=0 - - // Use a function_instantiate in case it helps to explicitly optimize unchanging weights/biases - #pragma HLS function_instantiate variable=weights,biases - - // Parallel mode - #pragma HLS PIPELINE - #pragma HLS ARRAY_PARTITION variable=biases complete dim=0 - - // Limit multipliers to control parallelization - const int multiplier_limit = compute_multiplier_limit(weights); - #pragma HLS ALLOCATION instances=mul limit=multiplier_limit operation - - // Convolve, saving all multiplication results to accumulate later - ConvOut: for(int ii = 0; ii < CONFIG_T::out_width; ii++) { - ConvFilt: for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - ConvChan: for(int cc = 0; cc < CONFIG_T::n_chan; cc++) { - int index_mult = ii*CONFIG_T::n_filt*CONFIG_T::n_chan + ff*CONFIG_T::n_chan + cc; - int index_weight = cc*CONFIG_T::n_filt + ff; - int index_data = (ii*CONFIG_T::stride_width-CONFIG_T::pad_left) * CONFIG_T::n_chan + cc; - - if((ii*CONFIG_T::stride_width) < CONFIG_T::pad_left || (ii*CONFIG_T::stride_width) >= (CONFIG_T::pad_left + CONFIG_T::in_width)){ - mult[index_mult] = 0; - } - else { - mult[index_mult] = data[index_data] * weights[index_weight]; - } - }//end channel loop - }//end filter loop - }//end output loop - - - // Initialize accumulator with input biases - for(int ii = 0; ii < CONFIG_T::out_width; ii++) { - for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - acc[ii][ff]=biases[ff]; - } - } - - - // Accumulate multiplication result - AccumOut: for(int ii = 0; ii < CONFIG_T::out_width; ii++) { - AccumFilt: for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - //Do "dot product" sum within filter and sum over channels - AccumChan: for(int cc = 0; cc < CONFIG_T::n_chan; cc++) { - int index_mult = ii*CONFIG_T::n_filt*CONFIG_T::n_chan + ff*CONFIG_T::n_chan + cc; - acc[ii][ff] += mult[index_mult]; - }//end channel loop - }//end filter loop - }//end output loop - - - // Cast to "res_t" type - for(int ii = 0; ii < CONFIG_T::out_width; ii++) { - for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - res[ii * CONFIG_T::n_filt + ff] = (res_T)(acc[ii][ff]); - } - } -} - -} -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv1d_resource.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv1d_resource.h deleted file mode 100644 index 043812c..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv1d_resource.h +++ /dev/null @@ -1,199 +0,0 @@ -#ifndef NNET_CONV1D_RESOURCE_H_ -#define NNET_CONV1D_RESOURCE_H_ - -#include "nnet_common.h" -#include "nnet_dense.h" - -namespace nnet { - -template -void im2col_1d(data_T data[CONFIG_T::in_width * CONFIG_T::n_chan], data_T data_col[CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::out_width]) { - //int index = 0; - for (int channel = CONFIG_T::n_chan; channel--; data += CONFIG_T::in_width) { - #pragma HLS PIPELINE II=1 rewind - for (int kernel_col = 0; kernel_col < CONFIG_T::filt_width; kernel_col++) { - #pragma HLS UNROLL - int input_col = -CONFIG_T::pad_left + kernel_col * CONFIG_T::dilation; - for (int output_col = CONFIG_T::out_width; output_col; output_col--) { - #pragma HLS UNROLL - if (input_col >= 0 && input_col < CONFIG_T::in_width) { - *(data_col++) = data[input_col]; - //data_col[index] = data[input_col]; - } else { - *(data_col++) = 0; - //data_col[index] = 0; - } - //index++; - input_col += CONFIG_T::stride_width; - } - } - } -} - -template -void conv_1d_full( - data_T data[CONFIG_T::in_width * CONFIG_T::n_chan], - res_T res[CONFIG_T::out_width * CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt] -) -{ - data_T data_conv[CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::out_width]; - data_T data_col[CONFIG_T::filt_width * CONFIG_T::n_chan]; - res_T res_col[CONFIG_T::n_filt]; - - //#pragma HLS ARRAY_PARTITION variable=data_conv complete - #pragma HLS ARRAY_PARTITION variable=data_col complete - #pragma HLS ARRAY_PARTITION variable=res_col complete - - im2col_1d(data, data_conv); - - for (int i = 0; i < CONFIG_T::out_width; i++) { - #pragma HLS UNROLL - for (int j = 0; j < CONFIG_T::filt_width * CONFIG_T::n_chan; j++) { - data_col[j] = data_conv[j * CONFIG_T::out_width + i]; - } - dense_resource(data_col, res_col, weights, biases); - for (int j = 0; j < CONFIG_T::n_filt; j++) { - //res[i * CONFIG_T::n_filt + j] = res_col[j]; - res[j * CONFIG_T::out_width + i] = res_col[j]; // Transposed order - } - } -} - -template -void im2col_1d_cf_idx(data_T data[CONFIG_T::in_width * CONFIG_T::n_chan], data_T data_col[CONFIG_T::filt_width * CONFIG_T::n_chan], const int col) { - ChannelLoop: - for (int channel = 0; channel < CONFIG_T::n_chan; channel++) { - //#pragma HLS UNROLL - #pragma HLS PIPELINE II=1 rewind - KernelLoop: - for (int kernel_col = 0; kernel_col < CONFIG_T::filt_width; kernel_col++) { - #pragma HLS UNROLL - int input_col = -CONFIG_T::pad_left + kernel_col * CONFIG_T::dilation + col * CONFIG_T::stride_width; - if (input_col >= 0 && input_col < CONFIG_T::in_width) { - //*(data_col++) = data[input_col]; - data_col[channel * CONFIG_T::filt_width + kernel_col] = data[channel * CONFIG_T::in_width + input_col]; - } else { - //*(data_col++) = 0; - data_col[channel * CONFIG_T::filt_width + kernel_col] = 0; - } - } - } -} - -template -void im2col_1d_cf(data_T data[CONFIG_T::in_width * CONFIG_T::n_chan], data_T data_col[CONFIG_T::n_chan * CONFIG_T::filt_width], const int col) { - int index = 0; - ChannelLoop: - for (int channel = CONFIG_T::n_chan; channel--; data += CONFIG_T::in_width) { - #pragma HLS UNROLL - KernelLoop: - for (int kernel_col = 0; kernel_col < CONFIG_T::filt_width; kernel_col++) { - int input_col = -CONFIG_T::pad_left + kernel_col * CONFIG_T::dilation + col * CONFIG_T::stride_width; - if (input_col >= 0 && input_col < CONFIG_T::in_width) { - //*(data_col++) = data[input_col]; - data_col[index] = data[input_col]; - } else { - //*(data_col++) = 0; - data_col[index] = 0; - } - index++; - } - } -} - -template -void conv_1d_resource_cf( - data_T data[CONFIG_T::n_chan * CONFIG_T::in_width], - res_T res[CONFIG_T::out_width * CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt] -) -{ - const int nin = CONFIG_T::n_chan * CONFIG_T::filt_width; - const int nout = CONFIG_T::n_filt; - const int rufactor = CONFIG_T::reuse_factor; - const int block_factor = DIV_ROUNDUP(nin*nout, rufactor); - - //#pragma HLS function_instantiate variable=weights,biases - //#pragma HLS RESOURCE variable=weights core=RAM_2P_BRAM Commenting out the deisgnation HLS seems to choose correctly - //#pragma HLS ARRAY_RESHAPE variable=weights block factor=block_factor - //#pragma HLS ARRAY_PARTITION variable=biases complete - - data_T data_col[CONFIG_T::filt_width * CONFIG_T::n_chan]; - res_T res_col[CONFIG_T::n_filt]; - - #pragma HLS ARRAY_PARTITION variable=data_col complete - #pragma HLS ARRAY_PARTITION variable=res_col complete - - ColLoop: - for (int i = 0; i < CONFIG_T::out_width; i++) { - #pragma HLS PIPELINE - im2col_1d_cf(data, data_col, i); - dense_resource(data_col, res_col, weights, biases); - for (int j = 0; j < CONFIG_T::n_filt; j++) { - //res[i * CONFIG_T::n_filt + j] = res_col[j]; - res[j * CONFIG_T::out_width + i] = res_col[j]; // Transposed order - } - } -} - -template -void im2col_1d_cl(data_T data[CONFIG_T::in_width * CONFIG_T::n_chan], data_T data_col[CONFIG_T::filt_width * CONFIG_T::n_chan], const int col) { - int index = 0; - KernelLoop: - for (int kernel_col = 0; kernel_col < CONFIG_T::filt_width; kernel_col++) { - #pragma HLS UNROLL - - ChannelLoop: - for (int channel = 0; channel < CONFIG_T::n_chan; channel++) { - int index_data = (col*CONFIG_T::stride_width+kernel_col-CONFIG_T::pad_left) * CONFIG_T::n_chan + channel; - - if (index_data >= 0 && index_data < CONFIG_T::in_width*CONFIG_T::n_chan) { - data_col[index] = data[index_data]; - } else { - data_col[index] = 0; - } - index++; - } - } -} - -template -void conv_1d_resource_cl( - data_T data[CONFIG_T::in_width * CONFIG_T::n_chan], - res_T res[CONFIG_T::out_width * CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt] -) -{ - const int nin = CONFIG_T::n_chan * CONFIG_T::filt_width; - const int nout = CONFIG_T::n_filt; - const int rufactor = CONFIG_T::reuse_factor; - const int block_factor = DIV_ROUNDUP(nin*nout, rufactor); - - //#pragma HLS function_instantiate variable=weights,biases - //#pragma HLS RESOURCE variable=weights core=RAM_2P_BRAM Commenting out the deisgnation HLS seems to choose correctly - //#pragma HLS ARRAY_RESHAPE variable=weights block factor=block_factor - //#pragma HLS ARRAY_PARTITION variable=biases complete - - data_T data_col[CONFIG_T::filt_width * CONFIG_T::n_chan]; - res_T res_col[CONFIG_T::n_filt]; - - #pragma HLS ARRAY_PARTITION variable=data_col complete - #pragma HLS ARRAY_PARTITION variable=res_col complete - - ColLoop: - for (int i = 0; i < CONFIG_T::out_width; i++) { - #pragma HLS PIPELINE - im2col_1d_cl(data, data_col, i); - dense_resource(data_col, res_col, weights, biases); - for (int j = 0; j < CONFIG_T::n_filt; j++) { - res[i * CONFIG_T::n_filt + j] = res_col[j]; - } - } -} - -} -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv1d_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv1d_stream.h deleted file mode 100644 index e0f6f08..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv1d_stream.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef NNET_CONV1D_STREAM_H_ -#define NNET_CONV1D_STREAM_H_ - -#include "nnet_common.h" -#include "nnet_conv_stream.h" -#include "hls_stream.h" - -namespace nnet { - -template -void compute_scaled_indices_1d( - const unsigned w_idx, - ap_uint *pixel_idx -) { - unsigned wp_idx = w_idx * (data_T::size / CONFIG_T::n_chan); - - ComputeIndex: for (unsigned p = 0; p < data_T::size / CONFIG_T::n_chan; p++) { - #pragma HLS UNROLL - - unsigned sw_idx = scale_index(wp_idx + p); - pixel_idx[p] = CONFIG_T::pixels[sw_idx]; - } -} - -template -void conv_1d_encoded_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - assert(CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - - hls::stream data_window[CONFIG_T::filt_width * CONFIG_T::n_chan]; - const int win_depth = CONFIG_T::out_width; - for (unsigned i_out = 0; i_out < CONFIG_T::filt_width * CONFIG_T::n_chan; i_out++) { - #pragma HLS STREAM variable=data_window[i_out] depth=win_depth - } - - #pragma HLS ARRAY_PARTITION variable=CONFIG_T::pixels complete - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - unsigned outputs_ready = 0; - - ap_uint pixel_idx[data_T::size / CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=pixel_idx complete - - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width / (data_T::size / CONFIG_T::n_chan); i_iw++) { - #pragma HLS LOOP_FLATTEN - if (CONFIG_T::strategy == nnet::latency && data_T::size / CONFIG_T::n_chan == 1) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - } - compute_scaled_indices_1d(i_iw, pixel_idx); - compute_output_encoded(data.read(), data_window, res, res_pack, outputs_ready, weights, biases, pixel_idx); - } -} - -template -void conv_1d_buffer_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - assert(CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width; i_iw++) { - #pragma HLS LOOP_FLATTEN - if (CONFIG_T::strategy == nnet::latency) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - } - compute_output_buffer_1d(data.read(), res, weights, biases); - } -} - -template -void conv_1d_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - #pragma HLS inline region - switch(CONFIG_T::implementation){ - case conv_implementation::linebuffer: - conv_1d_buffer_cl(data, res, weights, biases); - break; - case conv_implementation::encoded: - conv_1d_encoded_cl(data, res, weights, biases); - break; - } -} - -} -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv2d.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv2d.h deleted file mode 100644 index 5ecdc3a..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv2d.h +++ /dev/null @@ -1,91 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_CONV2D_H_ -#define NNET_CONV2D_H_ - -#include "nnet_common.h" -#include "nnet_conv2d_latency.h" -#include "nnet_conv2d_resource.h" -#include - -namespace nnet { - -struct conv2d_config -{ - // Internal data type definitions - typedef float bias_t; - typedef float weight_t; - typedef float accum_t; - - // Convolutional parameters - static const unsigned pad_top = 0; - static const unsigned pad_bottom = 0; - static const unsigned pad_left = 0; - static const unsigned pad_right = 0; - static const unsigned in_height = 10; - static const unsigned in_width = 10; - static const unsigned n_chan = 1; - static const unsigned filt_height = 1; - static const unsigned filt_width = 1; - static const unsigned kernel_size = filt_height * filt_width; - static const unsigned n_filt = 1; - static const unsigned stride_height = 1; - static const unsigned stride_width = 1; - static const unsigned out_height = 10; - static const unsigned out_width = 10; - static const unsigned dilation_height = 1; - static const unsigned dilation_width = 1; - - static const unsigned reuse_factor = 1; - static const bool store_weights_in_bram = false; - static const unsigned n_zeros = 0; // not used yet -}; - -template -void conv_2d_cf( - data_T data[CONFIG_T::in_height * CONFIG_T::in_width * CONFIG_T::n_chan], - res_T res[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - if (CONFIG_T::strategy == nnet::latency) { - conv_2d_latency_cf(data, res, weights, biases); - } else { - conv_2d_resource_cf(data, res, weights, biases); - } -} - -template -void conv_2d_cl( - data_T data[CONFIG_T::in_height * CONFIG_T::in_width * CONFIG_T::n_chan], - res_T res[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - if (CONFIG_T::strategy == nnet::latency) { - conv_2d_latency_cl(data, res, weights, biases); - } else { - conv_2d_resource_cl(data, res, weights, biases); - } -} - -}//end namespace - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv2d_latency.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv2d_latency.h deleted file mode 100644 index 9cd91b8..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv2d_latency.h +++ /dev/null @@ -1,385 +0,0 @@ -#ifndef NNET_CONV2D_LATENCY_H_ -#define NNET_CONV2D_LATENCY_H_ - -#include "nnet_common.h" -#include - -namespace nnet { - -//Computes multiplier limit -//This function should not be synthesized into firmware -template - int compute_multiplier_limit_conv2d( - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt] -) -{ - int n_mult = 0; - - for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - for(int ff = 0; ff < CONFIG_T::n_filt; ff++){ - for(int cc = 0; cc < CONFIG_T::n_chan; cc++){ - for(int fh = 0; fh < CONFIG_T::filt_height; fh++){ - for(int fw = 0; fw < CONFIG_T::filt_width; fw++){ - - int index_weight = fh*CONFIG_T::filt_width*CONFIG_T::n_chan*CONFIG_T::n_filt - + fw*CONFIG_T::n_chan*CONFIG_T::n_filt - + cc*CONFIG_T::n_filt - + ff; - - if ((oh*CONFIG_T::stride_height+fh) < CONFIG_T::pad_top - || (oh*CONFIG_T::stride_height+fh) >= (CONFIG_T::pad_top+CONFIG_T::in_height) - || (ow*CONFIG_T::stride_width+fw) < CONFIG_T::pad_left - || (ow*CONFIG_T::stride_width+fw) >= (CONFIG_T::pad_left+CONFIG_T::in_width)) { - //padded - do nothing - continue; - } else { - if (weights[index_weight] > 1e-20 || weights[index_weight] < -1e-20) { - n_mult++; - } - } - - }//end mult loop - }//end channel loop - }//end filter width loop - }//end filter height loop - }//end output width loop - }//end output height loop - - return ceil( float(n_mult) / float(CONFIG_T::reuse_factor) ); - -}//end compute_n_mult - -template -void conv_2d_latency_cf( - data_T data[CONFIG_T::in_height*CONFIG_T::in_width*CONFIG_T::n_chan], - res_T res[CONFIG_T::out_height*CONFIG_T::out_width*CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - - typename CONFIG_T::accum_t mult[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt * CONFIG_T::n_chan * CONFIG_T::filt_height * CONFIG_T::filt_width]; - typename CONFIG_T::accum_t acc[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt]; - - #pragma HLS ARRAY_PARTITION variable=mult complete dim=0 - #pragma HLS ARRAY_PARTITION variable=acc complete dim=0 - - // Use a function_instantiate in case it helps to explicitly optimize unchanging weights/biases - #pragma HLS function_instantiate variable=weights,biases - - // Parallel mode - #pragma HLS PIPELINE - #pragma HLS ARRAY_PARTITION variable=biases complete dim=0 - - // Limit multipliers to control parallelization - const int multiplier_limit = compute_multiplier_limit_conv2d(weights); - #pragma HLS ALLOCATION instances=mul limit=multiplier_limit operation - - // Convolve, saving all multiplication results to accumulate later - ConvOutHeight: for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - ConvOutWidth: for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - ConvFilt: for(int ff = 0; ff < CONFIG_T::n_filt; ff++){ - ConvChan: for(int cc = 0; cc < CONFIG_T::n_chan; cc++){ - ConvFiltHeight: for(int fh = 0; fh < CONFIG_T::filt_height; fh++){ - ConvFiltWidth: for(int fw = 0; fw < CONFIG_T::filt_width; fw++){ - - int index_mult = oh*CONFIG_T::out_width*CONFIG_T::n_filt*CONFIG_T::n_chan*CONFIG_T::filt_height*CONFIG_T::filt_width - + ow*CONFIG_T::n_filt*CONFIG_T::n_chan*CONFIG_T::filt_height*CONFIG_T::filt_width - + ff*CONFIG_T::n_chan*CONFIG_T::filt_height*CONFIG_T::filt_width - + cc*CONFIG_T::filt_height*CONFIG_T::filt_width - + fh*CONFIG_T::filt_width - + fw; - - int index_weight = fh*CONFIG_T::filt_width*CONFIG_T::n_chan*CONFIG_T::n_filt - + fw*CONFIG_T::n_chan*CONFIG_T::n_filt - + cc*CONFIG_T::n_filt - + ff; - - if ((oh*CONFIG_T::stride_height+fh) < CONFIG_T::pad_top - || (oh*CONFIG_T::stride_height+fh) >= (CONFIG_T::pad_top+CONFIG_T::in_height) - || (ow*CONFIG_T::stride_width+fw) < CONFIG_T::pad_left - || (ow*CONFIG_T::stride_width+fw) >= (CONFIG_T::pad_left+CONFIG_T::in_width)) { - mult[index_mult] = 0; - } else { - int index_data = cc*CONFIG_T::in_height*CONFIG_T::in_width - + (oh*CONFIG_T::stride_height+fh-CONFIG_T::pad_top)*CONFIG_T::in_width - + (ow*CONFIG_T::stride_width+fw-CONFIG_T::pad_left); - mult[index_mult] = data[index_data] * weights[index_weight]; - } - - }//end mult loop - }//end channel loop - }//end filter width loop - }//end filter height loop - }//end output width loop - }//end output height loop - - - // Initialize accumulator with input biases - for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - acc[oh*CONFIG_T::out_width*CONFIG_T::n_filt + ow*CONFIG_T::n_filt + ff]=biases[ff]; - } - } - } - - - // Accumulate multiplication result - AccumOutHeight: for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - AccumOutWidth: for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - AccumFilt: for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - //Do "dot product" sum within filter and sum over channels - AccumChan: for(int cc = 0; cc < CONFIG_T::n_chan; cc++){ - AccumDotHeight: for(int fh = 0; fh < CONFIG_T::filt_height; fh++){ - AccumDotWidth: for(int fw = 0; fw < CONFIG_T::filt_width; fw++){ - - int index_mult = oh*CONFIG_T::out_width*CONFIG_T::n_filt*CONFIG_T::n_chan*CONFIG_T::filt_height*CONFIG_T::filt_width - + ow*CONFIG_T::n_filt*CONFIG_T::n_chan*CONFIG_T::filt_height*CONFIG_T::filt_width - + ff*CONFIG_T::n_chan*CONFIG_T::filt_height*CONFIG_T::filt_width - + cc*CONFIG_T::filt_height*CONFIG_T::filt_width - + fh*CONFIG_T::filt_width - + fw; - int index_acc = oh*CONFIG_T::out_width*CONFIG_T::n_filt - + ow*CONFIG_T::n_filt - + ff; - - acc[index_acc] += mult[index_mult]; - - }//end dot product filter width loop - }//end dot product filter height loop - }//end n channel loop - }//end n filter loop - }//end output width loop - }//end output height loop - - // Cast to "res_t" type - for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - int res_index = ff*CONFIG_T::out_height*CONFIG_T::out_width + oh*CONFIG_T::out_width + ow; - int acc_index = oh*CONFIG_T::out_width*CONFIG_T::n_filt + ow*CONFIG_T::n_filt + ff; - res[res_index] = acc[acc_index]; - } - } - } - -}//end conv2d - -template -void conv_2d_latency_cl( - data_T data[CONFIG_T::in_height*CONFIG_T::in_width*CONFIG_T::n_chan], - res_T res[CONFIG_T::out_height*CONFIG_T::out_width*CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - - typename CONFIG_T::accum_t mult[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt * CONFIG_T::n_chan * CONFIG_T::filt_height * CONFIG_T::filt_width]; - typename CONFIG_T::accum_t acc[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt]; - - #pragma HLS ARRAY_PARTITION variable=mult complete dim=0 - #pragma HLS ARRAY_PARTITION variable=acc complete dim=0 - - // Use a function_instantiate in case it helps to explicitly optimize unchanging weights/biases - #pragma HLS function_instantiate variable=weights,biases - - // Parallel mode - #pragma HLS PIPELINE - #pragma HLS ARRAY_PARTITION variable=biases complete dim=0 - - // Limit multipliers to control parallelization - const int multiplier_limit = compute_multiplier_limit_conv2d(weights); - #pragma HLS ALLOCATION instances=mul limit=multiplier_limit operation - - // Convolve, saving all multiplication results to accumulate later - ConvOutHeight: for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - ConvOutWidth: for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - ConvFilt: for(int ff = 0; ff < CONFIG_T::n_filt; ff++){ - ConvChan: for(int cc = 0; cc < CONFIG_T::n_chan; cc++){ - ConvFiltHeight: for(int fh = 0; fh < CONFIG_T::filt_height; fh++){ - ConvFiltWidth: for(int fw = 0; fw < CONFIG_T::filt_width; fw++){ - - int index_mult = oh*CONFIG_T::out_width*CONFIG_T::n_filt*CONFIG_T::n_chan*CONFIG_T::filt_height*CONFIG_T::filt_width - + ow*CONFIG_T::n_filt*CONFIG_T::n_chan*CONFIG_T::filt_height*CONFIG_T::filt_width - + ff*CONFIG_T::n_chan*CONFIG_T::filt_height*CONFIG_T::filt_width - + cc*CONFIG_T::filt_height*CONFIG_T::filt_width - + fh*CONFIG_T::filt_width - + fw; - - int index_weight = fh*CONFIG_T::filt_width*CONFIG_T::n_chan*CONFIG_T::n_filt - + fw*CONFIG_T::n_chan*CONFIG_T::n_filt - + cc*CONFIG_T::n_filt - + ff; - - if ((oh*CONFIG_T::stride_height+fh) < CONFIG_T::pad_top - || (oh*CONFIG_T::stride_height+fh) >= (CONFIG_T::pad_top+CONFIG_T::in_height) - || (ow*CONFIG_T::stride_width+fw) < CONFIG_T::pad_left - || (ow*CONFIG_T::stride_width+fw) >= (CONFIG_T::pad_left+CONFIG_T::in_width)) { - mult[index_mult] = 0; - } else { - int index_data = (oh*CONFIG_T::stride_height+fh-CONFIG_T::pad_top)*CONFIG_T::in_width*CONFIG_T::n_chan - + (ow*CONFIG_T::stride_width+fw-CONFIG_T::pad_left)*CONFIG_T::n_chan - + cc; - mult[index_mult] = data[index_data] * weights[index_weight]; - } - - }//end mult loop - }//end channel loop - }//end filter width loop - }//end filter height loop - }//end output width loop - }//end output height loop - - - // Initialize accumulator with input biases - for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - acc[oh*CONFIG_T::out_width*CONFIG_T::n_filt + ow*CONFIG_T::n_filt + ff]=biases[ff]; - } - } - } - - - // Accumulate multiplication result - AccumOutHeight: for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - AccumOutWidth: for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - AccumFilt: for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - //Do "dot product" sum within filter and sum over channels - AccumChan: for(int cc = 0; cc < CONFIG_T::n_chan; cc++){ - AccumDotHeight: for(int fh = 0; fh < CONFIG_T::filt_height; fh++){ - AccumDotWidth: for(int fw = 0; fw < CONFIG_T::filt_width; fw++){ - - int index_mult = oh*CONFIG_T::out_width*CONFIG_T::n_filt*CONFIG_T::n_chan*CONFIG_T::filt_height*CONFIG_T::filt_width - + ow*CONFIG_T::n_filt*CONFIG_T::n_chan*CONFIG_T::filt_height*CONFIG_T::filt_width - + ff*CONFIG_T::n_chan*CONFIG_T::filt_height*CONFIG_T::filt_width - + cc*CONFIG_T::filt_height*CONFIG_T::filt_width - + fh*CONFIG_T::filt_width - + fw; - int index_acc = oh*CONFIG_T::out_width*CONFIG_T::n_filt - + ow*CONFIG_T::n_filt - + ff; - - acc[index_acc] += mult[index_mult]; - - }//end dot product filter width loop - }//end dot product filter height loop - }//end n channel loop - }//end n filter loop - }//end output width loop - }//end output height loop - - // Cast to "res_t" type - for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - int index = oh*CONFIG_T::out_width*CONFIG_T::n_filt + ow*CONFIG_T::n_filt + ff; - res[index] = (res_T)(acc[index]); - } - } - } - -}//end conv2d - -template -void pointwise_conv_2d_cl( - data_T data[CONFIG_T::in_height*CONFIG_T::in_width*CONFIG_T::n_chan], - res_T res[CONFIG_T::out_height*CONFIG_T::out_width*CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - - typename CONFIG_T::accum_t mult[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt * CONFIG_T::n_chan]; - typename CONFIG_T::accum_t acc[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt]; - - #pragma HLS ARRAY_PARTITION variable=mult complete dim=0 - #pragma HLS ARRAY_PARTITION variable=acc complete dim=0 - - // Use a function_instantiate in case it helps to explicitly optimize unchanging weights/biases - #pragma HLS function_instantiate variable=weights,biases - - // Parallel mode - #pragma HLS PIPELINE - #pragma HLS ARRAY_PARTITION variable=biases complete dim=0 - - // Limit multipliers to control parallelization - const int multiplier_limit = compute_multiplier_limit_conv2d(weights); - #pragma HLS ALLOCATION instances=mul limit=multiplier_limit operation - - // Convolve, saving all multiplication results to accumulate later - ConvOutHeight: for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - ConvOutWidth: for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - ConvFilt: for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - ConvChan: for(int cc = 0; cc < CONFIG_T::n_chan; cc++) { - - int index_mult = oh*CONFIG_T::out_width*CONFIG_T::n_filt*CONFIG_T::n_chan - + ow*CONFIG_T::n_filt*CONFIG_T::n_chan - + ff*CONFIG_T::n_chan - + cc; - - int index_weight = cc*CONFIG_T::n_filt + ff; - - if ((oh*CONFIG_T::stride_height) < CONFIG_T::pad_top - || (oh*CONFIG_T::stride_height) >= (CONFIG_T::pad_top+CONFIG_T::in_height) - || (ow*CONFIG_T::stride_width) < CONFIG_T::pad_left - || (ow*CONFIG_T::stride_width) >= (CONFIG_T::pad_left+CONFIG_T::in_width)) { - mult[index_mult] = 0; - } else { - int index_data = (oh*CONFIG_T::stride_height-CONFIG_T::pad_top)*CONFIG_T::in_width*CONFIG_T::n_chan - + (ow*CONFIG_T::stride_width-CONFIG_T::pad_left)*CONFIG_T::n_chan - + cc; - mult[index_mult] = data[index_data] * weights[index_weight]; - } - - } - } - } - } - - - // Initialize accumulator with input biases - for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - acc[oh*CONFIG_T::out_width*CONFIG_T::n_filt + ow*CONFIG_T::n_filt + ff]=biases[ff]; - } - } - } - - - // Accumulate multiplication result - AccumOutHeight: for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - AccumOutWidth: for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - AccumFilt: for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - //Do "dot product" sum within filter and sum over channels - AccumChan: for(int cc = 0; cc < CONFIG_T::n_chan; cc++) { - - int index_mult = oh*CONFIG_T::out_width*CONFIG_T::n_filt*CONFIG_T::n_chan - + ow*CONFIG_T::n_filt*CONFIG_T::n_chan - + ff*CONFIG_T::n_chan - + cc; - int index_acc = oh*CONFIG_T::out_width*CONFIG_T::n_filt - + ow*CONFIG_T::n_filt - + ff; - - acc[index_acc] += mult[index_mult]; - - } - } - } - } - - // Cast to "res_t" type - for(int oh = 0; oh < CONFIG_T::out_height; oh++) { - for(int ow = 0; ow < CONFIG_T::out_width; ow++) { - for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - int index = oh*CONFIG_T::out_width*CONFIG_T::n_filt + ow*CONFIG_T::n_filt + ff; - res[index] = (res_T)(acc[index]); - } - } - } - -}//end conv2d - -} -#endif \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv2d_resource.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv2d_resource.h deleted file mode 100644 index a251051..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv2d_resource.h +++ /dev/null @@ -1,216 +0,0 @@ -#ifndef NNET_CONV2D_RESOURCE_H_ -#define NNET_CONV2D_RESOURCE_H_ - -#include "nnet_common.h" -#include "nnet_dense.h" - -namespace nnet { - -template -void im2col_2d( - data_T data[CONFIG_T::in_height * CONFIG_T::in_width * CONFIG_T::n_chan], - data_T data_col[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::out_height * CONFIG_T::out_width]) -{ - const int output_h = (CONFIG_T::in_height + CONFIG_T::pad_top + CONFIG_T::pad_bottom - - (CONFIG_T::dilation_height * (CONFIG_T::filt_height - 1) + 1)) / CONFIG_T::stride_height + 1; - const int output_w = (CONFIG_T::in_width + CONFIG_T::pad_left + CONFIG_T::pad_right - - (CONFIG_T::dilation_width * (CONFIG_T::filt_width - 1) + 1)) / CONFIG_T::stride_width + 1; - const int channel_size = CONFIG_T::in_height * CONFIG_T::in_width; - - for (int channel = CONFIG_T::n_chan; channel--; data += channel_size) { - for (int kernel_row = 0; kernel_row < CONFIG_T::filt_height; kernel_row++) { - for (int kernel_col = 0; kernel_col < CONFIG_T::filt_width; kernel_col++) { - int input_row = -CONFIG_T::pad_top + kernel_row * CONFIG_T::dilation_height; - for (int output_rows = output_h; output_rows; output_rows--) { - if (input_row < 0 || input_row > CONFIG_T::in_height) { - for (int output_cols = output_w; output_cols; output_cols--) { - *(data_col++) = 0; - } - } else { - int input_col = -CONFIG_T::pad_left + kernel_col * CONFIG_T::dilation_width; - for (int output_col = output_w; output_col; output_col--) { - if (input_col >= 0 && input_col < CONFIG_T::in_width) { - *(data_col++) = data[input_row * CONFIG_T::in_width + input_col]; - } else { - *(data_col++) = 0; - } - input_col += CONFIG_T::stride_width; - } - } - input_row += CONFIG_T::stride_height; - } - } - } - } -} - - -template -void conv_2d_full( - data_T data[CONFIG_T::in_height * CONFIG_T::in_width * CONFIG_T::n_chan], - res_T res[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - data_T data_conv[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::out_height * CONFIG_T::out_width]; - data_T data_col[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan]; - res_T res_col[CONFIG_T::n_filt]; - - //#pragma HLS ARRAY_PARTITION variable=data_conv complete - #pragma HLS ARRAY_PARTITION variable=data_col complete - #pragma HLS ARRAY_PARTITION variable=res_col complete - - im2col_2d(data, data_conv); - - for (int i = 0; i < CONFIG_T::out_height * CONFIG_T::out_width; i++) { - for (int j = 0; j < CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan; j++) { - data_col[j] = data[j * CONFIG_T::out_height * CONFIG_T::out_width + i]; - } - dense(data_col, res_col, weights, biases); - for (int j = 0; j < CONFIG_T::n_filt; j++) { - //res[i * CONFIG_T::n_filt + j] = res_col[j]; - res[j * CONFIG_T::out_height * CONFIG_T::out_width + i] = res_col[j]; // Transposed order - } - } -} - -template -void im2col_2d_cf( - data_T data[CONFIG_T::n_chan * CONFIG_T::in_height * CONFIG_T::in_width], - data_T data_col[CONFIG_T::n_chan * CONFIG_T::filt_height * CONFIG_T::filt_width], - const int row, - const int col) -{ - const int channel_size = CONFIG_T::in_height * CONFIG_T::in_width; - int index = 0; - for (int channel = CONFIG_T::n_chan; channel--; data += channel_size) { - #pragma HLS UNROLL - for (int kernel_row = 0; kernel_row < CONFIG_T::filt_height; kernel_row++) { - int input_row = -CONFIG_T::pad_top + kernel_row * CONFIG_T::dilation_height + row * CONFIG_T::stride_height; - for (int kernel_col = 0; kernel_col < CONFIG_T::filt_width; kernel_col++) { - if (input_row < 0 || input_row > CONFIG_T::in_height) { - data_col[index++] = 0; - } else { - int input_col = -CONFIG_T::pad_left + kernel_col * CONFIG_T::dilation_width + col * CONFIG_T::stride_width; - if (input_col >= 0 && input_col < CONFIG_T::in_width) { - //*(data_col++) = data[input_row * CONFIG_T::in_width + input_col]; - data_col[index++] = data[input_row * CONFIG_T::in_width + input_col]; - } else { - //*(data_col++) = 0; - data_col[index++] = 0; - } - input_col += CONFIG_T::stride_width; - } - } - input_row += CONFIG_T::stride_height; - } - } -} - -template -void conv_2d_resource_cf( - data_T data[CONFIG_T::n_chan * CONFIG_T::in_height * CONFIG_T::in_width], - res_T res[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - const int nin = CONFIG_T::n_chan * CONFIG_T::filt_width; - const int nout = CONFIG_T::n_filt; - const int rufactor = CONFIG_T::reuse_factor; - const int block_factor = DIV_ROUNDUP(nin*nout, rufactor); - - //#pragma HLS function_instantiate variable=weights,biases - //#pragma HLS RESOURCE variable=weights core=RAM_2P_BRAM Commenting out the deisgnation HLS seems to choose correctly - //#pragma HLS ARRAY_RESHAPE variable=weights block factor=block_factor - //#pragma HLS ARRAY_PARTITION variable=biases complete - - data_T data_col[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan]; - res_T res_col[CONFIG_T::n_filt]; - - #pragma HLS ARRAY_PARTITION variable=data_col complete - #pragma HLS ARRAY_PARTITION variable=res_col complete - - HeightLoop: - for (int i = 0; i < CONFIG_T::out_height; i++) { - WidthLoop: - for (int j = 0; j < CONFIG_T::out_width; j++) { - #pragma HLS PIPELINE - im2col_2d_cf(data, data_col, i, j); - dense(data_col, res_col, weights, biases); - FiltLoop: - for (int k = 0; k < CONFIG_T::n_filt; k++) { - //res[i * CONFIG_T::out_width * CONFIG_T::n_filt + j * CONFIG_T::n_filt + k] = res_col[k]; - res[k * CONFIG_T::out_height * CONFIG_T::out_width + i * CONFIG_T::out_width + j] = res_col[k]; // Transposed order - } - } - } -} - -template -void im2col_2d_cl( - data_T data[CONFIG_T::in_height * CONFIG_T::in_width * CONFIG_T::n_chan], - data_T data_col[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan], - const int row, - const int col) -{ - int index = 0; - for (int kernel_row = 0; kernel_row < CONFIG_T::filt_height; kernel_row++) { - #pragma HLS UNROLL - int input_row = -CONFIG_T::pad_top + kernel_row * CONFIG_T::dilation_height + row * CONFIG_T::stride_height; - for (int kernel_col = 0; kernel_col < CONFIG_T::filt_width; kernel_col++) { - for (int channel = 0; channel < CONFIG_T::n_chan; channel++) { - if (input_row < 0 || input_row >= CONFIG_T::in_height) { - data_col[index++] = 0; - } else { - int input_col = -CONFIG_T::pad_left + kernel_col * CONFIG_T::dilation_width + col * CONFIG_T::stride_width; - if (input_col >= 0 && input_col < CONFIG_T::in_width) { - data_col[index++] = data[input_row * CONFIG_T::in_width * CONFIG_T::n_chan + input_col * CONFIG_T::n_chan + channel]; - } else { - data_col[index++] = 0; - } - } - } - } - } -} - -template -void conv_2d_resource_cl( - data_T data[CONFIG_T::in_height * CONFIG_T::in_width * CONFIG_T::n_chan], - res_T res[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt], - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - const int nin = CONFIG_T::n_chan * CONFIG_T::filt_width; - const int nout = CONFIG_T::n_filt; - const int rufactor = CONFIG_T::reuse_factor; - const int block_factor = DIV_ROUNDUP(nin*nout, rufactor); - - //#pragma HLS function_instantiate variable=weights,biases - //#pragma HLS RESOURCE variable=weights core=RAM_2P_BRAM Commenting out the deisgnation HLS seems to choose correctly - //#pragma HLS ARRAY_RESHAPE variable=weights block factor=block_factor - //#pragma HLS ARRAY_PARTITION variable=biases complete - - data_T data_col[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan]; - res_T res_col[CONFIG_T::n_filt]; - - #pragma HLS ARRAY_PARTITION variable=data_col complete - #pragma HLS ARRAY_PARTITION variable=res_col complete - - HeightLoop: - for (int i = 0; i < CONFIG_T::out_height; i++) { - WidthLoop: - for (int j = 0; j < CONFIG_T::out_width; j++) { - #pragma HLS PIPELINE - im2col_2d_cl(data, data_col, i, j); - dense(data_col, res_col, weights, biases); - FiltLoop: - for (int k = 0; k < CONFIG_T::n_filt; k++) { - res[i * CONFIG_T::out_width * CONFIG_T::n_filt + j * CONFIG_T::n_filt + k] = res_col[k]; - } - } - } -} - -} -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv2d_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv2d_stream.h deleted file mode 100644 index 5d1c7d1..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv2d_stream.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef NNET_CONV2D_STREAM_H_ -#define NNET_CONV2D_STREAM_H_ - -#include "ap_shift_reg.h" -#include "nnet_common.h" -#include "nnet_conv_stream.h" -#include "hls_stream.h" - -namespace nnet { - -template -void compute_scaled_indices_2d( - const unsigned h_idx, - const unsigned w_idx, - ap_uint *pixel_idx -) { - const unsigned sh_idx = scale_index(h_idx); - unsigned wp_idx = w_idx * (data_T::size / CONFIG_T::n_chan); - - ComputeIndex: for (unsigned p = 0; p < data_T::size / CONFIG_T::n_chan; p++) { - #pragma HLS UNROLL - - unsigned sw_idx = scale_index(wp_idx + p); - pixel_idx[p] = CONFIG_T::pixels[sh_idx * CONFIG_T::min_width + sw_idx]; - } -} - -template -void conv_2d_encoded_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - assert(CONFIG_T::pad_top == 0 && CONFIG_T::pad_bottom == 0 && CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - assert(CONFIG_T::filt_height == CONFIG_T::filt_width); - - hls::stream data_window[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan]; - const int win_depth = CONFIG_T::filt_height * CONFIG_T::out_width; - for (unsigned i_out = 0; i_out < CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan; i_out++) { - #pragma HLS STREAM variable=data_window[i_out] depth=win_depth - } - - #pragma HLS ARRAY_PARTITION variable=CONFIG_T::pixels complete - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - unsigned outputs_ready = 0; - - ap_uint pixel_idx[data_T::size / CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=pixel_idx complete - - ReadInputHeight: for (unsigned i_ih = 0; i_ih < CONFIG_T::in_height; i_ih++) { - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width / (data_T::size / CONFIG_T::n_chan); i_iw++) { - #pragma HLS LOOP_FLATTEN - if (CONFIG_T::strategy == nnet::latency && data_T::size / CONFIG_T::n_chan == 1) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - } - compute_scaled_indices_2d(i_ih, i_iw, pixel_idx); - compute_output_encoded(data.read(), data_window, res, res_pack, outputs_ready, weights, biases, pixel_idx); - } - } -} - -// Line Buffer -template -void conv_2d_buffer_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - assert(CONFIG_T::pad_top == 0 && CONFIG_T::pad_bottom == 0 && CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - - static ap_shift_reg line_buffer[MAX(CONFIG_T::filt_height - 1,1)][CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable = line_buffer complete dim = 2 - - ReadInputHeight: for (unsigned i_ih = 0; i_ih < CONFIG_T::in_height; i_ih++) { - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width; i_iw++) { - #pragma HLS LOOP_FLATTEN - if(CONFIG_T::strategy == nnet::latency) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - } - if (CONFIG_T::filt_height > 1) { - compute_output_buffer_2d(data.read(), line_buffer, res, weights, biases); - } else { - compute_output_buffer_1d(data.read(), res, weights, biases); - } - } - } -} - -template -void conv_2d_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - #pragma HLS inline region - switch(CONFIG_T::implementation){ - case conv_implementation::linebuffer: - conv_2d_buffer_cl(data, res, weights, biases); - break; - case conv_implementation::encoded: - conv_2d_encoded_cl(data, res, weights, biases); - break; - } -} - -} -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv_stream.h deleted file mode 100644 index 862e836..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_conv_stream.h +++ /dev/null @@ -1,375 +0,0 @@ -#ifndef NNET_CONV_STREAM_H_ -#define NNET_CONV_STREAM_H_ - -#include "ap_shift_reg.h" -#include "nnet_common.h" -#include "hls_stream.h" -#include "nnet_dense.h" - -namespace nnet { - -enum class conv_implementation { linebuffer=0, encoded=1}; - -// ************************************************* -// Encoded Implementation (Vlad's) -// ************************************************* -template -unsigned scale_index_K_gte_S(const unsigned idx) { - #pragma HLS INLINE - - if (idx < K - S) { - return idx; - } - - constexpr unsigned nW = ((W - K) / S) * S + K; // Nearest W without unused pixels on the right - constexpr unsigned sW = (DIV_ROUNDUP(K, S) - 1) * S + K; // Scaled W that behaves like original W - if (idx >= nW) { - return sW; - } - - const unsigned r = nW - idx; - if (r <= K - S) { - return sW - r; - } - - return K - S + (idx - (K - S)) % S; -} - -template -unsigned scale_index_K_lt_S(const unsigned idx) { - #pragma HLS INLINE - - if (idx < S - K) { - return idx; - } - - constexpr unsigned nW = ((W - K) / S) * S + K; // Nearest W without unused pixels on the right - constexpr unsigned sW = (DIV_ROUNDUP(S, K) - 1) * S + K; // Scaled W that behaves like original W - if (idx >= nW) { - return sW; - } - - const unsigned r = nW - idx; - if (r <= S - K) { - return sW - r; - } - - return S - K + (idx - (S - K)) % S; -} - -template -unsigned scale_index(const unsigned idx) { - #pragma HLS INLINE - - if (K >= S) { - return scale_index_K_gte_S(idx); - } else { - return scale_index_K_lt_S(idx); - } -} - -template -void mult_buffer( - hls::stream data_window[CONFIG_T::kernel_size * CONFIG_T::n_chan], - res_T& res_pack, - hls::stream& res_stream, - unsigned & outputs_ready, - typename CONFIG_T::weight_t weights[CONFIG_T::kernel_size * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt] -) { - #pragma HLS INLINE - - typename data_T::value_type data[CONFIG_T::kernel_size * CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=data complete - typename res_T::value_type res[CONFIG_T::n_filt]; - #pragma HLS ARRAY_PARTITION variable=res complete - - InitData: for (int id = 0; id < CONFIG_T::kernel_size * CONFIG_T::n_chan; id++) { - #pragma HLS UNROLL - data[id] = data_window[id].read(); - } - - #pragma HLS INLINE region - if (CONFIG_T::strategy == nnet::latency) { - dense_latency(data, res, weights, biases); - } else { - dense_resource(data, res, weights, biases); - } - - CastLoop: for (unsigned jj = 0; jj < CONFIG_T::n_filt; jj++) { - #pragma HLS UNROLL - if (res_T::size / CONFIG_T::n_filt == 1) { - res_pack[jj] = res[jj]; - } else { - res_pack[outputs_ready * CONFIG_T::n_filt + jj] = res[jj]; - } - } - - if (res_T::size / CONFIG_T::n_filt == 1) { - res_stream.write(res_pack); - } else { - if (outputs_ready == (res_T::size / CONFIG_T::n_filt) - 1) { - res_stream.write(res_pack); - outputs_ready = 0; - } else { - outputs_ready++; - } - } -} - -template -void compute_output_encoded( - const data_T& in_elem, - hls::stream data_window[CONFIG_T::kernel_size * CONFIG_T::n_chan], - hls::stream &res, - res_T &res_pack, - unsigned &outputs_ready, - typename CONFIG_T::weight_t weights[CONFIG_T::kernel_size * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt], - ap_uint *pixel_idx -) { - #pragma HLS INLINE - - MultLoop: for (unsigned p = 0; p < data_T::size / CONFIG_T::n_chan; p++) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - CopyDataFilt: for (unsigned f = 0; f < CONFIG_T::kernel_size; f++) { - #pragma HLS UNROLL - CopyDataChan: for (unsigned c = 0; c < CONFIG_T::n_chan; c++) { - #pragma HLS UNROLL - if (pixel_idx[p][f]) data_window[f * CONFIG_T::n_chan + c].write(in_elem[p * CONFIG_T::n_chan + c]); - } - } - if (pixel_idx[p][CONFIG_T::kernel_size - 1]) { - mult_buffer(data_window, res_pack, res, outputs_ready, weights, biases); - } - } -} - - - -// ************************************************* -// Line Buffer Implementation (Phil's) -// ************************************************* -template -void kernel_shift_1d( - const data_T& in_elem, - typename data_T::value_type kernel_window[CONFIG_T::filt_width * CONFIG_T::n_chan] -) { - #pragma HLS inline - #pragma HLS PIPELINE II = 1 - - // Shift kernel_window by one step to the left (manual shift operation) - static const int filt_width = CONFIG_T::filt_width - 1; - KernelShiftWidth: for (int i_iw = 0; i_iw < filt_width; i_iw++) { - #pragma HLS UNROLL - KernelShiftChannel: for (unsigned i_ic = 0; i_ic < CONFIG_T::n_chan; i_ic++) { - // Shift every element in kernel_window to the left - kernel_window[i_iw * CONFIG_T::n_chan + i_ic] = kernel_window[(i_iw + 1) * CONFIG_T::n_chan + i_ic]; - } - } - - // Insert shift_buffer column into right-most column of kernel - static const int lastheight = (CONFIG_T::filt_width - 1) * CONFIG_T::n_chan; - KernelPushChannel: for (int i_ic = 0; i_ic < CONFIG_T::n_chan; i_ic++) { - #pragma HLS UNROLL - kernel_window[lastheight + i_ic] = in_elem[i_ic]; - } -} - -template -void kernel_shift_2d( - typename data_T::value_type shift_buffer[CONFIG_T::filt_height][CONFIG_T::n_chan], - typename data_T::value_type kernel_window[CONFIG_T::filt_width * CONFIG_T::filt_height * CONFIG_T::n_chan] -) { - #pragma HLS inline - - // Shift kernel_window by one step to the left (manual shift operation) - static const int filt_width = CONFIG_T::filt_width - 1; - KernelShiftWidth: for (int i_iw = 0; i_iw < filt_width; i_iw++) { - #pragma HLS PIPELINE II = 1 - KernelShiftHeight: for (unsigned i_ih = 0; i_ih < CONFIG_T::filt_height; i_ih++) { - KernelShiftChannel: for (unsigned i_ic = 0; i_ic < CONFIG_T::n_chan; i_ic++) { - // Shift every element in kernel_window to the left - kernel_window[i_ih * CONFIG_T::filt_width * CONFIG_T::n_chan + i_iw * CONFIG_T::n_chan + i_ic] = kernel_window[i_ih * CONFIG_T::filt_width * CONFIG_T::n_chan + (i_iw + 1) * CONFIG_T::n_chan + i_ic]; - } - } - } - - // Insert shift_buffer column into right-most column of kernel - static const int lastheight = (CONFIG_T::filt_width - 1) * CONFIG_T::n_chan; - KernelPushHeight: for (int i_ih = 0; i_ih < CONFIG_T::filt_height; i_ih++) { - #pragma HLS UNROLL - KernelPushChannel: for (int i_ic = 0; i_ic < CONFIG_T::n_chan; i_ic++) { - kernel_window[lastheight + i_ih * CONFIG_T::filt_width * CONFIG_T::n_chan + i_ic] = shift_buffer[i_ih][i_ic]; - } - } -} - -template -void shift_line_buffer(const data_T& in_elem, - ap_shift_reg line_buffer[MAX(CONFIG_T::filt_height - 1,1)][CONFIG_T::n_chan], - typename data_T::value_type kernel_window[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan] -) { - - #pragma HLS PIPELINE - - // Temporary buffer for popped (shifted) elements - typename data_T::value_type shift_buffer[CONFIG_T::filt_height][CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable = shift_buffer complete dim = 0 - - UpdateBuffer: for (int i_ic = 0; i_ic < CONFIG_T::n_chan; i_ic++) { - #pragma HLS UNROLL - - // Insert pixel(s) at end of shift buffer - shift_buffer[CONFIG_T::filt_height - 1][i_ic] = in_elem[i_ic]; - } - - LineBufferDataIn: for (int i_ic = 0; i_ic < CONFIG_T::n_chan; i_ic++) { - // Shift the shift buffer into the line buffer - LineBufferShift: for (unsigned i_ih = 1; i_ih < CONFIG_T::filt_height; i_ih++) { - #pragma HLS UNROLL - typename data_T::value_type pop_elem = line_buffer[i_ih - 1][i_ic].shift(shift_buffer[CONFIG_T::filt_height - i_ih][i_ic]); // Shift the line buffer, return the popped pixel - shift_buffer[CONFIG_T::filt_height - i_ih - 1][i_ic] = pop_elem; // Popped element placed back into shift_buffer, one row up. - } - } - kernel_shift_2d(shift_buffer, kernel_window); -} - -template -void compute_output_buffer_2d( - const data_T& in_elem, - ap_shift_reg line_buffer[MAX(CONFIG_T::filt_height - 1,1)][CONFIG_T::n_chan], - hls::stream &res_stream, - typename CONFIG_T::weight_t weights[CONFIG_T::kernel_size * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt] -) { - #pragma HLS INLINE - - // Thresholds - const static int lShiftX = CONFIG_T::filt_width - 1; - const static int lShiftY = CONFIG_T::filt_height - 1; - - // Counters - static int pX = 0; // Pixel X - static int pY = 0; // Pixel Y - - static int sX = 0; // Stride X - static int sY = 0; // Stride Y - - static typename data_T::value_type kernel_data[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=kernel_data complete - - typename res_T::value_type res_out[CONFIG_T::n_filt]; - #pragma HLS ARRAY_PARTITION variable=res_out complete dim = 0 - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - - // Add pixel to buffer - nnet::shift_line_buffer(in_elem, line_buffer, kernel_data); - - // Check to see if we have a full kernel - if ( (sX - lShiftX) == 0 && (sY - lShiftY) == 0 && pY > lShiftY - 1 && pX > lShiftX - 1) { - - // Dense multiply - #pragma HLS INLINE region - if (CONFIG_T::strategy == nnet::latency) { - dense_latency(kernel_data, res_out, weights, biases); - } else { - dense_resource(kernel_data, res_out, weights, biases); - } - - // Pack output - CastLoop: for (unsigned i_ic = 0; i_ic < CONFIG_T::n_filt; i_ic++) { - #pragma HLS UNROLL - res_pack[i_ic] = res_out[i_ic]; - } - - // Write output to stream when output ready - res_stream.write(res_pack); - } - - // Counter Housekeeping - if (pX + 1 == CONFIG_T::in_width) // Includes padding, end of line (padded) - { - pX = 0; - sX = 0; - if (pY + 1 == CONFIG_T::in_height) { // Reached bottom of image - pY = 0; - sY = 0; - } else { - pY = pY + 1; - // Update stride (threshold) ? subtract stride : increment stride - sY = ((sY - lShiftY) == 0) ? sY - CONFIG_T::stride_height + 1 : sY + 1; - } - } else { - pX = pX + 1; - // Update stride (threshold) ? subtract stride : increment stride - sX = ((sX - lShiftX) == 0) ? sX - CONFIG_T::stride_width + 1 : sX + 1; - } -} - -// Conv 1D compute output -template -void compute_output_buffer_1d( - const data_T& in_elem, - hls::stream &res_stream, - typename CONFIG_T::weight_t weights[CONFIG_T::kernel_size * CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt] -) { - #pragma HLS INLINE - - // Thresholds - const static int lShiftX = CONFIG_T::filt_width - 1; - - // Counters - static int pX = 0; // pixel counter - static int sX = 0; // stride counter - - static typename data_T::value_type kernel_data[CONFIG_T::filt_width * CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=kernel_data complete - - typename res_T::value_type res_out[CONFIG_T::n_filt]; - #pragma HLS ARRAY_PARTITION variable=res_out complete dim = 0 - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - - // Add pixel to buffer - nnet::kernel_shift_1d(in_elem, kernel_data); - - // Check to see if we have a full kernel - if ( (sX - lShiftX) == 0 && pX > lShiftX - 1 ) { - - // Dense multiply - #pragma HLS INLINE region - if (CONFIG_T::strategy == nnet::latency) { - dense_latency(kernel_data, res_out, weights, biases); - } else { - dense_resource(kernel_data, res_out, weights, biases); - } - - // Pack output - CastLoop: for (unsigned i_ic = 0; i_ic < CONFIG_T::n_filt; i_ic++) { - #pragma HLS UNROLL - res_pack[i_ic] = res_out[i_ic]; - } - - // Write output to stream when output ready - res_stream.write(res_pack); - } - - // Counter Housekeeping - if (pX + 1 == CONFIG_T::in_width) // Includes padding, end of line (padded) - { - pX = 0; - sX = 0; - } else { - pX = pX + 1; - // Update stride (threshold) ? subtract stride : increment stride - sX = ((sX - lShiftX) == 0) ? sX - CONFIG_T::stride_width + 1 : sX + 1; - } -} - -} -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense.h deleted file mode 100644 index deb1c04..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef NNET_DENSE_H_ -#define NNET_DENSE_H_ - -#include "nnet_common.h" -#include "nnet_mult.h" -#include "nnet_dense_latency.h" -#include "nnet_dense_resource.h" -#include "nnet_helpers.h" -#include "hls_stream.h" -#include - -namespace nnet { - -struct dense_config -{ - // Internal data type definitions - typedef float bias_t; - typedef float weight_t; - typedef float accum_t; - - // Layer Sizes - static const unsigned n_in = 10; - static const unsigned n_out = 10; - - // Resource reuse info - static const unsigned io_type = io_parallel; - static const unsigned strategy = latency; - static const unsigned reuse_factor = 1; - static const bool store_weights_in_bram = false; - static const unsigned n_zeros = 0; - // partitioning arrays cyclically to go with roll factors? - // Product function to use - template - using product = nnet::product::mult; -}; - -template -void dense( - data_T data[CONFIG_T::n_in], - res_T res[CONFIG_T::n_out], - typename CONFIG_T::weight_t weights[CONFIG_T::n_in*CONFIG_T::n_out], - typename CONFIG_T::bias_t biases[CONFIG_T::n_out]) -{ - #pragma HLS inline - if (CONFIG_T::strategy == nnet::latency) { - dense_latency(data, res, weights, biases); - } else { - dense_resource(data, res, weights, biases); - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense_compressed.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense_compressed.h deleted file mode 100644 index adfaa0e..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense_compressed.h +++ /dev/null @@ -1,109 +0,0 @@ -// -// hls4ml: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2018 Giuseppe Di Guglielmo -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_COMPRESSED_LAYER_H_ -#define NNET_COMPRESSED_LAYER_H_ - -#include "nnet_common.h" -#include "nnet_dense.h" -#include "hls_stream.h" -#include - -namespace nnet { - -template -void fill_mult(typename CONFIG_T::index_t index, - typename CONFIG_T::accum_t mult[CONFIG_T::n_out], - typename CONFIG_T::accum_t weight) { - for(unsigned k = 0; k < CONFIG_T::n_out; k++) { - #pragma HLS UNROLL - if (k == index) mult[k] += weight; - } -} - -template -void dense_compressed( - data_T data[CONFIG_T::n_in], - res_T res[CONFIG_T::n_out], - typename CONFIG_T::weight_t weights[CONFIG_T::n_nonzeros], - typename CONFIG_T::bias_t biases[CONFIG_T::n_out]) -{ - - const int multiplier_limit = DIV_ROUNDUP(CONFIG_T::n_nonzeros, CONFIG_T::reuse_factor); - - typename CONFIG_T::accum_t acc [CONFIG_T::n_out]; - #pragma HLS ARRAY_PARTITION variable=acc complete - #pragma HLS ARRAY_PARTITION variable=biases complete - #pragma HLS ARRAY_RESHAPE variable=weights block factor=multiplier_limit - //if (CONFIG_T::store_weights_in_bram){ - //#pragma HLS RESOURCE variable=weights core=ROM_1P_BRAM - #pragma HLS data_pack variable=weights struct_level - //} - - InitAccum: - for(unsigned i = 0; i < CONFIG_T::n_out; i++) { - #pragma HLS UNROLL - acc[i] = (typename CONFIG_T::accum_t) (biases[i]); - } - - // Do the compressed matrix-multiply - const int rufactor = CONFIG_T::reuse_factor; - ReuseLoop: - for(unsigned ir = 0; ir < rufactor; ir++) { - #pragma HLS PIPELINE II=1 rewind - - typename CONFIG_T::accum_t mult[CONFIG_T::n_out]; - #pragma HLS ARRAY_PARTITION variable=mult complete - - ResetMult: - for(int imult = 0; imult < CONFIG_T::n_out; imult++) { - #pragma HLS UNROLL - mult[imult] = 0; - } - - CompressedMultLoop: - for(unsigned im = 0; im < multiplier_limit; im++) { - #pragma HLS UNROLL - unsigned w = im * rufactor + ir; - auto row = weights[w].row_index; - auto col = weights[w].col_index; - auto weight_cache = weights[w].weight; - data_T data_cache = data[row]; - //mult[col] += weight_cache * data_cache; - typename CONFIG_T::accum_t prod = CONFIG_T::template product::product(data_cache, weight_cache); - fill_mult(col, mult, prod); - } - - for (int im = 0; im < CONFIG_T::n_out; im++){ - acc[im] += mult[im]; - } - } - - // Cast to "res_t" type - ResultLoop: - for(unsigned i = 0; i < CONFIG_T::n_out; i++){ - #pragma HLS UNROLL - //res[i] = (res_T) (acc[i]); - res[i] = cast(acc[i]); - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense_latency.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense_latency.h deleted file mode 100644 index 4a04671..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense_latency.h +++ /dev/null @@ -1,131 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_DENSE_LATENCY_H_ -#define NNET_DENSE_LATENCY_H_ - -#include "nnet_common.h" -#include "nnet_mult.h" -#include "nnet_helpers.h" -#include "hls_stream.h" -#include - -namespace nnet { - -template -void dense_latency( - data_T data[CONFIG_T::n_in], - res_T res[CONFIG_T::n_out], - typename CONFIG_T::weight_t weights[CONFIG_T::n_in*CONFIG_T::n_out], - typename CONFIG_T::bias_t biases[CONFIG_T::n_out]) -{ - data_T cache; - typename CONFIG_T::accum_t mult[CONFIG_T::n_in*CONFIG_T::n_out]; - typename CONFIG_T::accum_t acc[CONFIG_T::n_out]; - - // Use a function_instantiate in case it helps to explicitly optimize unchanging weights/biases - #pragma HLS function_instantiate variable=weights,biases - - if (CONFIG_T::io_type == io_parallel || CONFIG_T::io_type == io_stream){ - // For parallel inputs: - // - completely partition arrays -- target fabric - // - if we have an unroll factor, limit number of multipliers - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - - // #pragma HLS ARRAY_PARTITION variable=weights complete // remove this line for now, it breaks compression sometimes - #pragma HLS ARRAY_PARTITION variable=biases complete - #pragma HLS ARRAY_PARTITION variable=mult complete - #pragma HLS ARRAY_PARTITION variable=acc complete - - int multiplier_limit = ceil(float(CONFIG_T::n_in*CONFIG_T::n_out) / float(CONFIG_T::reuse_factor)) - floor(float(CONFIG_T::n_zeros) / float(CONFIG_T::reuse_factor)); - CONFIG_T::template product::limit(multiplier_limit); - - } else if (CONFIG_T::io_type == io_serial){ - // Only reduce cycle_factor if n_out is evenly divisible by reuse_factor - // Otherwise, HLS wont be happy - int cycle_factor = CONFIG_T::n_out / CONFIG_T::reuse_factor; - int reused_cycle = DIV_ROUNDUP(CONFIG_T::n_out, CONFIG_T::reuse_factor); - if (cycle_factor != reused_cycle) { - cycle_factor = CONFIG_T::n_out; - } - /*int cycle_factor = CONFIG_T::n_out; - float reused_cycle = CONFIG_T::n_out / CONFIG_T::reuse_factor; - if (reused_cycle == ceil(reused_cycle)){ - // Dont use "ceil" here; as of 2018.2, HLS crashes mysteriously - cycle_factor = cycle_factor / CONFIG_T::reuse_factor; - }*/ - #pragma HLS ARRAY_PARTITION variable=weights cyclic factor=cycle_factor - #pragma HLS ARRAY_PARTITION variable=mult cyclic factor=cycle_factor - #pragma HLS ARRAY_PARTITION variable=acc complete - #pragma HLS DATAFLOW - #pragma HLS STREAM variable=mult depth=1 - #pragma HLS STREAM variable=acc depth=1 - if (CONFIG_T::store_weights_in_bram){ - #pragma HLS RESOURCE variable=weights core=ROM_2P_BRAM - } - } - - // Do the matrix-multiply - Product1: for(int ii = 0; ii < CONFIG_T::n_in; ii++) { - if (CONFIG_T::io_type == io_serial){ - #pragma HLS PIPELINE - } - cache = data[ii]; - Product2: for(int jj = 0; jj < CONFIG_T::n_out; jj++) { - if (CONFIG_T::io_type == io_serial) { - int multiplier_limit = ceil(float(CONFIG_T::n_out) / float(CONFIG_T::reuse_factor)); - CONFIG_T::template product::limit(multiplier_limit); - } - int index = ii*CONFIG_T::n_out+jj; - mult[index] = CONFIG_T::template product::product(cache, weights[index]); - } - } - - // Initialize accumulator with input biases - ResetAccum: for(int iacc = 0; iacc < CONFIG_T::n_out; iacc++) { - if (CONFIG_T::io_type == io_serial){ - #pragma HLS UNROLL - } - acc[iacc] = (typename CONFIG_T::accum_t) biases[iacc]; - } - - // Accumulate multiplication result - Accum1: for(int ii = 0; ii < CONFIG_T::n_in; ii++) { - if (CONFIG_T::io_type == io_serial){ - #pragma HLS PIPELINE - } - Accum2: for(int jj = 0; jj < CONFIG_T::n_out; jj++) { - int index = ii*CONFIG_T::n_out+jj; - acc[jj] += mult[index]; - } - } - - // Cast to "res_t" type - Result: for(int ires = 0; ires < CONFIG_T::n_out; ires++){ - if (CONFIG_T::io_type == io_serial){ - #pragma HLS UNROLL - } - //res[ires] = (res_T) (acc[ires]); - res[ires] = cast(acc[ires]); - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense_resource.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense_resource.h deleted file mode 100644 index 756a627..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense_resource.h +++ /dev/null @@ -1,284 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_DENSE_RESOURCE_H_ -#define NNET_DENSE_RESOURCE_H_ - -#include "nnet_common.h" -#include "nnet_mult.h" -#include "hls_stream.h" -#include -#include - -namespace nnet { - -template -void dense_resource_rf_leq_nin( - data_T data[CONFIG_T::n_in], - res_T res[CONFIG_T::n_out], - typename CONFIG_T::weight_t weights[CONFIG_T::n_in*CONFIG_T::n_out], - typename CONFIG_T::bias_t biases[CONFIG_T::n_out]) { - - const int rufactor = CONFIG_T::reuse_factor; - const int multfactor = MIN(CONFIG_T::n_in,CONFIG_T::reuse_factor); - const int multiplier_limit = DIV_ROUNDUP(CONFIG_T::n_in*CONFIG_T::n_out, multfactor); - const int block_factor = DIV_ROUNDUP(CONFIG_T::n_in*CONFIG_T::n_out, CONFIG_T::reuse_factor); - const int multscale = multiplier_limit/CONFIG_T::n_out; - const int nin = CONFIG_T::n_in; - const int nout = CONFIG_T::n_out; - - assert((multiplier_limit % nout == 0 || rufactor >= nin) && "The current Reuse Factor is not allowed"); - assert((multiplier_limit == block_factor) && "This function is correct only for RF <= N_IN"); - - #pragma HLS function_instantiate variable=weights,biases - //#pragma HLS RESOURCE variable=weights core=RAM_2P_BRAM Commenting out the deisgnation HLS seems to choose correctly - #pragma HLS ARRAY_RESHAPE variable=weights block factor=block_factor - #pragma HLS ARRAY_PARTITION variable=biases complete - - typename CONFIG_T::accum_t acc[CONFIG_T::n_out]; - #pragma HLS ARRAY_PARTITION variable=acc complete - - InitAccum: - for (int iacc = 0; iacc < nout; iacc++) { - #pragma HLS UNROLL - acc[iacc] = (typename CONFIG_T::accum_t) biases[iacc]; - } - - ReuseLoop: - for (int ir = 0; ir < rufactor; ir++) { - #pragma HLS PIPELINE II=1 rewind - - int w_index = ir; - int in_index = ir; - int out_index = 0; - int acc_step = 0; - - MultLoop: - for (int im = 0; im < block_factor; im++) { - #pragma HLS UNROLL - - acc[out_index] += CONFIG_T::template product::product(data[in_index], weights[w_index]); - - // Increment w_index - w_index += rufactor; - // Increment in_index - in_index += rufactor; - if (in_index >= nin) { - in_index = ir; - } - // Increment out_index - if (acc_step + 1 >= multscale) { - acc_step = 0; - out_index++; - } else { - acc_step++; - } - } - } - - // Cast to "res_t" type - Result: - for (int ires = 0; ires < CONFIG_T::n_out; ires++) { - #pragma HLS UNROLL - res[ires] = cast(acc[ires]); - } -} - -template -void dense_resource_rf_gt_nin_rem0( - data_T data[CONFIG_T::n_in], - res_T res[CONFIG_T::n_out], - typename CONFIG_T::weight_t weights[CONFIG_T::n_in*CONFIG_T::n_out], - typename CONFIG_T::bias_t biases[CONFIG_T::n_out]) { - - const int rufactor = MIN(CONFIG_T::reuse_factor, CONFIG_T::n_in * CONFIG_T::n_out); - const int multfactor = MIN(CONFIG_T::n_in,CONFIG_T::reuse_factor); - const int multiplier_limit = DIV_ROUNDUP(CONFIG_T::n_in*CONFIG_T::n_out, multfactor); - const int block_factor = DIV_ROUNDUP(CONFIG_T::n_in*CONFIG_T::n_out, CONFIG_T::reuse_factor); - const int multscale = multiplier_limit/CONFIG_T::n_out; - const int nin = CONFIG_T::n_in; - const int nout = CONFIG_T::n_out; - - assert((multiplier_limit % nout == 0 || rufactor >= nin) && "The current Reuse Factor is not allowed"); - assert((rufactor > nin && rufactor % nin == 0) && "This function is correct only for RF > N_IN && RF % N_IN == 0"); - - #pragma HLS function_instantiate variable=weights,biases - //#pragma HLS RESOURCE variable=weights core=RAM_2P_BRAM Commenting out the deisgnation HLS seems to choose correctly - #pragma HLS ARRAY_RESHAPE variable=weights block factor=block_factor - #pragma HLS ARRAY_PARTITION variable=biases complete - - typename CONFIG_T::accum_t acc[CONFIG_T::n_out]; - #pragma HLS ARRAY_PARTITION variable=acc complete - - InitAccum: - for (int iacc = 0; iacc < nout; iacc++) { - #pragma HLS UNROLL - acc[iacc] = (typename CONFIG_T::accum_t) biases[iacc]; - } - - int w_index; - int in_index = 0; - int out_index; - int outstep = 0; - const int outscale = rufactor / nin; - - int outidx[rufactor]; - IndexLoop: - for (int ir = 0; ir < rufactor; ir++) { - outidx[ir] = outstep; - if ((ir + 1) % nin == 0) { - outstep++; - } - } - - ReuseLoop: - for (int ir = 0; ir < rufactor; ir++) { - #pragma HLS PIPELINE II=1 rewind - - w_index = ir; - out_index = outidx[ir]/*outstep*/; - - MultLoop: - for (int im = 0; im < block_factor; im++) { - #pragma HLS UNROLL - acc[out_index] += CONFIG_T::template product::product(data[in_index], weights[w_index]); - - w_index += rufactor; - if (w_index >= CONFIG_T::n_in * CONFIG_T::n_out) break; // check out of bounds - out_index += outscale; - } - - in_index++; - if (in_index >= nin) { - in_index = 0; - //outstep++; // This causes a huge increase in scheduling and RTL generation times, hence the above workaround. - } - } - - // Cast to "res_t" type - Result: - for (int ires = 0; ires < CONFIG_T::n_out; ires++) { - #pragma HLS UNROLL - res[ires] = cast(acc[ires]); - } -} - -template -void dense_resource_rf_gt_nin( - data_T data[CONFIG_T::n_in], - res_T res[CONFIG_T::n_out], - typename CONFIG_T::weight_t weights[CONFIG_T::n_in*CONFIG_T::n_out], - typename CONFIG_T::bias_t biases[CONFIG_T::n_out]) { - - const int rufactor = CONFIG_T::reuse_factor; - const int multfactor = MIN(CONFIG_T::n_in,CONFIG_T::reuse_factor); - const int multiplier_limit = DIV_ROUNDUP(CONFIG_T::n_in*CONFIG_T::n_out, multfactor); - const int block_factor = DIV_ROUNDUP(CONFIG_T::n_in*CONFIG_T::n_out, CONFIG_T::reuse_factor); - const int multscale = multiplier_limit/CONFIG_T::n_out; - const int nin = CONFIG_T::n_in; - const int nout = CONFIG_T::n_out; - - assert((multiplier_limit % nout == 0 || rufactor >= nin) && "The current Reuse Factor is not allowed"); - assert((rufactor > nin) && "This function is correct only for RF > N_IN"); - - #pragma HLS function_instantiate variable=weights,biases - //#pragma HLS RESOURCE variable=weights core=RAM_2P_BRAM Commenting out the deisgnation HLS seems to choose correctly - #pragma HLS ARRAY_RESHAPE variable=weights block factor=block_factor - #pragma HLS ARRAY_PARTITION variable=biases complete - - typename CONFIG_T::accum_t acc[CONFIG_T::n_out]; - #pragma HLS ARRAY_PARTITION variable=acc complete - - InitAccum: - for (int iacc = 0; iacc < nout; iacc++) { - #pragma HLS UNROLL - acc[iacc] = (typename CONFIG_T::accum_t) biases[iacc]; - } - - ReuseLoop: - for (int ir = 0; ir < rufactor; ir++) { - #pragma HLS PIPELINE II=1 rewind - typename CONFIG_T::accum_t tmpmult[block_factor]; - #pragma HLS ARRAY_PARTITION variable=tmpmult complete - - MultLoop: - for (int im = 0; im < block_factor; im++) { - #pragma HLS UNROLL - int w_index = ir + rufactor * im; - int in_index = w_index % nin; - if (w_index >= CONFIG_T::n_in*CONFIG_T::n_out) continue; // check out of bounds - tmpmult[im] = CONFIG_T::template product::product(data[in_index], weights[w_index]); - } - - typename CONFIG_T::accum_t mult[multiplier_limit]; - #pragma HLS ARRAY_PARTITION variable=mult complete - - ResetMult: - for (int imult = 0; imult < multiplier_limit; imult++) { - #pragma HLS UNROLL - mult[imult] = 0; - } - - AccumLoop1: - for (int im = 0; im < block_factor; im++) { - #pragma HLS UNROLL - int w_index = ir + rufactor * im; - int out_index = w_index / multfactor; - if (out_index >= multiplier_limit) continue; // check out of bounds - mult[out_index] += tmpmult[im]; - } - - AccumLoop2: - for (int im = 0; im < multiplier_limit; im++) { - #pragma HLS UNROLL - //int out_index = im/multscale; // This is the general case - //acc[out_index] += mult[im]; - acc[im] += mult[im]; // If RF > N_IN then multiplier_limit == n_out - } - } - - // Cast to "res_t" type - Result: - for (int ires = 0; ires < CONFIG_T::n_out; ires++) { - #pragma HLS UNROLL - res[ires] = cast(acc[ires]); - } -} - -template -void dense_resource( - data_T data[CONFIG_T::n_in], - res_T res[CONFIG_T::n_out], - typename CONFIG_T::weight_t weights[CONFIG_T::n_in*CONFIG_T::n_out], - typename CONFIG_T::bias_t biases[CONFIG_T::n_out]) { - - #pragma HLS INLINE region - - if (CONFIG_T::reuse_factor <= CONFIG_T::n_in) { - dense_resource_rf_leq_nin(data, res, weights, biases); - } else if (CONFIG_T::reuse_factor % CONFIG_T::n_in == 0) { - dense_resource_rf_gt_nin_rem0(data, res, weights, biases); - } else { - dense_resource_rf_gt_nin(data, res, weights, biases); - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense_stream.h deleted file mode 100644 index 52c96c5..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_dense_stream.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef NNET_DENSE_STREAM_H_ -#define NNET_DENSE_STREAM_H_ - -#include "nnet_common.h" -#include "nnet_types.h" -#include "hls_stream.h" -#include -#include - -namespace nnet { - -template -void dense_wrapper( - data_T data[CONFIG_T::n_in], - res_T res[CONFIG_T::n_out], - typename CONFIG_T::weight_t weights[CONFIG_T::n_in*CONFIG_T::n_out], - typename CONFIG_T::bias_t biases[CONFIG_T::n_out] -) { - #pragma HLS INLINE region - if (CONFIG_T::strategy == nnet::latency) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - dense_latency(data, res, weights, biases); - } else { - dense_resource(data, res, weights, biases); - } -} - -template -void dense( - hls::stream &data_stream, - hls::stream &res_stream, - typename CONFIG_T::weight_t weights[CONFIG_T::n_in*CONFIG_T::n_out], - typename CONFIG_T::bias_t biases[CONFIG_T::n_out]) -{ - typename data_T::value_type data[CONFIG_T::n_in]; - #pragma HLS ARRAY_PARTITION variable=data complete - - typename res_T::value_type res[CONFIG_T::n_out]; - #pragma HLS ARRAY_PARTITION variable=res complete - - DataPrepare: for(int i_in = 0; i_in < CONFIG_T::n_in / data_T::size; i_in++) { - if (CONFIG_T::n_in / data_T::size > 1) { - #pragma HLS PIPELINE - } - data_T data_pack = data_stream.read(); - DataPack: for (int i_pack = 0; i_pack < data_T::size; i_pack++) { - #pragma HLS UNROLL - data[i_in * data_T::size + i_pack] = data_pack[i_pack]; - } - } - - dense_wrapper(data, res, weights, biases); - - ResWrite: for(unsigned i_out = 0; i_out < CONFIG_T::n_out / res_T::size; i_out++) { - if (CONFIG_T::n_out / res_T::size > 1) { - #pragma HLS PIPELINE - } - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - ResPack: for (int i_pack = 0; i_pack < res_T::size; i_pack++) { - #pragma HLS UNROLL - res_pack[i_pack] = res[i_out * res_T::size + i_pack]; - } - res_stream.write(res_pack); - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_garnet.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_garnet.h deleted file mode 100644 index dfd4ced..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_garnet.h +++ /dev/null @@ -1,983 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_GARNET_H_ -#define NNET_GARNET_H_ - -#include "nnet_common.h" -#include "hls_stream.h" -#include "hls_math.h" - -namespace nnet { - namespace garnet_utils { - - template - inline - typename std::enable_if::value>::type - initialize_edge_weights_table(typename CONFIG_T::edge_weight_t edge_weights_table[]) - { - typedef ap_uint index_t; - - unsigned const table_size = (1 << CONFIG_T::distance_width); - - index_t index; - typename CONFIG_T::distance_t distance; - - // edge_weight_t is ap_ufixed with 0 iwidth -> let index 0 be a saturated version of 1 - edge_weights_table[0] = ap_ufixed(1.); - - for (unsigned iw = 1; iw < table_size; ++iw) { - index = iw; - distance.range(CONFIG_T::distance_width - 1, 0) = index.range(CONFIG_T::distance_width - 1, 0); - edge_weights_table[iw] = hls::exp(-distance * distance); - } - } - - template - inline - typename std::enable_if::value>::type - initialize_edge_weights_table(typename CONFIG_T::edge_weight_t edge_weights_table[]) - { - unsigned const table_size = (1 << CONFIG_T::distance_width); - double const step = 64. / table_size; - - typename CONFIG_T::distance_t v = -32.; - for (unsigned iw = 0; iw < table_size; ++iw) { - edge_weights_table[iw] = std::exp(-v * v); - v += step; - } - } - - template - inline - typename std::enable_if::value, typename CONFIG_T::edge_weight_t>::type - get_edge_weight(typename CONFIG_T::distance_t distance, typename CONFIG_T::edge_weight_t edge_weights_table[]) - { - typedef ap_uint index_t; - - index_t index(distance.range(CONFIG_T::distance_width - 1, 0)); - - return edge_weights_table[index]; - } - - template - inline - typename std::enable_if::value, typename CONFIG_T::edge_weight_t>::type - get_edge_weight(typename CONFIG_T::distance_t distance, typename CONFIG_T::edge_weight_t edge_weights_table[]) - { - unsigned const table_size = (1 << CONFIG_T::distance_width); - double const step = 64. / table_size; - - int index = (distance + 32.) / step; - if (index < 0) - index = 0; - else if (index >= table_size) - index = table_size - 1; - - return edge_weights_table[index]; - } - - template - typename CONFIG_T::edge_weight_t - compute_edge_weight(typename CONFIG_T::distance_t distance) - { - if (CONFIG_T::is_stack) { - #pragma HLS INLINE OFF - } -#ifdef __SYNTHESIS__ - typename CONFIG_T::edge_weight_t edge_weights_table[1 << CONFIG_T::distance_width]; - // unsigned const reshape_factor = CONFIG_T::n_aggregators * CONFIG_T::n_in_features * (CONFIG_T::n_vertices / CONFIG_T::reuse_factor); - // #pragma HLS ARRAY_RESHAPE variable=edge_weights_table cyclic factor=reshape_factor dim=1 - bool initialized = false; -#else - static typename CONFIG_T::edge_weight_t edge_weights_table[1 << CONFIG_T::distance_width]; - static bool initialized = false; -#endif - if (not initialized) { - initialize_edge_weights_table(edge_weights_table); - initialized = true; - } - - return get_edge_weight(distance, edge_weights_table); - } - - template - inline - typename std::enable_if::value, dividend_T>::type - normalize_log2(dividend_T dividend, exponent_T exponent) - { - #pragma HLS INLINE - return dividend >> exponent; - } - - template - inline - typename std::enable_if::value, dividend_T>::type - normalize_log2(dividend_T dividend, exponent_T exponent) - { - #pragma HLS INLINE - return dividend / std::pow(2., exponent); - } - - template - struct Means { - typedef E edge_weight_t; - - edge_weight_t edge_weight_mean[CONFIG_T::n_aggregators]; - typename CONFIG_T::aggr_t weighted_feature_mean[CONFIG_T::n_aggregators * CONFIG_T::n_in_features]; - - Means() { - #pragma HLS INLINE - #pragma HLS ARRAY_PARTITION variable=edge_weight_mean complete - #pragma HLS ARRAY_PARTITION variable=weighted_feature_mean complete - #pragma HLS UNROLL region - - Aggregators: - for (unsigned ia = 0; ia < CONFIG_T::n_aggregators; ++ia) { - edge_weight_mean[ia] = 0.; - - InFeatures: - for (unsigned ix = 0; ix < CONFIG_T::n_in_features; ++ix) { - unsigned const iax = ia * CONFIG_T::n_in_features + ix; - weighted_feature_mean[iax] = 0.; - } - } - } - - void set_weight(unsigned, edge_weight_t const&) { - #pragma HLS INLINE - } - - void add_means_normalized(Means const& local) { - #pragma HLS INLINE - // Always called within a pipelined region - no UNROLL needed - - unsigned const log2_unroll_factor = CONFIG_T::n_vertices_width - CONFIG_T::log2_reuse_factor; - - Aggregators: - for (unsigned ia = 0; ia < CONFIG_T::n_aggregators; ++ia) { - edge_weight_mean[ia] += normalize_log2(local.edge_weight_mean[ia], log2_unroll_factor); - - InFeatures: - for (unsigned ix = 0; ix < CONFIG_T::n_in_features; ++ix) { - unsigned const iax = ia * CONFIG_T::n_in_features + ix; - weighted_feature_mean[iax] += normalize_log2(local.weighted_feature_mean[iax], log2_unroll_factor); - } - } - } - - template - typename std::enable_if::type set_means_normalized(nvtx_T const nvtx, arrays_T const& accum) { - #pragma HLS INLINE - #pragma HLS UNROLL region - - // accum comes divided by unroll factor - typename T::norm_t nvtx_norm = (T::n_vertices / T::reuse_factor) / nvtx; - - Aggregators: - for (unsigned ia = 0; ia < T::n_aggregators; ++ia) { - edge_weight_mean[ia] = accum.edge_weight_mean[ia] * nvtx_norm; - - InFeatures: - for (unsigned ix = 0; ix < T::n_in_features; ++ix) { - unsigned const iax = ia * T::n_in_features + ix; - - weighted_feature_mean[iax] = accum.weighted_feature_mean[iax] * nvtx_norm; - } - } - } - - template - typename std::enable_if::type set_means_normalized(nvtx_T const nvtx, arrays_T const& accum) { - #pragma HLS INLINE - #pragma HLS UNROLL region - - Aggregators: - for (unsigned ia = 0; ia < T::n_aggregators; ++ia) { - - edge_weight_mean[ia] = normalize_log2(accum.edge_weight_mean[ia], T::log2_reuse_factor); - - InFeatures: - for (unsigned ix = 0; ix < T::n_in_features; ++ix) { - unsigned const iax = ia * T::n_in_features + ix; - - weighted_feature_mean[iax] = normalize_log2(accum.weighted_feature_mean[iax], T::log2_reuse_factor); - } - } - } - }; - - template - struct WeightsAndMeans : public Means { - typedef E edge_weight_t; - - edge_weight_t edge_weights[CONFIG_T::n_vertices * CONFIG_T::n_aggregators]; - - WeightsAndMeans() : Means() { - #pragma HLS INLINE - unsigned const reshape_factor = CONFIG_T::n_aggregators * (CONFIG_T::n_vertices / CONFIG_T::reuse_factor); - #pragma HLS ARRAY_PARTITION variable=edge_weights cyclic factor=reshape_factor - } - - void set_weight(unsigned iva, edge_weight_t const& weight) { - #pragma HLS INLINE - edge_weights[iva] = weight; - } - }; - - - template - struct OutputBiasNormalizer; - - template - struct OutputBiasNormalizer::type> { - typedef typename CONFIG_T::output_transform_biases_t biases_t; - - biases_t const (&output_biases)[CONFIG_T::n_out_features]; - - OutputBiasNormalizer(nvtx_T const) : output_biases{CONFIG_T::output_transform_biases} { - #pragma HLS INLINE - } - }; - - template - struct OutputBiasNormalizer::type> { - typedef typename CONFIG_T::output_transform_biases_t biases_t; - - biases_t output_biases[CONFIG_T::n_out_features]; - - OutputBiasNormalizer(nvtx_T const nvtx) { - #pragma HLS ARRAY_PARTITION variable=output_biases complete - #pragma HLS UNROLL region - - // Cannot add a loop label here due to a Vivado HLS bug, apparently - for (unsigned io = 0; io < CONFIG_T::n_out_features; ++io) { - typename CONFIG_T::aggr_t bias = CONFIG_T::output_transform_biases[io]; - bias *= nvtx; - output_biases[io] = normalize_log2(bias, CONFIG_T::n_vertices_width); - } - } - }; - - template - struct InputDataGetter { - typedef data_T data_t; - - data_T const* dataref; - - InputDataGetter(data_T const* d) : dataref{d} { - #pragma HLS INLINE - } - data_T const& get(unsigned iv, unsigned ix) const { - #pragma HLS INLINE - unsigned const ivx = iv * CONFIG_T::n_in_features + ix; - return dataref[ivx]; - } - }; - - template - struct SingleVertexDataGetter { - typedef data_T data_t; - - data_T const (&dataref)[CONFIG_T::n_in_features]; - - SingleVertexDataGetter(data_T const (&d)[CONFIG_T::n_in_features]) : dataref{d} { - #pragma HLS INLINE - } - data_T const& get(unsigned, unsigned ix) const { - #pragma HLS INLINE - return dataref[ix]; - } - }; - - template - struct OutputResSetter { - typedef res_T res_t; - - res_T* resref; - - OutputResSetter(res_T* r) : resref{r} { - #pragma HLS INLINE - } - void set(unsigned iv, unsigned io, res_T const& acc) { - #pragma HLS INLINE - unsigned const ivo = iv * CONFIG_T::n_out_features + io; - resref[ivo] = acc; - } - }; - - template - struct SingleVertexResSetter { - typedef res_T res_t; - - res_T (&resref)[CONFIG_T::n_out_features]; - - SingleVertexResSetter(res_T (&r)[CONFIG_T::n_out_features]) : resref{r} { - #pragma HLS INLINE - } - void set(unsigned, unsigned io, res_T const& acc) { - #pragma HLS INLINE - resref[io] = acc; - } - }; - - template - inline - void - compute_weights_aggregates( - data_getter_T const& data_getter, - unsigned iv, - arrays_local_T& arrays_local, - arrays_T& arrays - ) - { - #pragma HLS INLINE - - Aggregators: - for (unsigned ia = 0; ia < CONFIG_T::n_aggregators; ++ia) { - typename CONFIG_T::distance_t distance = CONFIG_T::aggregator_distance_biases[ia]; - - InFeatures1: - for (unsigned ix = 0; ix < CONFIG_T::n_in_features; ++ix) { - unsigned const iax = ia * CONFIG_T::n_in_features + ix; - - typename CONFIG_T::distance_t incr = data_getter.get(iv, ix) * CONFIG_T::aggregator_distance_weights[iax]; - - distance += incr; - } - - typename CONFIG_T::edge_weight_t edge_weight = garnet_utils::compute_edge_weight(distance); - - arrays_local.edge_weight_mean[ia] += edge_weight; - - InFeatures2: - for (unsigned ix = 0; ix < CONFIG_T::n_in_features; ++ix) { - unsigned const iax = ia * CONFIG_T::n_in_features + ix; - - typename data_getter_T::data_t incr = data_getter.get(iv, ix) * edge_weight; - - arrays_local.weighted_feature_mean[iax] += incr; - } - - unsigned const iva = iv * CONFIG_T::n_aggregators + ia; - arrays.set_weight(iva, edge_weight); - } - } - - template - inline - typename CONFIG_T::aggr_t - compute_output_base_core( - arrays_T const& arrays, - unsigned io, - unsigned ia - ) - { - #pragma HLS INLINE - #pragma HLS UNROLL region - - unsigned const ioa = io * CONFIG_T::n_aggregators + ia; - typename CONFIG_T::aggr_t aggr = arrays.edge_weight_mean[ia] * CONFIG_T::input_transform_biases[ioa]; - - InFeatures: - for (unsigned ix = 0; ix < CONFIG_T::n_in_features; ++ix) { - unsigned const ioax = ioa * CONFIG_T::n_in_features + ix; - unsigned const iax = ia * CONFIG_T::n_in_features + ix; - - aggr += arrays.weighted_feature_mean[iax] * CONFIG_T::input_transform_weights[ioax]; - } - - return aggr; - } - - template - inline - void - compute_output_base( - arrays_T const& arrays, - typename CONFIG_T::aggr_t output_base[CONFIG_T::n_out_features * CONFIG_T::n_aggregators] - ) - { - #pragma HLS INLINE - #pragma HLS UNROLL region - - OutFeatures: - for (unsigned io = 0; io < CONFIG_T::n_out_features; ++io) { - Aggregators: - for (unsigned ia = 0; ia < CONFIG_T::n_aggregators; ++ia) { - unsigned const ioa = io * CONFIG_T::n_aggregators + ia; - - output_base[ioa] = compute_output_base_core(arrays, io, ia); - } - } - } - - template - inline - void - compute_vertex_output( - arrays_T const& arrays, - unsigned iv, - typename CONFIG_T::aggr_t const output_base[CONFIG_T::n_out_features * CONFIG_T::n_aggregators], - res_setter_T& res_setter - ) - { - #pragma HLS INLINE - - typename arrays_T::edge_weight_t edge_weights[CONFIG_T::n_aggregators]; - #pragma HLS ARRAY_PARTITION variable=edge_weights complete - - Aggregators1: - for (unsigned ia = 0; ia < CONFIG_T::n_aggregators; ++ia) { - unsigned const iva = iv * CONFIG_T::n_aggregators + ia; - - edge_weights[ia] = arrays.edge_weights[iva]; - } - - OutFeatures: - for (unsigned io = 0; io < CONFIG_T::n_out_features; ++io) { - typename res_setter_T::res_t acc = CONFIG_T::output_transform_biases[io]; - - Aggregators2: - for (unsigned ia = 0; ia < CONFIG_T::n_aggregators; ++ia) { - unsigned const ioa = io * CONFIG_T::n_aggregators + ia; - - typename res_setter_T::res_t incr = edge_weights[ia] * output_base[ioa]; - acc += incr; - } - - res_setter.set(iv, io, acc); - } - } - - template - void - aggregate( - data_T const data[CONFIG_T::n_vertices * CONFIG_T::n_in_features], - nvtx_T const nvtx, - arrays_T& arrays - ) - { - InputDataGetter data_getter(data); - - unsigned const unroll_factor = CONFIG_T::n_vertices >> CONFIG_T::log2_reuse_factor; - - Means means_accum; - - VerticesOuter: - for (unsigned ivv = 0; ivv < CONFIG_T::reuse_factor; ++ivv) { - #pragma HLS PIPELINE - - if (ivv * unroll_factor >= nvtx) - break; - - Means means_local; - - VerticesInner: - for (unsigned ir = 0; ir < unroll_factor; ++ir) { - unsigned iv = ivv * unroll_factor + ir; - - if (iv == nvtx) - break; - - compute_weights_aggregates(data_getter, iv, means_local, arrays); - } - - means_accum.add_means_normalized(means_local); - } - - arrays.set_means_normalized(nvtx, means_accum); - } - - template - void - distribute( - nvtx_T const nvtx, - arrays_T const& arrays, - res_T res[CONFIG_T::n_vertices * CONFIG_T::n_out_features] - ) - { - OutputResSetter res_setter(res); - - typename CONFIG_T::aggr_t output_base[CONFIG_T::n_out_features * CONFIG_T::n_aggregators]; - #pragma HLS ARRAY_PARTITION variable=output_base complete - - compute_output_base(arrays, output_base); - - unsigned const unroll_factor = CONFIG_T::n_vertices >> CONFIG_T::log2_reuse_factor; - - VerticesOuter: - for (unsigned ivv = 0; ivv < CONFIG_T::reuse_factor; ++ivv) { - #pragma HLS PIPELINE - - if (ivv * unroll_factor >= nvtx) - break; - - VerticesInner: - for (unsigned ir = 0; ir < unroll_factor; ++ir) { - unsigned iv = ivv * unroll_factor + ir; - - if (iv == nvtx) - break; - - compute_vertex_output(arrays, iv, output_base, res_setter); - } - } - } - - template - void - set_output( - output_biases_T const& output_transform_biases, - arrays_T const& arrays, - res_T res[CONFIG_T::n_out_features] - ) - { - #pragma HLS PIPELINE - - OutFeatures: - for (unsigned io = 0; io < CONFIG_T::n_out_features; ++io) { - res_T acc = output_transform_biases.output_biases[io]; - - Aggregators: - for (unsigned ia = 0; ia < CONFIG_T::n_aggregators; ++ia) { - typename CONFIG_T::aggr_t aggr = compute_output_base_core(arrays, io, ia); - - acc += arrays.edge_weight_mean[ia] * aggr; - } - - res[io] = acc; - } - } - - template - void - distribute_aggregate( - nvtx_T const nvtx, - prev_arrays_T const& prev_arrays, - current_arrays_T& current_arrays - ) - { - typedef typename prev_layer_t::output_t data_T; - - typename prev_layer_t::aggr_t prev_output_base[prev_layer_t::n_out_features * prev_layer_t::n_aggregators]; - #pragma HLS ARRAY_PARTITION variable=prev_output_base complete - - compute_output_base(prev_arrays, prev_output_base); - - unsigned const unroll_factor = current_layer_t::n_vertices >> current_layer_t::log2_reuse_factor; - - Means means_accum; - - VerticesOuter: - for (unsigned ivv = 0; ivv < current_layer_t::reuse_factor; ++ivv) { - #pragma HLS PIPELINE - - if (ivv * unroll_factor >= nvtx) - break; - - Means means_local; - - VerticesInner: - for (unsigned ir = 0; ir < unroll_factor; ++ir) { - unsigned iv = ivv * unroll_factor + ir; - - if (iv == nvtx) - break; - - data_T data[prev_layer_t::n_out_features]; - #pragma HLS ARRAY_PARTITION variable=data complete - - SingleVertexResSetter res_setter(data); - - compute_vertex_output(prev_arrays, iv, prev_output_base, res_setter); - - SingleVertexDataGetter data_getter(data); - - compute_weights_aggregates(data_getter, iv, means_local, current_arrays); - } - - means_accum.add_means_normalized(means_local); - } - - current_arrays.set_means_normalized(nvtx, means_accum); - } - - template - inline - typename std::enable_if::value>::type - sublayer( - nvtx_T const nvtx, - prev_arrays_T const& prev_arrays, - last_arrays_T& last_arrays - ) - { - #pragma HLS INLINE - - distribute_aggregate(nvtx, prev_arrays, last_arrays); - } - - template - inline - typename std::enable_if::value>::type - sublayer( - nvtx_T const nvtx, - prev_arrays_T const& prev_arrays, - last_arrays_T& last_arrays - ) - { - #pragma HLS INLINE - - WeightsAndMeans current_arrays; - - distribute_aggregate(nvtx, prev_arrays, current_arrays); - - sublayer(nvtx, current_arrays, last_arrays); - } - } - - struct garnet_config - { - // Layer specs - static const unsigned n_vertices_width = 8; - static const unsigned n_vertices = (1 << n_vertices_width); - static const unsigned n_in_features = 4; - static const unsigned n_propagate = 4; - static const unsigned n_aggregators = 4; - static const unsigned n_out_features = 4; - static const unsigned distance_width = 12; - - // Internal data type definitions - typedef float input_transform_weights_t; - typedef float input_transform_biases_t; - typedef float output_transform_weights_t; - typedef float output_transform_biases_t; - typedef float aggregator_distance_weights_t; - typedef float aggregator_distance_biases_t; - - typedef float norm_t; - typedef float distance_t; - typedef float edge_weight_t; - typedef float edge_weight_aggr_t; - typedef float aggr_t; - typedef float output_t; - - /* static const input_transform_weights_t (&input_transform_weights)[n_out_features * n_aggregators * n_in_features]; */ - /* static const input_transform_biases_t (&input_transform_biases)[n_out_features * n_aggregators]; */ - /* static const aggregator_distance_weights_t (&aggregator_distance_weights)[n_aggregators * n_in_features]; */ - /* static const aggregator_distance_biases_t (&aggregator_distance_biases)[n_aggregators]; */ - /* static const output_transform_biases_t (&output_transform_biases)[n_out_features]; */ - - enum OutputCollapse { - no_collapse, - collapse_mean, - collapse_max - }; - - static const unsigned output_collapse = no_collapse; - - static const bool mean_by_nvert = false; - static const bool is_stack = false; - - // Optimization specs - static const unsigned reuse_factor = 64; - static const unsigned log2_reuse_factor = 6; - }; - - // vertices -> vertices - template - typename std::enable_if::type - garnet( - data_T const data[CONFIG_T::n_vertices * CONFIG_T::n_in_features], - nvtx_T const nvtx[1], - res_T res[CONFIG_T::n_vertices * CONFIG_T::n_out_features] - ) - { - #pragma HLS DATAFLOW - - garnet_utils::WeightsAndMeans arrays; - - garnet_utils::aggregate( - data, - nvtx[0], - arrays - ); - - garnet_utils::distribute( - nvtx[0], - arrays, - res - ); - } - - // vertices -> out features - template - typename std::enable_if::type - garnet( - data_T const data[CONFIG_T::n_vertices * CONFIG_T::n_in_features], - nvtx_T const nvtx[1], - res_T res[CONFIG_T::n_out_features] - ) - { - #pragma HLS DATAFLOW - - garnet_utils::Means arrays; - - garnet_utils::aggregate( - data, - nvtx[0], - arrays - ); - - garnet_utils::OutputBiasNormalizer normalize_bias(nvtx[0]); - - garnet_utils::set_output( - normalize_bias, - arrays, - res - ); - } - - // vertices -> vertices - template - typename std::enable_if::type - garnet_stack( - data_T const data[CONFIG_T::n_vertices * CONFIG_T::n_in_features], - nvtx_T const nvtx[1], - res_T res[CONFIG_T::n_vertices * CONFIG_T::n_out_features] - ) - { - #pragma HLS DATAFLOW - - typedef typename CONFIG_T::template sublayer_t<0> first_layer_t; - unsigned const ilast = CONFIG_T::n_sublayers - 1; - typedef typename CONFIG_T::template sublayer_t last_layer_t; - - garnet_utils::WeightsAndMeans arrays_first; - garnet_utils::Means arrays_last; - - garnet_utils::aggregate( - data, - nvtx[0], - arrays_first - ); - - garnet_utils::sublayer( - nvtx[0], - arrays_first, - arrays_last - ); - - garnet_utils::distribute( - nvtx[0], - arrays_last, - res - ); - } - - // vertices -> out features - template - typename std::enable_if::type - garnet_stack( - data_T const data[CONFIG_T::n_vertices * CONFIG_T::n_in_features], - nvtx_T const nvtx[1], - res_T res[CONFIG_T::n_out_features] - ) - { - #pragma HLS DATAFLOW - - typedef typename CONFIG_T::template sublayer_t<0> first_layer_t; - unsigned const ilast = CONFIG_T::n_sublayers - 1; - typedef typename CONFIG_T::template sublayer_t last_layer_t; - - garnet_utils::WeightsAndMeans arrays_first; - garnet_utils::Means arrays_last; - - garnet_utils::aggregate( - data, - nvtx[0], - arrays_first - ); - - garnet_utils::sublayer( - nvtx[0], - arrays_first, - arrays_last - ); - - garnet_utils::OutputBiasNormalizer normalize_bias(nvtx[0]); - - garnet_utils::set_output( - normalize_bias, - arrays_last, - res - ); - } - - /* Reference (dumb) implementation returning (Vertices, Features) */ - template - typename std::enable_if::type - garnet_ref( - data_T const data[CONFIG_T::n_vertices * CONFIG_T::n_in_features], - nvtx_T const nvtx[1], - res_T res[CONFIG_T::n_vertices * CONFIG_T::n_out_features] - ) - { - typename CONFIG_T::edge_weight_t edge_weights[CONFIG_T::n_vertices * CONFIG_T::n_aggregators]; - typename CONFIG_T::aggr_t propagated_features[CONFIG_T::n_vertices * CONFIG_T::n_propagate]; - - for (unsigned iv = 0; iv < CONFIG_T::n_vertices; ++iv) { - if (iv == nvtx[0]) - break; - - for (unsigned ip = 0; ip < CONFIG_T::n_propagate; ++ip) { - unsigned const ivp = iv * CONFIG_T::n_propagate + ip; - - propagated_features[ivp] = CONFIG_T::input_transform_biases[ip]; - - for (unsigned ix = 0; ix < CONFIG_T::n_in_features; ++ix) { - unsigned const ivx = iv * CONFIG_T::n_in_features + ix; - unsigned const ipx = ip * CONFIG_T::n_in_features + ix; - - propagated_features[ivp] += data[ivx] * CONFIG_T::input_transform_weights[ipx]; - } - } - - for (unsigned ia = 0; ia < CONFIG_T::n_aggregators; ++ia) { - unsigned const iva = iv * CONFIG_T::n_aggregators + ia; - - typename CONFIG_T::aggr_t distance = CONFIG_T::aggregator_distance_biases[ia]; - - for (unsigned ix = 0; ix < CONFIG_T::n_in_features; ++ix) { - unsigned const ivx = iv * CONFIG_T::n_in_features + ix; - unsigned const iax = ia * CONFIG_T::n_in_features + ix; - - distance += data[ivx] * CONFIG_T::aggregator_distance_weights[iax]; - } - - edge_weights[iva] = garnet_utils::compute_edge_weight(distance); - } - } - - typename CONFIG_T::aggr_t aggregated_features[CONFIG_T::n_aggregators * CONFIG_T::n_propagate]; - - for (unsigned ia = 0; ia < CONFIG_T::n_aggregators; ++ia) { - for (unsigned ip = 0; ip < CONFIG_T::n_propagate; ++ip) { - unsigned const iap = ia * CONFIG_T::n_propagate + ip; - - aggregated_features[iap] = 0.; - - for (unsigned iv = 0; iv < CONFIG_T::n_vertices; ++iv) { - if (iv == nvtx[0]) - break; - - unsigned const iva = iv * CONFIG_T::n_aggregators + ia; - unsigned const ivp = iv * CONFIG_T::n_propagate + ip; - - aggregated_features[iap] += edge_weights[iva] * propagated_features[ivp]; - } - } - } - - for (unsigned ia = 0; ia < CONFIG_T::n_aggregators; ++ia) { - for (unsigned ip = 0; ip < CONFIG_T::n_propagate; ++ip) { - unsigned const iap = ia * CONFIG_T::n_propagate + ip; - - if (CONFIG_T::mean_by_nvert) - aggregated_features[iap] /= nvtx[0]; - else { - // Not using right shift in case aggr_t is float or double - aggregated_features[iap] /= CONFIG_T::n_vertices; - } - } - } - - for (unsigned iv = 0; iv < CONFIG_T::n_vertices; ++iv) { - if (iv == nvtx[0]) - break; - - for (unsigned io = 0; io < CONFIG_T::n_out_features; ++io) { - unsigned const ivo = iv * CONFIG_T::n_out_features + io; - - typename CONFIG_T::aggr_t acc = CONFIG_T::output_transform_biases[io]; - - for (unsigned ia = 0; ia < CONFIG_T::n_aggregators; ++ia) { - unsigned const iva = iv * CONFIG_T::n_aggregators + ia; - unsigned const ioa = io * CONFIG_T::n_aggregators + ia; - - typename CONFIG_T::aggr_t aggr = 0.; - - for (unsigned ip = 0; ip < CONFIG_T::n_propagate; ++ip) { - unsigned const iap = ia * CONFIG_T::n_propagate + ip; - unsigned const ioap = ioa * CONFIG_T::n_propagate + ip; - - aggr += CONFIG_T::output_transform_weights[ioap] * aggregated_features[iap]; - } - - acc += edge_weights[iva] * aggr; - } - - res[ivo] = acc; - } - } - } - - /* Reference (dumb) implementation returning (Features) - output averaged over vertices already */ - template - typename std::enable_if::type - garnet_ref( - data_T const data[CONFIG_T::n_vertices * CONFIG_T::n_in_features], - nvtx_T const nvtx[1], - res_T res[CONFIG_T::n_out_features] - ) - { - typename CONFIG_T::aggr_t vertex_res[CONFIG_T::n_vertices * CONFIG_T::n_out_features]; - - garnet_ref( - data, - nvtx, - vertex_res - ); - - for (unsigned io = 0; io < CONFIG_T::n_out_features; ++io) { - typename CONFIG_T::aggr_t acc = 0.; - - for (unsigned iv = 0; iv < CONFIG_T::n_vertices; ++iv) { - if (iv == nvtx[0]) - break; - - unsigned const ivo = iv * CONFIG_T::n_out_features + io; - - acc += vertex_res[ivo]; - } - - if (CONFIG_T::mean_by_nvert) - acc /= nvtx[0]; - else { - // Not using right shift in case aggr_t is float or double - acc /= CONFIG_T::n_vertices; - } - - res[io] = acc; - } - } - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_helpers.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_helpers.h deleted file mode 100644 index eed64fc..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_helpers.h +++ /dev/null @@ -1,433 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_HELPERS_H -#define NNET_HELPERS_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include "hls_stream.h" - -namespace nnet { - -#ifndef __SYNTHESIS__ - -#ifndef WEIGHTS_DIR -#define WEIGHTS_DIR "weights" -#endif - -template -void load_weights_from_txt(T *w, const char* fname) { - - std::string full_path = std::string(WEIGHTS_DIR) + "/" + std::string(fname); - std::ifstream infile(full_path.c_str(), std::ios::binary); - - if (infile.fail()) { - std::cerr << "ERROR: file " << std::string(fname) << " does not exist" << std::endl; - exit(1); - } - - std::string line; - if (std::getline(infile, line)) { - std::istringstream iss(line); - std::string token; - - size_t i = 0; - while(std::getline(iss, token, ',')) { - std::istringstream(token) >> w[i]; - i++; - } - - if (SIZE != i) { - std::cerr << "ERROR: Expected " << SIZE << " values"; - std::cerr << " but read only " << i << " values" << std::endl; - } - } -} - -template -void load_compressed_weights_from_txt(T *w, const char* fname) { - - std::string full_path = std::string(WEIGHTS_DIR) + "/" + std::string(fname); - std::ifstream infile(full_path.c_str(), std::ios::binary); - - if (infile.fail()) { - std::cerr << "ERROR: file " << std::string(fname) << " does not exist" << std::endl; - exit(1); - } - - std::string line; - if (std::getline(infile, line)) { - std::istringstream iss(line); - std::string token; - std::string extra_chars = "} "; - - size_t i = 0; - while(std::getline(iss, token, '{')) { - if (token.length() == 0) { - continue; - } - for (char c: extra_chars) { - token.erase(std::remove(token.begin(), token.end(), c), token.end()); - } - if (token.back() == ',') { - token.erase(token.end() - 1); - } - - std::replace(token.begin(), token.end(), ',', ' '); - std::istringstream structss(token); - - if(!(structss >> w[i].row_index >> w[i].col_index >> w[i].weight)) { - std::cerr << "ERROR: Unable to parse file " << std::string(fname); - exit(1); - } - i++; - } - - if (SIZE != i) { - std::cerr << "ERROR: Expected " << SIZE << " values"; - std::cerr << " but read only " << i << " values" << std::endl; - } - } -} - -template -void load_exponent_weights_from_txt(T *w, const char* fname) { - - std::string full_path = std::string(WEIGHTS_DIR) + "/" + std::string(fname); - std::ifstream infile(full_path.c_str(), std::ios::binary); - - if (infile.fail()) { - std::cerr << "ERROR: file " << std::string(fname) << " does not exist" << std::endl; - exit(1); - } - - std::string line; - if (std::getline(infile, line)) { - std::istringstream iss(line); - std::string token; - std::string extra_chars = "} "; - - size_t i = 0; - while(std::getline(iss, token, '{')) { - if (token.length() == 0) { - continue; - } - for (char c: extra_chars) { - token.erase(std::remove(token.begin(), token.end(), c), token.end()); - } - if (token.back() == ',') { - token.erase(token.end() - 1); - } - - std::replace(token.begin(), token.end(), ',', ' '); - std::istringstream structss(token); - - if(!(structss >> w[i].sign >> w[i].weight)) { - std::cerr << "ERROR: Unable to parse file " << std::string(fname); - exit(1); - } - i++; - } - - if (SIZE != i) { - std::cerr << "ERROR: Expected " << SIZE << " values"; - std::cerr << " but read only " << i << " values" << std::endl; - } - } -} -template -void convert_data(srcType *src, dstType *dst) { - for (size_t i = 0; i < SIZE; i++) { - dst[i] = dstType(src[i]); - } -} - -template -void convert_data(srcType *src, hls::stream &dst) { - for (size_t i = 0; i < SIZE / dstType::size; i++) { - dstType ctype; - for (size_t j = 0; j < dstType::size; j++) { - ctype[j] = typename dstType::value_type(src[i * dstType::size + j]); - } - dst.write(ctype); - } -} - -template -void convert_data(hls::stream &src, dstType *dst) { - for (size_t i = 0; i < SIZE / srcType::size; i++) { - srcType ctype = src.read(); - for (size_t j = 0; j < srcType::size; j++) { - dst[i * srcType::size + j] = dstType(ctype[j]); - } - } -} - -extern bool trace_enabled; -extern std::map *trace_outputs; -extern size_t trace_type_size; - -template -void save_output_array(data_T *data, save_T *ptr, size_t layer_size) { - for(int i = 0; i < layer_size; i++) { - ptr[i] = save_T(data[i]); - } -} - -template -void save_output_array(hls::stream &data, save_T *ptr, size_t layer_size) { - for (size_t i = 0; i < layer_size / data_T::size; i++) { - data_T ctype = data.read(); - for (size_t j = 0; j < data_T::size; j++) { - ptr[i * data_T::size + j] = save_T(ctype[j]); - } - data.write(ctype); - } -} - -// We don't want to include save_T in this function because it will be inserted into myproject.cpp -// so a workaround with element size is used -template -void save_layer_output(data_T *data, const char *layer_name, size_t layer_size) { - if (!trace_enabled) return; - - if (trace_outputs) { - if (trace_outputs->count(layer_name) > 0) { - if (trace_type_size == 4) { - save_output_array(data, (float *) (*trace_outputs)[layer_name], layer_size); - } else if (trace_type_size == 8) { - save_output_array(data, (double *) (*trace_outputs)[layer_name], layer_size); - } else { - std::cout << "Unknown trace type!" << std::endl; - } - } else { - std::cout << "Layer name: " << layer_name << " not found in debug storage!" << std::endl; - } - } else { - std::ostringstream filename; - filename << "./tb_data/" << layer_name << "_output.log"; //TODO if run as a shared lib, path should be ../tb_data - std::fstream out; - out.open(filename.str(), std::ios::app); - assert(out.is_open()); - for(int i = 0; i < layer_size; i++) { - out << float(data[i]) << " "; // We don't care about precision in text files - } - out << std::endl; - out.close(); - } -} - -template -void save_layer_output(hls::stream &data, const char *layer_name, size_t layer_size) { - if (!trace_enabled) return; - - if (trace_outputs) { - if (trace_outputs->count(layer_name) > 0) { - if (trace_type_size == 4) { - save_output_array(data, (float *) (*trace_outputs)[layer_name], layer_size); - } else if (trace_type_size == 8) { - save_output_array(data, (double *) (*trace_outputs)[layer_name], layer_size); - } else { - std::cout << "Unknown trace type!" << std::endl; - } - } else { - std::cout << "Layer name: " << layer_name << " not found in debug storage!" << std::endl; - } - } else { - std::ostringstream filename; - filename << "./tb_data/" << layer_name << "_output.log"; //TODO if run as a shared lib, path should be ../tb_data - std::fstream out; - out.open(filename.str(), std::ios::app); - assert(out.is_open()); - for (size_t i = 0; i < layer_size / data_T::size; i++) { - data_T ctype = data.read(); - for (size_t j = 0; j < data_T::size; j++) { - out << float(ctype[j]) << " "; // We don't care about precision in text files - } - data.write(ctype); - } - out << std::endl; - out.close(); - } -} - - -#endif - -template -void copy_data(std::vector src, dst_T dst[SIZE]) { - typename std::vector::const_iterator in_begin = src.cbegin() + OFFSET; - typename std::vector::const_iterator in_end = in_begin + SIZE; - std::copy(in_begin, in_end, dst); -} - -template -void copy_data(std::vector src, hls::stream &dst) { - typename std::vector::const_iterator in_begin = src.cbegin() + OFFSET; - typename std::vector::const_iterator in_end = in_begin + SIZE; - - size_t i_pack = 0; - dst_T dst_pack; - for (typename std::vector::const_iterator i = in_begin; i != in_end; ++i) { - dst_pack[i_pack++] = typename dst_T::value_type(*i); - if (i_pack == dst_T::size) { - i_pack = 0; - dst.write(dst_pack); - } - } -} - -template -void copy_data_axi(std::vector src, dst_T dst[SIZE]) { - for(auto i = 0; i < SIZE; i++) - if(i == SIZE - 1) - { - dst[i].data = src[i]; - dst[i].last = 1; - } - else - { - dst[i].data = src[i]; - dst[i].last = 0; - } -} - -template -void print_result(res_T result[SIZE], std::ostream &out, bool keep = false) { - for(int i = 0; i < SIZE; i++) { - out << result[i] << " "; - } - out << std::endl; -} - -template -void print_result(hls::stream &result, std::ostream &out, bool keep = false) { - for(int i = 0; i < SIZE / res_T::size; i++) { - res_T res_pack = result.read(); - for(int j = 0; j < res_T::size; j++) { - out << res_pack[j] << " "; - } - if (keep) result.write(res_pack); - } - out << std::endl; -} - -template -void fill_zero(data_T data[SIZE]) { - std::fill_n(data, SIZE, 0.); -} - -template -void fill_zero(hls::stream &data) { - for(int i = 0; i < SIZE / data_T::size; i++) { - data_T data_pack; - for(int j = 0; j < data_T::size; j++) { - data_pack[j] = 0.; - } - data.write(data_pack); - } -} - -template -int read_file_1D(const char * filename, dataType data[nrows]) -{ - FILE *fp; - fp = fopen(filename, "r"); - if (fp == 0) { - return -1; - } - // Read data from file - float newval; - for (int ii = 0; ii < nrows; ii++){ - if (fscanf(fp, "%f\n", &newval) != 0){ - data[ii] = newval; - } else { - return -2; - } - } - fclose(fp); - return 0; -} - -template -int read_file_2D(const char * filename, dataType data[nrows][ncols]) -{ - FILE *fp; - fp = fopen(filename, "r"); - if (fp == 0) { - return -1; - } - // Read data from file - float newval; - for (int ii = 0; ii < nrows; ii++) { - for (int jj = 0; jj < ncols; jj++){ - if (fscanf(fp, "%f\n", &newval) != 0){ - data[ii][jj] = newval; - } else { - return -2; - } - } - } - fclose(fp); - return 0; -} - -template -void change_type(hls::stream &in, hls::stream &out) -{ - in_T datareg; - hls::stream input_trunc; - for (int ii=0; ii -void hls_stream_debug(hls::stream &data, hls::stream &res) -{ - data_T datareg; - for (int ii=0; ii - -namespace nnet { - -struct resize_config { - static const unsigned height = 10; - static const unsigned width = 10; - static const unsigned n_chan = 10; - static const unsigned new_height = 10; - static const unsigned new_width = 10; -}; - -template -void resize_nearest( - data_T image[CONFIG_T::height * CONFIG_T::width * CONFIG_T::n_chan], - data_T resized[CONFIG_T::new_height * CONFIG_T::new_width * CONFIG_T::n_chan] -) { - int y_ratio = (int)((CONFIG_T::height << 16) / CONFIG_T::new_height) + 1; - int x_ratio = (int)((CONFIG_T::width << 16) / CONFIG_T::new_width) + 1; - int x2, y2; - - #pragma HLS PIPELINE - - for (int i = 0; i < CONFIG_T::new_height; i++) { - for (int j = 0; j < CONFIG_T::new_width; j++) { - x2 = ((j * x_ratio) >> 16); - y2 = ((i * y_ratio) >> 16); - for (int k = 0; k < CONFIG_T::n_chan; k++) { - resized[(i * CONFIG_T::new_width * CONFIG_T::n_chan) + j * CONFIG_T::n_chan + k] = image[(y2 * CONFIG_T::width * CONFIG_T::n_chan) + x2 * CONFIG_T::n_chan + k]; - } - } - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_image_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_image_stream.h deleted file mode 100644 index e25f5fe..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_image_stream.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef NNET_IMAGE_STREAM_H_ -#define NNET_IMAGE_STREAM_H_ - -#include "nnet_common.h" -#include "hls_stream.h" - -namespace nnet { - -template -void resize_nearest( - hls::stream &image, - hls::stream &resized -) { - assert(CONFIG_T::new_height % CONFIG_T::height == 0); - assert(CONFIG_T::new_width % CONFIG_T::width == 0); - constexpr unsigned ratio_height = CONFIG_T::new_height / CONFIG_T::height; - constexpr unsigned ratio_width = CONFIG_T::new_width / CONFIG_T::width; - constexpr unsigned ii = ratio_height * ratio_width; - - ResizeImage: for (unsigned i = 0; i < CONFIG_T::height * CONFIG_T::width; i++) { - #pragma HLS PIPELINE II=ii - - data_T in_data = image.read(); - - ResizeNew: for (unsigned j = 0; j < ratio_height * ratio_width; j++) { - #pragma HLS UNROLL - - data_T out_data; - #pragma HLS DATA_PACK variable=out_data - - ResizeChan: for (unsigned k = 0; k < CONFIG_T::n_chan; k++) { - #pragma HLS UNROLL - out_data[k] = in_data[k]; - } - - resized.write(out_data); - } - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_merge.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_merge.h deleted file mode 100644 index 48a5e17..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_merge.h +++ /dev/null @@ -1,302 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_MERGE_H_ -#define NNET_MERGE_H_ - -#include "nnet_common.h" -#include "nnet_mult.h" -#include "hls_stream.h" -#include - -namespace nnet { - -struct merge_config -{ - static const unsigned n_elem = 10; -}; - -struct dot_config { - static const unsigned n_in = 10; - static const unsigned n_out = 1; - static const unsigned reuse_factor = 1; - typedef float accum_t; - // Product function to use - template - using product = nnet::product::mult; -}; - -struct concat_config { - static const unsigned n_elem1_0 = 10; - static const unsigned n_elem1_1 = 10; - static const unsigned n_elem1_2 = 10; - static const unsigned n_elem2_0 = 10; - static const unsigned n_elem2_1 = 10; - static const unsigned n_elem2_2 = 10; - - static const unsigned axis = -1; -}; - -template -void add( - input1_T data1[CONFIG_T::n_elem], - input2_T data2[CONFIG_T::n_elem], - res_T res[CONFIG_T::n_elem]) -{ - for (int ii=0; ii -void subtract( - input1_T data1[CONFIG_T::n_elem], - input2_T data2[CONFIG_T::n_elem], - res_T res[CONFIG_T::n_elem]) -{ - for (int ii=0; ii -void multiply( - input1_T data1[CONFIG_T::n_elem], - input2_T data2[CONFIG_T::n_elem], - res_T res[CONFIG_T::n_elem]) -{ - for (int ii=0; ii -void average( - input1_T data1[CONFIG_T::n_elem], - input2_T data2[CONFIG_T::n_elem], - res_T res[CONFIG_T::n_elem]) -{ - for (int ii=0; ii -void maximum( - input1_T data1[CONFIG_T::n_elem], - input2_T data2[CONFIG_T::n_elem], - res_T res[CONFIG_T::n_elem]) -{ - for (int ii=0; ii data2[ii]) ? data1[ii] : data2[ii]; - } -} - -template -void minimum( - input1_T data1[CONFIG_T::n_elem], - input2_T data2[CONFIG_T::n_elem], - res_T res[CONFIG_T::n_elem]) -{ - for (int ii=0; ii -void dot1d( - input1_T data1[CONFIG_T::n_in], - input2_T data2[CONFIG_T::n_in], - res_T res[CONFIG_T::n_out]) -{ - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - - constexpr unsigned multiplier_limit = DIV_ROUNDUP(CONFIG_T::n_in, CONFIG_T::reuse_factor); - CONFIG_T::template product::limit(multiplier_limit); - - typename CONFIG_T::accum_t mult[CONFIG_T::n_in]; - #pragma HLS ARRAY_PARTITION variable=mult complete - typename CONFIG_T::accum_t acc = 0; - - Product: for(int i_mult=0; i_mult < CONFIG_T::n_in; i_mult++) { - #pragma HLS UNROLL - mult[i_mult] = CONFIG_T::template product::product(data1[i_mult], data2[i_mult]); - } - - Accum: for(int i_acc = 0; i_acc < CONFIG_T::n_in; i_acc++) { - #pragma HLS UNROLL - acc += mult[i_acc]; - } - - res[0] = cast(acc); -} - - -template -void concatenate1d( - input1_T data1[CONFIG_T::n_elem1_0], - input2_T data2[CONFIG_T::n_elem2_0], - res_T res[CONFIG_T::n_elem1_0 + CONFIG_T::n_elem2_0]) -{ - for (int ii=0; ii -void concatenate2d_0( - input1_T data1[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1], - input2_T data2[CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1], - res_T res[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1 + CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1]) -{ - for (int ii=0; ii -void concatenate2d_1( - input1_T data1[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1], - input2_T data2[CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1], - res_T res[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1 + CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1]) -{ - for (int ii=0; ii -void concatenate2d( - input1_T data1[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1], - input2_T data2[CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1], - res_T res[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1 + CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1]) -{ - if (CONFIG_T::axis == 2 || CONFIG_T::axis == -1) { - concatenate2d_1(data1, data2, res); - } else { - concatenate2d_0(data1, data2, res); - } -} - -template -void concatenate3d_0( -input1_T data1[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1 * CONFIG_T::n_elem1_2], - input2_T data2[CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1 * CONFIG_T::n_elem2_2], - res_T res[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1 * CONFIG_T::n_elem1_2 + CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1 * CONFIG_T::n_elem2_2]) -{ - for (int ii=0; ii -void concatenate3d_1( -input1_T data1[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1 * CONFIG_T::n_elem1_2], - input2_T data2[CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1 * CONFIG_T::n_elem2_2], - res_T res[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1 * CONFIG_T::n_elem1_2 + CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1 * CONFIG_T::n_elem2_2]) -{ - for (int ii=0; ii -void concatenate3d_2( - input1_T data1[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1 * CONFIG_T::n_elem1_2], - input2_T data2[CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1 * CONFIG_T::n_elem2_2], - res_T res[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1 * CONFIG_T::n_elem1_2 + CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1 * CONFIG_T::n_elem2_2]) -{ - for (int ii=0; ii -void concatenate3d( - input1_T data1[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1 * CONFIG_T::n_elem1_2], - input2_T data2[CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1 * CONFIG_T::n_elem2_2], - res_T res[CONFIG_T::n_elem1_0 * CONFIG_T::n_elem1_1 * CONFIG_T::n_elem1_2 + CONFIG_T::n_elem2_0 * CONFIG_T::n_elem2_1 * CONFIG_T::n_elem2_2]) -{ - if (CONFIG_T::axis == 3 || CONFIG_T::axis == -1) { - concatenate3d_2(data1, data2, res); - } else if (CONFIG_T::axis == 2 || CONFIG_T::axis == -2) { - concatenate3d_1(data1, data2, res); - } else { - concatenate3d_0(data1, data2, res); - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_merge_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_merge_stream.h deleted file mode 100644 index e7a02ce..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_merge_stream.h +++ /dev/null @@ -1,304 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef NNET_MERGE_STREAM_H_ -#define NNET_MERGE_STREAM_H_ - -#include "nnet_common.h" -#include "hls_stream.h" -#include - -namespace nnet { - -template -void add( - hls::stream &data1, - hls::stream &data2, - hls::stream &res) -{ - assert(input1_T::size == input2_T::size && input1_T::size == res_T::size); - - AddLoop: for (int i = 0; i < CONFIG_T::n_elem / input1_T::size; i++) { - #pragma HLS PIPELINE - - input1_T in_data1 = data1.read(); - input2_T in_data2 = data2.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - AddPack: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - out_data[j] = in_data1[j] + in_data2[j]; - } - - res.write(out_data); - } -} - -template -void subtract( - hls::stream &data1, - hls::stream &data2, - hls::stream &res) -{ - assert(input1_T::size == input2_T::size && input1_T::size == res_T::size); - - SubtractLoop: for (int i = 0; i < CONFIG_T::n_elem / input1_T::size; i++) { - #pragma HLS PIPELINE - - input1_T in_data1 = data1.read(); - input2_T in_data2 = data2.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - SubtractPack: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - out_data[j] = in_data1[j] - in_data2[j]; - } - - res.write(out_data); - } -} - -template -void multiply( - hls::stream &data1, - hls::stream &data2, - hls::stream &res) -{ - assert(input1_T::size == input2_T::size && input1_T::size == res_T::size); - - MultiplyLoop: for (int i = 0; i < CONFIG_T::n_elem / input1_T::size; i++) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - - input1_T in_data1 = data1.read(); - input2_T in_data2 = data2.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - MultiplyPack: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - out_data[j] = in_data1[j] * in_data2[j]; - } - - res.write(out_data); - } -} - -template -void average( - hls::stream &data1, - hls::stream &data2, - hls::stream &res) -{ - assert(input1_T::size == input2_T::size && input1_T::size == res_T::size); - - AverageLoop: for (int i = 0; i < CONFIG_T::n_elem / input1_T::size; i++) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - - input1_T in_data1 = data1.read(); - input2_T in_data2 = data2.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - AveragePack: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - out_data[j] = (in_data1[j] + in_data2[j]) / (typename res_T::value_type) 2; - } - - res.write(out_data); - } -} - -template -void maximum( - hls::stream &data1, - hls::stream &data2, - hls::stream &res) -{ - assert(input1_T::size == input2_T::size && input1_T::size == res_T::size); - - MaximumLoop: for (int i = 0; i < CONFIG_T::n_elem / input1_T::size; i++) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - - input1_T in_data1 = data1.read(); - input2_T in_data2 = data2.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - MaximumPack: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - out_data[j] = (in_data1[j] > in_data2[j]) ? in_data1[j] : in_data2[j]; - } - - res.write(out_data); - } -} - -template -void minimum( - hls::stream &data1, - hls::stream &data2, - hls::stream &res) -{ - assert(input1_T::size == input2_T::size && input1_T::size == res_T::size); - - MinimumLoop: for (int i = 0; i < CONFIG_T::n_elem / input1_T::size; i++) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - - input1_T in_data1 = data1.read(); - input2_T in_data2 = data2.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - MinimumPack: for (int j = 0; j < res_T::size; j++) { - #pragma HLS UNROLL - out_data[j] = (in_data1[j] < in_data2[j]) ? in_data1[j] : in_data2[j]; - } - - res.write(out_data); - } -} - -template -void concatenate3d_0( - hls::stream &data1, - hls::stream &data2, - hls::stream &res) -{ - ConcatLoopHeight1: for (int i = 0; i < CONFIG_T::n_elem1_0; i++) { - ConcatLoopWidth1: for (int j = 0; j < CONFIG_T::n_elem1_1; j++) { - #pragma HLS PIPELINE II=1 - - input1_T in_data1 = data1.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - ConcatPackInput1: for (int k = 0; k < input1_T::size; k++) { - #pragma HLS UNROLL - out_data[k] = in_data1[k]; - } - - res.write(out_data); - } - } - ConcatLoopHeight2: for (int i = 0; i < CONFIG_T::n_elem2_0; i++) { - ConcatLoopWidth2: for (int j = 0; j < CONFIG_T::n_elem2_1; j++) { - #pragma HLS PIPELINE II=1 - - input2_T in_data2 = data2.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - ConcatPackInput2: for (int k = 0; k < input2_T::size; k++) { - #pragma HLS UNROLL - out_data[k] = in_data2[k]; - } - - res.write(out_data); - } - } -} - -template -void concatenate3d_1( - hls::stream &data1, - hls::stream &data2, - hls::stream &res) -{ - ConcatLoopHeight: for (int i = 0; i < CONFIG_T::n_elem1_0; i++) { - ConcatLoopWidth1: for (int j = 0; j < CONFIG_T::n_elem1_1; j++) { - #pragma HLS PIPELINE II=1 - - input1_T in_data1 = data1.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - ConcatPackInput1: for (int k = 0; k < input1_T::size; k++) { - #pragma HLS UNROLL - out_data[k] = in_data1[k]; - } - - res.write(out_data); - } - ConcatLoopWidth2: for (int j = 0; j < CONFIG_T::n_elem2_1; j++) { - #pragma HLS PIPELINE II=1 - - input2_T in_data2 = data2.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - ConcatPackInput2: for (int k = 0; k < input2_T::size; k++) { - #pragma HLS UNROLL - out_data[k] = in_data2[k]; - } - - res.write(out_data); - } - } -} - -template -void concatenate3d_2( - hls::stream &data1, - hls::stream &data2, - hls::stream &res) -{ - ConcatLoopHeight: for (int i = 0; i < CONFIG_T::n_elem1_0; i++) { - ConcatLoopWidth: for (int j = 0; j < CONFIG_T::n_elem1_1; j++) { - #pragma HLS PIPELINE II=1 - - input1_T in_data1 = data1.read(); - input2_T in_data2 = data2.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - ConcatPackInput1: for (int k = 0; k < input1_T::size; k++) { - #pragma HLS UNROLL - out_data[k] = in_data1[k]; - } - - ConcatPackInput2: for (int k = 0; k < input2_T::size; k++) { - #pragma HLS UNROLL - out_data[input1_T::size + k] = in_data2[k]; - } - - res.write(out_data); - } - } -} - -template -void concatenate3d( - hls::stream &data1, - hls::stream &data2, - hls::stream &res) -{ - if (CONFIG_T::axis == 3 || CONFIG_T::axis == -1) { - concatenate3d_2(data1, data2, res); - } else if (CONFIG_T::axis == 2 || CONFIG_T::axis == -2) { - concatenate3d_1(data1, data2, res); - } else { - concatenate3d_0(data1, data2, res); - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_mult.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_mult.h deleted file mode 100644 index 3a597f0..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_mult.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef NNET_MULT_H_ -#define NNET_MULT_H_ - -#include "nnet_common.h" -#include "nnet_helpers.h" -#include "hls_stream.h" -#include - -namespace nnet { - -namespace product{ - -/* --- - * 5 different methods to perform the product of input and weight, depending on the - * types of each. - * --- */ - -template -class Product{ - public: - static y_T product(x_T a, w_T w){ - // 'Normal' product - #pragma HLS INLINE - return a * w; - } - static void limit(unsigned multiplier_limit) {} // Nothing to do here -}; - -template -class both_binary : public Product{ - public: - static y_T product(x_T a, w_T w){ - // specialisation for 1-bit weights and incoming data - #pragma HLS INLINE - return a == w; - } -}; - -template -class weight_binary : public Product{ - public: - static y_T product(x_T a, w_T w){ - // Specialisation for 1-bit weights, arbitrary data - #pragma HLS INLINE - return w == 0 ? (x_T) -a : a; - } -}; - -template -class data_binary : public Product{ - public: - static y_T product(x_T a, w_T w){ - // Specialisation for 1-bit data, arbitrary weight - #pragma HLS INLINE - return a == 0 ? (w_T) -w : w; - } -}; - -template -class weight_ternary : public Product{ - public: - static y_T product(x_T a, w_T w){ - // Specialisation for 2-bit weights, arbitrary data - #pragma HLS INLINE - if (w == 0) return (x_T) 0; - else if(w == -1) return (x_T) -a; - else return (x_T) a; // if(w == 1) - } -}; - -template -class mult : public Product{ - public: - static y_T product(x_T a, w_T w){ - // 'Normal' product - #pragma HLS INLINE - return a * w; - } - static void limit(unsigned multiplier_limit){ - #pragma HLS INLINE - #pragma HLS ALLOCATION instances=mul limit=multiplier_limit operation - } -}; - -template -class weight_exponential : public Product{ - public: - static y_T product(x_T a, w_T w){ - // Shift product for exponential weights - #pragma HLS INLINE - // shift by the exponent. Negative weights shift right - y_T y = a << w.weight; - // negate or not depending on weight sign - return w.sign == 1 ? (y_T) y : (y_T) -y; - } -}; - -} // namespace product_type - -template -inline typename std::enable_if>::value - && std::is_same>::value, ap_int>::type -cast(typename CONFIG_T::accum_t x){ - return (ap_int) (x - CONFIG_T::n_in / 2) * 2; -} - -template -inline typename std::enable_if>::value - && ! std::is_same>::value, res_T>::type -cast(typename CONFIG_T::accum_t x){ - return (res_T) x; -} - -template -inline typename std::enable_if<(! std::is_same>::value), res_T>::type -cast(typename CONFIG_T::accum_t x){ - return (res_T) x; -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_padding.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_padding.h deleted file mode 100644 index 6a2c713..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_padding.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef NNET_PADDING_H_ -#define NNET_PADDING_H_ - -#include - -namespace nnet { - -struct padding1d_config { - static const unsigned n_chan = 10; - static const unsigned in_width = 10; - static const unsigned out_width = 10; - static const unsigned pad_left = 0; - static const unsigned pad_right = 0; -}; - -template -void zeropad1d_cf( - data_T data[CONFIG_T::n_chan * CONFIG_T::in_width], - data_T res[CONFIG_T::n_chan * CONFIG_T::out_width] -) { - for(int j = 0; j < CONFIG_T::n_chan; j++) { - for (int i = 0; i < CONFIG_T::pad_left; i++) { - *(res++) = 0; - } - - for (int i = 0; i < CONFIG_T::in_width; i++) { - *(res++) = (res_T) *(data++); - } - - for (int i = 0; i < CONFIG_T::pad_right; i++) { - *(res++) = 0; - } - } -} - -template -void zeropad1d_cl( - data_T data[CONFIG_T::n_chan * CONFIG_T::in_width], - res_T res[CONFIG_T::n_chan * CONFIG_T::out_width] -) { - for (int i = 0; i < CONFIG_T::pad_left; i++) { - for(int j = 0; j < CONFIG_T::n_chan; j++) { - *(res++) = 0; - } - } - - for (int i = 0; i < CONFIG_T::in_width; i++) { - for(int j = 0; j < CONFIG_T::n_chan; j++) { - *(res++) = (res_T) *(data++); - } - } - - for (int i = 0; i < CONFIG_T::pad_right; i++) { - for(int j = 0; j < CONFIG_T::n_chan; j++) { - *(res++) = 0; - } - } -} - - -struct padding2d_config { - static const unsigned n_chan = 10; - static const unsigned in_height = 10; - static const unsigned in_width = 10; - static const unsigned out_height = 10; - static const unsigned out_width = 10; - static const unsigned pad_top = 0; - static const unsigned pad_bottom = 0; - static const unsigned pad_left = 0; - static const unsigned pad_right = 0; -}; - -template -void zeropad2d_cf( - data_T data[CONFIG_T::n_chan * CONFIG_T::in_height * CONFIG_T::in_width], - data_T res[CONFIG_T::n_chan * CONFIG_T::out_height * CONFIG_T::out_width] -) { - for(int k = 0; k < CONFIG_T::n_chan; k++) { - - for (int i = 0; i < CONFIG_T::pad_top; i++) { - for (int j = 0; j < CONFIG_T::out_width; j++) { - *(res++) = 0; - } - } - - for (int i = 0; i < CONFIG_T::in_height; i++) { - for (int j = 0; j < CONFIG_T::pad_left; j++) { - *(res++) = 0; - } - for (int j = 0; j < CONFIG_T::in_width; j++) { - *(res++) = (res_T) *(data++); - } - for (int j = 0; j < CONFIG_T::pad_right; j++) { - *(res++) = 0; - } - } - - for (int i = 0; i < CONFIG_T::pad_bottom; i++) { - for (int j = 0; j < CONFIG_T::out_width; j++) { - *(res++) = 0; - } - } - } -} - -template -void zeropad2d_cl( - data_T data[CONFIG_T::n_chan * CONFIG_T::in_height * CONFIG_T::in_width], - res_T res[CONFIG_T::n_chan * CONFIG_T::out_height * CONFIG_T::out_width] -) { - for (int i = 0; i < CONFIG_T::pad_top; i++) { - for (int j = 0; j < CONFIG_T::out_width; j++) { - for(int k = 0; k < CONFIG_T::n_chan; k++) { - *(res++) = 0; - } - } - } - - for (int i = 0; i < CONFIG_T::in_height; i++) { - for (int j = 0; j < CONFIG_T::pad_left; j++) { - for(int k = 0; k < CONFIG_T::n_chan; k++) { - *(res++) = 0; - } - } - for (int j = 0; j < CONFIG_T::in_width; j++) { - for(int k = 0; k < CONFIG_T::n_chan; k++) { - *(res++) = (res_T) *(data++); - } - } - for (int j = 0; j < CONFIG_T::pad_right; j++) { - for(int k = 0; k < CONFIG_T::n_chan; k++) { - *(res++) = 0; - } - } - } - - for (int i = 0; i < CONFIG_T::pad_bottom; i++) { - for (int j = 0; j < CONFIG_T::out_width; j++) { - for(int k = 0; k < CONFIG_T::n_chan; k++) { - *(res++) = 0; - } - } - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_padding_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_padding_stream.h deleted file mode 100644 index 0bbd42f..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_padding_stream.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef NNET_PADDING_STREAM_H_ -#define NNET_PADDING_STREAM_H_ - -#include - -namespace nnet { - -template -void fill_zero(hls::stream &res) { - #pragma HLS INLINE - res_T res_part; - for (int c = 0; c < CONFIG_T::n_chan; c++) { - #pragma HLS UNROLL - res_part[c] = 0; - } - res.write(res_part); -} - -template -void fill_data(hls::stream &data, hls::stream &res) { - #pragma HLS INLINE - data_T data_part = data.read(); - res_T res_part; - for (int c = 0; c < CONFIG_T::n_chan; c++) { - #pragma HLS UNROLL - res_part[c] = data_part[c]; - } - res.write(res_part); -} - -template -void zeropad1d_cl( - hls::stream &data, - hls::stream &res -) { - PadLeft: for (int i = 0; i < CONFIG_T::pad_left; i++) { - fill_zero(res); - } - - CopyMain: for (int i = 0; i < CONFIG_T::in_width; i++) { - fill_data(data, res); - } - - PadRight: for (int i = 0; i < CONFIG_T::pad_right; i++) { - fill_zero(res); - } -} - -template -void zeropad2d_cl( - hls::stream &data, - hls::stream &res -) { - - PadTop: for (int i = 0; i < CONFIG_T::pad_top; i++) { - PadTopWidth: for (int j = 0; j < CONFIG_T::out_width; j++) { - fill_zero(res); - } - } - - PadMain: for (int i = 0; i < CONFIG_T::in_height; i++) { - PadLeft: for (int j = 0; j < CONFIG_T::pad_left; j++) { - fill_zero(res); - } - CopyMain: for (int j = 0; j < CONFIG_T::in_width; j++) { - fill_data(data, res); - } - PadRight: for (int j = 0; j < CONFIG_T::pad_right; j++) { - fill_zero(res); - } - } - - PadBottom: for (int i = 0; i < CONFIG_T::pad_bottom; i++) { - PadBottomWidth: for (int j = 0; j < CONFIG_T::out_width; j++) { - fill_zero(res); - } - } -} - -} - -#endif \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_pooling.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_pooling.h deleted file mode 100644 index 545ae55..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_pooling.h +++ /dev/null @@ -1,298 +0,0 @@ -#ifndef NNET_POOLING_H_ -#define NNET_POOLING_H_ - -#include -#include "nnet_helpers.h" - -namespace nnet{ - -// Return the maximum value from an array -template -T max(T x[N]){ - T y = x[0]; - for(int i = 1; i < N; i++){ - y = x[i] > y ? x[i] : y; - } - return y; -} - -template -ap_int avg(ap_int (&x)[N]){ - // Use a wider accumulator than the input to avoid overflow - ap_int tmp = 0; - for(int i = 0; i < N; i++){ - tmp += x[i]; - } - tmp /= N; - // Now cast back to original type - ap_int y = tmp; - return tmp; -} - -template -ap_fixed avg(ap_fixed (&x)[N]){ - // Use a wider accumulator than the input to avoid overflow - ap_fixed tmp = 0; - for(int i = 0; i < N; i++){ - tmp += x[i]; - } - tmp /= N; - // Now cast back to original type - ap_fixed y = tmp; - return y; -} - -// Return the mean value of an array -template -T avg(T (&x)[N]){ - T y = 0; - for(int i = 0; i < N; i++){ - y += x[i]; - } - y /= N; - return y; -} - -// Enumeration for pooling operation (max, avg, l2norm pooling) -enum Pool_Op { Max, Average }; // L2Norm }; -template -T pool_op(T (&x)[N]){ - switch(op){ - case Max: return max(x); - case Average: return avg(x); - // case L2Norm: return l2norm(x); - } -} - -template -T pad_val(){ - /*--- - *- In Tensorflow, pooling ignores the value in the padded cells - *- For Avg pooling, return 0 (the divisior is modified to the - *- area overlapping the unpadded image. - *- For max pooling, return the most negative value for the type. - *- TODO this is not really generic, it assumes fixed point or integer T - ---*/ - switch(op){ - case Max:{ - T x = 0; - x[x.width - 1] = 1; - return x; - break;} - case Average: return 0; - } -} - -struct pooling1d_config{ - // IO size - static const unsigned n_in = 10; - static const unsigned pool_width = 2; - static const unsigned stride_width = 2; - static const unsigned n_out = (n_in - pool_width) / stride_width + 1; - static const unsigned pad_left = 0; - static const unsigned pad_right = 0; - // Pooling function - static const Pool_Op pool_op = Max; -}; - -template -constexpr int pool_op_limit_1d() { - return CONFIG_T::n_in * CONFIG_T::n_filt / CONFIG_T::reuse; -} - -template -void pooling1d_cl(data_T data[CONFIG_T::n_in * CONFIG_T::n_filt], res_T res[CONFIG_T::n_out * CONFIG_T::n_filt]) { - - // TODO partition the arrays according to the reuse factor - const int limit = pool_op_limit_1d(); - #pragma HLS ALLOCATION instances=pool_op limit=limit function - // Add any necessary padding - unsigned padded_width = CONFIG_T::n_in + CONFIG_T::pad_left + CONFIG_T::pad_right; - if (CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0) { - padded_width -= padded_width - (padded_width / CONFIG_T::stride_width * CONFIG_T::stride_width); - } - - for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - // Loop over input image x in steps of stride - for(int ii = 0; ii < padded_width; ii += CONFIG_T::stride_width) { - data_T pool[CONFIG_T::pool_width]; - // Keep track of number of pixels in image vs padding region - unsigned img_overlap = 0; - // Loop over pool window x - for(int jj = 0; jj < CONFIG_T::stride_width; jj++) { - if(ii+jj < CONFIG_T::pad_left || ii+jj >= (padded_width - CONFIG_T::pad_right)) { - // Add padding - pool[jj] = pad_val(); - }else{ - pool[jj] = data[(ii + jj) * CONFIG_T::n_filt + ff]; - img_overlap++; - } - } - // do the pooling - // TODO in the case of average pooling, need to reduce width to area of pool window - // not overlapping padding region - res[(ii/CONFIG_T::stride_width)* CONFIG_T::n_filt + ff] = - pool_op(pool); - // If the pool op is Average, the zero-padding needs to be removed from the results - if(CONFIG_T::pool_op == Average) { - data_T rescale = CONFIG_T::pool_width / img_overlap; - res[(ii/CONFIG_T::stride_width)* CONFIG_T::n_filt + ff] *= rescale; - } - } - } -} - -template -void global_pooling1d_cl(data_T data[CONFIG_T::n_in * CONFIG_T::n_filt], res_T res[CONFIG_T::n_filt]) { - assert(CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - assert(CONFIG_T::pool_width == CONFIG_T::stride_width); - - // TODO partition the arrays according to the reuse factor - const int limit = pool_op_limit_1d(); - #pragma HLS ALLOCATION instances=pool_op limit=limit function - - for(int ff = 0; ff < CONFIG_T::n_filt; ff++) { - data_T pool[CONFIG_T::n_in]; - for(int jj = 0; jj < CONFIG_T::n_in; jj++) { - pool[jj] = data[jj * CONFIG_T::n_filt + ff]; - } - // do the pooling - res[ff] = pool_op(pool); - } -} - -struct pooling2d_config{ - // IO size - static const unsigned in_height = 10; - static const unsigned in_width = 10; - static const unsigned n_filt = 4; - static const unsigned stride_height = 2; - static const unsigned stride_width = 2; - static const unsigned pool_height = 2; - static const unsigned pool_width = 2; - static const unsigned out_height = (in_height - pool_height) / stride_height + 1; - static const unsigned out_width = (in_width - pool_width) / stride_width + 1; - // Padding - static const unsigned pad_top = 0; - static const unsigned pad_bottom = 0; - static const unsigned pad_left = 0; - static const unsigned pad_right = 0; - // Pooling function - static const Pool_Op pool_op = Max; - // Reuse - static const unsigned reuse = 1; - - // Internal data type definitions - typedef float accum_t; -}; - -template -constexpr int pool_op_limit(){ - return (CONFIG_T::out_height * CONFIG_T::out_width) * CONFIG_T::n_filt / CONFIG_T::reuse; -} - -template -void pooling2d_cl(data_T data[CONFIG_T::in_height * CONFIG_T::in_width * CONFIG_T::n_filt], - res_T res[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt]){ - - // TODO partition the arrays according to the reuse factor - const int limit = pool_op_limit(); - #pragma HLS ALLOCATION instances=pool_op limit=limit function - // Add any necessary padding - unsigned padded_height = CONFIG_T::in_height + CONFIG_T::pad_top + CONFIG_T::pad_bottom; - unsigned padded_width = CONFIG_T::in_width + CONFIG_T::pad_left + CONFIG_T::pad_right; - if (CONFIG_T::pad_top == 0 && CONFIG_T::pad_bottom == 0 && CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0) { - padded_height -= padded_height - (padded_height / CONFIG_T::stride_height * CONFIG_T::stride_height); - padded_width -= padded_width - (padded_width / CONFIG_T::stride_width * CONFIG_T::stride_width); - } - - for(int ff = 0; ff < CONFIG_T::n_filt; ff++){ - // Loop over input image y in steps of stride - for(int ii = 0; ii < padded_height; ii += CONFIG_T::stride_height){ - // Loop over input image x in steps of stride - for(int jj = 0; jj < padded_width; jj += CONFIG_T::stride_width){ - data_T pool[CONFIG_T::pool_height * CONFIG_T::pool_width]; - // Keep track of number of pixels in image vs padding region - unsigned img_overlap = 0; - // Loop over pool window y - for(int kk = 0; kk < CONFIG_T::stride_height; kk++){ - // Loop over pool window x - for(int ll = 0; ll < CONFIG_T::stride_width; ll++){ - if(ii+kk < CONFIG_T::pad_top || ii+kk >= (padded_height - CONFIG_T::pad_bottom) || jj+ll < CONFIG_T::pad_left || jj+ll >= (padded_width - CONFIG_T::pad_right)){ - // Add padding - pool[kk * CONFIG_T::stride_width + ll] = pad_val(); - }else{ - pool[kk * CONFIG_T::stride_width + ll] = data[(ii + kk) * CONFIG_T::in_width * CONFIG_T::n_filt + (jj + ll) * CONFIG_T::n_filt + ff]; - img_overlap++; - } - } - } - // do the pooling - // TODO in the case of average pooling, need to reduce height * width to area of pool window - // not overlapping padding region - res[(ii/CONFIG_T::stride_height) * CONFIG_T::out_width * CONFIG_T::n_filt + (jj/CONFIG_T::stride_width)* CONFIG_T::n_filt + ff] = - pool_op(pool); - // If the pool op is Average, the zero-padding needs to be removed from the results - if(CONFIG_T::pool_op == Average){ - data_T rescale = CONFIG_T::pool_height * CONFIG_T::pool_width / img_overlap; - res[(ii/CONFIG_T::stride_height) * CONFIG_T::out_width * CONFIG_T::n_filt + (jj/CONFIG_T::stride_width)* CONFIG_T::n_filt + ff] *= rescale; - } - } - } - } -} - -template -void pooling2d_cf(data_T data[CONFIG_T::in_height * CONFIG_T::in_width * CONFIG_T::n_filt], - res_T res[CONFIG_T::out_height * CONFIG_T::out_width * CONFIG_T::n_filt]){ - - // TODO partition the arrays according to the reuse factor - const int limit = pool_op_limit(); - #pragma HLS ALLOCATION instances=pool_op limit=limit function - // Add any necessary padding - unsigned padded_height = CONFIG_T::in_height + CONFIG_T::pad_top + CONFIG_T::pad_bottom; - unsigned padded_width = CONFIG_T::in_width + CONFIG_T::pad_left + CONFIG_T::pad_right; - if (CONFIG_T::pad_top == 0 && CONFIG_T::pad_bottom == 0 && CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0) { - padded_height -= padded_height - (padded_height / CONFIG_T::stride_height * CONFIG_T::stride_height); - padded_width -= padded_width - (padded_width / CONFIG_T::stride_width * CONFIG_T::stride_width); - } - - for(int ff = 0; ff < CONFIG_T::n_filt; ff++){ - // Loop over input image y in steps of stride - for(int ii = 0; ii < padded_height; ii += CONFIG_T::stride_height){ - // Loop over input image x in steps of stride - for(int jj = 0; jj < padded_width; jj += CONFIG_T::stride_width){ - data_T pool[CONFIG_T::pool_height * CONFIG_T::pool_width]; - // Keep track of number of pixels in image vs padding region - unsigned img_overlap = 0; - // Loop over pool window y - for(int kk = 0; kk < CONFIG_T::stride_height; kk++){ - // Loop over pool window x - for(int ll = 0; ll < CONFIG_T::stride_width; ll++){ - if(ii+kk < CONFIG_T::pad_top || ii+kk >= (padded_height - CONFIG_T::pad_bottom) || jj+ll < CONFIG_T::pad_left || jj+ll >= (padded_width - CONFIG_T::pad_right)){ - // Add padding - pool[kk * CONFIG_T::stride_width + ll] = pad_val(); - }else{ - pool[kk * CONFIG_T::stride_width + ll] = data[(ii + kk) * CONFIG_T::in_width + ff * CONFIG_T::in_width*CONFIG_T::in_height + ll + jj]; - img_overlap++; - } - } - } - // do the pooling - // TODO in the case of average pooling, need to reduce height * width to area of pool window - // not overlapping padding region - res[(ii/CONFIG_T::stride_height) * CONFIG_T::out_width + (jj/CONFIG_T::stride_width) + ff* CONFIG_T::out_height* CONFIG_T::out_width] = - pool_op(pool); - // If the pool op is Average, the zero-padding needs to be removed from the results - if(CONFIG_T::pool_op == Average){ - data_T rescale = CONFIG_T::pool_height * CONFIG_T::pool_width / img_overlap; - res[(ii/CONFIG_T::stride_height) * CONFIG_T::out_width + (jj/CONFIG_T::stride_width) + ff* CONFIG_T::out_height* CONFIG_T::out_width] *= rescale; - } - } - } - } -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_pooling_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_pooling_stream.h deleted file mode 100644 index 80fa1d2..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_pooling_stream.h +++ /dev/null @@ -1,605 +0,0 @@ -#ifndef NNET_POOLING_STREAM_H_ -#define NNET_POOLING_STREAM_H_ - -#include "utils/x_hls_utils.h" -#include "ap_shift_reg.h" -#include "nnet_common.h" -#include "nnet_pooling.h" -#include "nnet_conv_stream.h" -#include "hls_stream.h" - -namespace nnet { - -// ************************************************* -// Max/average pooling -// ************************************************* - -template -T reduce_pool(T x[N]) { - #pragma HLS INLINE - if (CONFIG_T::pool_op == Max) { - Op_max op_max; - return reduce>(x, op_max); - } else { - Op_add op_add; - T sum = reduce>(x, op_add); - return sum / N; - } -} - -template -void init_pool_table( - unsigned table[TABLE_SIZE] -) { - for (unsigned ii = 0; ii < TABLE_SIZE; ii++) { - table[ii] = ii % POOL_SIZE; - } -} - -template -void compute_pool_encoded_2d( - const unsigned h_idx, - const unsigned w_idx, - const data_T& in_elem, - hls::stream data_window[CONFIG_T::pool_height * CONFIG_T::pool_width * CONFIG_T::n_filt], - hls::stream &res, - res_T &res_pack, - unsigned &outputs_ready -) { - // Nearest H without unused pixels on the right - constexpr unsigned nH = ((CONFIG_T::in_height - CONFIG_T::pool_height) / CONFIG_T::stride_height) * CONFIG_T::stride_height + CONFIG_T::pool_height; - // Scaled H that behaves like original H - constexpr unsigned sH = (DIV_ROUNDUP(CONFIG_T::pool_height, CONFIG_T::stride_height) - 1) * CONFIG_T::stride_height + CONFIG_T::pool_height; - // Nearest W without unused pixels on the right - constexpr unsigned nW = ((CONFIG_T::in_width - CONFIG_T::pool_width) / CONFIG_T::stride_width) * CONFIG_T::stride_width + CONFIG_T::pool_width; - // Scaled W that behaves like original W - constexpr unsigned sW = (DIV_ROUNDUP(CONFIG_T::pool_width, CONFIG_T::stride_width) - 1) * CONFIG_T::stride_width + CONFIG_T::pool_width; - -#ifdef __SYNTHESIS__ - bool initialized = false; - unsigned pool_table_height[CONFIG_T::in_height]; - unsigned pool_table_width[CONFIG_T::in_width]; -#else - static bool initialized = false; - static unsigned pool_table_height[CONFIG_T::in_height]; - static unsigned pool_table_width[CONFIG_T::in_width]; -#endif - if (!initialized) { - init_pool_table(pool_table_height); - init_pool_table(pool_table_width); - initialized = true; - } - - #pragma HLS INLINE - - if (data_T::size / CONFIG_T::n_filt > 1) { - #pragma HLS ARRAY_PARTITION variable=pool_table_height complete - #pragma HLS ARRAY_PARTITION variable=pool_table_width complete - } - - typename CONFIG_T::accum_t pool_window[CONFIG_T::pool_height * CONFIG_T::pool_width]; - #pragma HLS ARRAY_PARTITION variable=pool_window complete - - const unsigned sh_idx = pool_table_height[h_idx] * CONFIG_T::pool_width; - const unsigned wp_idx = w_idx * (data_T::size / CONFIG_T::n_filt); - - PixelLoop: for (unsigned p = 0; p < data_T::size / CONFIG_T::n_filt; p++) { - #pragma HLS PIPELINE - - ap_uint filt_mask = 0; - if ((h_idx < nH) && (wp_idx + p < nW)) { - filt_mask = sh_idx + pool_table_width[wp_idx + p] + 1; - } - - CopyDataFilt: for (unsigned c = 0; c < CONFIG_T::n_filt; c++) { - if (filt_mask > 0) data_window[c * CONFIG_T::pool_height * CONFIG_T::pool_width + filt_mask.to_uint() - 1].write(in_elem[p * CONFIG_T::n_filt + c]); - } - - if (filt_mask == CONFIG_T::pool_height * CONFIG_T::pool_width) { - FiltLoop: for(unsigned c = 0; c < CONFIG_T::n_filt; c++) { - PoolLoop: for(unsigned f = 0; f < CONFIG_T::pool_height * CONFIG_T::pool_width; f++) { - pool_window[f] = data_window[c * CONFIG_T::pool_height * CONFIG_T::pool_width + f].read(); - } - if (res_T::size / CONFIG_T::n_filt == 1) { // Saves resources if we don't pack output, compiler will remove the else branch - res_pack[c] = reduce_pool(pool_window); - } else { - res_pack[outputs_ready * CONFIG_T::n_filt + c] = reduce_pool(pool_window); - } - - } - if (res_T::size / CONFIG_T::n_filt == 1) { // Saves resources if we don't pack output, compiler will remove the else branch - res.write(res_pack); - } else { - if (outputs_ready == (res_T::size / CONFIG_T::n_filt) - 1) { - res.write(res_pack); - outputs_ready = 0; - } else { - outputs_ready++; - } - } - } - } -} - -template -void pooling2d_encoded_cl( - hls::stream &data, - hls::stream &res -) { - assert(CONFIG_T::pad_top == 0 && CONFIG_T::pad_bottom == 0 && CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - assert(CONFIG_T::pool_height == CONFIG_T::stride_height && CONFIG_T::pool_width == CONFIG_T::stride_width); - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - unsigned outputs_ready = 0; - - hls::stream data_window[CONFIG_T::pool_height * CONFIG_T::pool_width * CONFIG_T::n_filt]; - constexpr int win_depth = CONFIG_T::pool_height * CONFIG_T::out_width; - for (unsigned i_out = 0; i_out < CONFIG_T::pool_height * CONFIG_T::pool_width * CONFIG_T::n_filt; i_out++) { - #pragma HLS STREAM variable=data_window[i_out] depth=win_depth - } - - constexpr int pack_factor = data_T::size / CONFIG_T::n_filt; - - ReadInputHeight: for (unsigned i_ih = 0; i_ih < CONFIG_T::in_height; i_ih++) { - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width / (pack_factor); i_iw++) { - #pragma HLS LOOP_FLATTEN - if (res_T::size / CONFIG_T::n_filt == 1) { - #pragma HLS PIPELINE II=pack_factor - } - compute_pool_encoded_2d(i_ih, i_iw, data.read(), data_window, res, res_pack, outputs_ready); - } - } -} - -// ************************************************* -// Line Buffer Implementation (Phil's) -// ************************************************* -template -void compute_pool_buffer_2d( - const data_T& in_elem, - ap_shift_reg line_buffer[MAX(CONFIG_T::pool_height - 1,1)][CONFIG_T::n_filt], - hls::stream &res -) { - #pragma HLS INLINE - const static int lShiftX = CONFIG_T::pool_width - 1; - const static int lShiftY = CONFIG_T::pool_height - 1; - static int pX = 0; // pixel X - static int pY = 0; // pixel Y - static int sX = 0; // stride X - static int sY = 0; // stride Y - - typename data_T::value_type pool_window[CONFIG_T::pool_height * CONFIG_T::pool_width]; - #pragma HLS ARRAY_PARTITION variable=pool_window complete - - static typename data_T::value_type kernel_data[CONFIG_T::pool_height * CONFIG_T::pool_width * CONFIG_T::n_filt]; - #pragma HLS ARRAY_PARTITION variable = kernel_data complete dim = 0 - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - - // Add pixel into line buffer, return pooling kernels - nnet::shift_line_buffer(in_elem, line_buffer, kernel_data); - - // Can compute pooling output - if ((sX - lShiftX) == 0 && (sY - lShiftY) == 0 && pY > lShiftY - 1 && pX > lShiftX - 1) { - FiltLoop: for(unsigned i_ic = 0; i_ic < CONFIG_T::n_filt; i_ic++) { - #pragma HLS PIPELINE - - // Retrieve data for current channel - PoolLoop: for(unsigned i_ihw = 0; i_ihw < CONFIG_T::pool_height * CONFIG_T::pool_width; i_ihw++) { - pool_window[i_ihw] = kernel_data[i_ihw * CONFIG_T::n_filt + i_ic]; - } - - // Compute Pooling - res_pack[i_ic] = reduce_pool(pool_window); - } - - // Write to output - res.write(res_pack); - } - - // Counter Housekeeping - if (pX + 1 == CONFIG_T::in_width) // Includes padding, end of line (padded) - { - pX = 0; - sX = 0; - if (pY + 1 == CONFIG_T::in_height) { // Reached bottom of image - pY = 0; - sY = 0; - } else { // Next line - pY = pY + 1; - // Update stride (threshold) ? subtract stride : increment stride - sY = ((sY - lShiftY) == 0) ? sY - CONFIG_T::stride_height + 1 : sY + 1; - } - } else { - pX = pX + 1; - // Update stride (threshold) ? subtract stride : increment stride - sX = ((sX - lShiftX) == 0) ? sX - CONFIG_T::stride_width + 1 : sX + 1; - } -} - -template -void pooling2d_buffer_cl( - hls::stream &data, - hls::stream &res -) { - assert(CONFIG_T::pad_top == 0 && CONFIG_T::pad_bottom == 0 && CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - assert(CONFIG_T::pool_height == CONFIG_T::stride_height && CONFIG_T::pool_width == CONFIG_T::stride_width); - - static ap_shift_reg line_buffer[MAX(CONFIG_T::pool_height - 1,1)][CONFIG_T::n_filt]; - #pragma HLS ARRAY_PARTITION variable = line_buffer complete dim = 2 - - ReadInputHeight: for (unsigned i_ih = 0; i_ih < CONFIG_T::in_height; i_ih++) { - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width; i_iw++) { - #pragma HLS LOOP_FLATTEN - #pragma HLS PIPELINE - - compute_pool_buffer_2d(data.read(), line_buffer, res); - } - } -} - -template -void pooling2d_cl( - hls::stream &data, - hls::stream &res -) { - #pragma HLS inline region - switch(CONFIG_T::implementation){ - case conv_implementation::linebuffer: - pooling2d_buffer_cl(data, res); - break; - case conv_implementation::encoded: - pooling2d_encoded_cl(data, res); - break; - } -} - -// ************************************************* -// Pooling 1D -// ************************************************* - -template -void compute_pool_encoded_1d( - const unsigned w_idx, - const data_T& in_elem, - hls::stream data_window[CONFIG_T::pool_width * CONFIG_T::n_filt], - hls::stream &res, - res_T &res_pack, - unsigned &outputs_ready -) { - // Nearest W without unused pixels on the right - constexpr unsigned nW = ((CONFIG_T::n_in - CONFIG_T::pool_width) / CONFIG_T::stride_width) * CONFIG_T::stride_width + CONFIG_T::pool_width; - // Scaled W that behaves like original W - constexpr unsigned sW = (DIV_ROUNDUP(CONFIG_T::pool_width, CONFIG_T::stride_width) - 1) * CONFIG_T::stride_width + CONFIG_T::pool_width; - -#ifdef __SYNTHESIS__ - bool initialized = false; - unsigned pool_table_width[CONFIG_T::n_in]; -#else - static bool initialized = false; - static unsigned pool_table_width[CONFIG_T::n_in]; -#endif - if (!initialized) { - init_pool_table(pool_table_width); - initialized = true; - } - - #pragma HLS INLINE - - if (data_T::size / CONFIG_T::n_filt > 1) { - #pragma HLS ARRAY_PARTITION variable=pool_table_width complete - } - - typename CONFIG_T::accum_t pool_window[CONFIG_T::pool_width]; - #pragma HLS ARRAY_PARTITION variable=pool_window complete - - const unsigned wp_idx = w_idx * (data_T::size / CONFIG_T::n_filt); - - PixelLoop: for (unsigned p = 0; p < data_T::size / CONFIG_T::n_filt; p++) { - #pragma HLS PIPELINE - - ap_uint filt_mask = 0; - if (wp_idx + p < nW) { - filt_mask = pool_table_width[wp_idx + p] + 1; - } - - CopyDataFilt: for (unsigned c = 0; c < CONFIG_T::n_filt; c++) { - if (filt_mask > 0) data_window[c * CONFIG_T::pool_width + filt_mask.to_uint() - 1].write(in_elem[p * CONFIG_T::n_filt + c]); - } - - if (filt_mask == CONFIG_T::pool_width) { - FiltLoop: for(unsigned c = 0; c < CONFIG_T::n_filt; c++) { - PoolLoop: for(unsigned f = 0; f < CONFIG_T::pool_width; f++) { - pool_window[f] = data_window[c * CONFIG_T::pool_width + f].read(); - } - if (res_T::size / CONFIG_T::n_filt == 1) { // Saves resources if we don't pack output, compiler will remove the else branch - res_pack[c] = reduce_pool(pool_window); - } else { - res_pack[outputs_ready * CONFIG_T::n_filt + c] = reduce_pool(pool_window); - } - - } - if (res_T::size / CONFIG_T::n_filt == 1) { // Saves resources if we don't pack output, compiler will remove the else branch - res.write(res_pack); - } else { - if (outputs_ready == (res_T::size / CONFIG_T::n_filt) - 1) { - res.write(res_pack); - outputs_ready = 0; - } else { - outputs_ready++; - } - } - } - } -} - -template -void pooling1d_encoded_cl( - hls::stream &data, - hls::stream &res -) { - assert(CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - assert(CONFIG_T::pool_width == CONFIG_T::stride_width); - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - unsigned outputs_ready = 0; - - hls::stream data_window[CONFIG_T::pool_width * CONFIG_T::n_filt]; - constexpr int win_depth = CONFIG_T::n_out; - for (unsigned i_out = 0; i_out < CONFIG_T::pool_width * CONFIG_T::n_filt; i_out++) { - #pragma HLS STREAM variable=data_window[i_out] depth=win_depth - } - - constexpr int pack_factor = data_T::size / CONFIG_T::n_filt; - - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::n_in / (pack_factor); i_iw++) { - #pragma HLS LOOP_FLATTEN - if (res_T::size / CONFIG_T::n_filt == 1) { - #pragma HLS PIPELINE II=pack_factor - } - compute_pool_encoded_1d(i_iw, data.read(), data_window, res, res_pack, outputs_ready); - } -} - -// ************************************************* -// Line Buffer Implementation (Phil's) 1D -// ************************************************* -template -void compute_pool_buffer_1d( - const data_T& in_elem, - hls::stream &res -) { - #pragma HLS INLINE - const static int lShiftX = CONFIG_T::pool_width - 1; - // Counters - static int pX = 0; - static int sX = 0; - - typename data_T::value_type pool_window[CONFIG_T::pool_width]; - #pragma HLS ARRAY_PARTITION variable=pool_window complete - - static typename data_T::value_type kernel_data[CONFIG_T::pool_width * CONFIG_T::n_filt]; - #pragma HLS ARRAY_PARTITION variable = kernel_data complete dim = 0 - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - - // Add pixel into line buffer, return pooling kernels - // 1D case line buffer not necessary. Put directly into the kernel_data buffer - nnet::kernel_shift_1d(in_elem, kernel_data); - - // Can compute pooling output - if ( (sX - lShiftX) == 0 && pX > lShiftX - 1) { - FiltLoop: for(unsigned i_ic = 0; i_ic < CONFIG_T::n_filt; i_ic++) { - #pragma HLS PIPELINE - - // Retrieve data for current channel - PoolLoop: for(unsigned i_iw = 0; i_iw < CONFIG_T::pool_width; i_iw++) { - pool_window[i_iw] = kernel_data[i_iw * CONFIG_T::n_filt + i_ic]; - } - - // Compute Pooling - res_pack[i_ic] = reduce_pool(pool_window); - } - - // Write to output - res.write(res_pack); - } - - // Counter Housekeeping - if (pX + 1 == CONFIG_T::n_in) // Includes padding, end of line (padded) - { - pX = 0; - sX = 0; - } else { - pX = pX + 1; - // Update stride (threshold) ? subtract stride : increment stride - sX = ((sX - lShiftX) == 0) ? sX - CONFIG_T::stride_width + 1 : sX + 1; - } -} - -template -void pooling1d_buffer_cl( - hls::stream &data, - hls::stream &res -) { - assert(CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::n_in; i_iw++) { - #pragma HLS LOOP_FLATTEN - #pragma HLS PIPELINE - compute_pool_buffer_1d(data.read(), res); - } -} - - -template -void pooling1d_cl( - hls::stream &data, - hls::stream &res -) { - #pragma HLS inline region - switch(CONFIG_T::implementation){ - case conv_implementation::linebuffer: - pooling1d_buffer_cl(data, res); - break; - case conv_implementation::encoded: - pooling1d_encoded_cl(data, res); - break; - } -} - - -// ************************************************* -// Global max/average pooling -// ************************************************* - -template -T reduce_global_pool(T x, T y[N]) { - #pragma HLS INLINE - if (CONFIG_T::pool_op == Max) { - Op_max op_max; - T y_max = reduce>(y, op_max); - return (x > y_max) ? x : y_max; - } else { - Op_add op_add; - T y_sum = reduce>(y, op_add); - return x + y_sum; - } -} - -template -void compute_global_pool( - const data_T& in_elem, - typename CONFIG_T::accum_t data_window[CONFIG_T::n_filt] -) { - PoolFilt: for (unsigned c = 0; c < CONFIG_T::n_filt; c++) { - #pragma HLS UNROLL - - typename CONFIG_T::accum_t data_pack[data_T::size / CONFIG_T::n_filt]; - #pragma HLS ARRAY_PARTITION variable=data_pack complete dim=0 - - PixelLoop: for (unsigned p = 0; p < data_T::size / CONFIG_T::n_filt; p++) { - #pragma HLS UNROLL - data_pack[p] = in_elem[p * CONFIG_T::n_filt + c]; - } - data_window[c] = reduce_global_pool(data_window[c], data_pack); - } -} - -template -void global_pooling2d_cl( - hls::stream &data, - hls::stream &res -) { - assert(CONFIG_T::pad_top == 0 && CONFIG_T::pad_bottom == 0 && CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - assert(CONFIG_T::pool_height == CONFIG_T::stride_height && CONFIG_T::pool_width == CONFIG_T::stride_width); - - typename CONFIG_T::accum_t data_window[CONFIG_T::n_filt]; - #pragma HLS ARRAY_PARTITION variable=data_window complete - - typename CONFIG_T::accum_t init = 0; - if (CONFIG_T::pool_op == Max) { - init = hls::numeric_limits::min(); - } - - PoolInitLoop: for (unsigned i_init = 0; i_init < CONFIG_T::n_filt; i_init++) { - #pragma HLS UNROLL - data_window[i_init] = init; - } - - ReadInputHeight: for (unsigned i_ih = 0; i_ih < CONFIG_T::in_height; i_ih++) { - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width / (data_T::size / CONFIG_T::n_filt); i_iw++) { - #pragma HLS LOOP_FLATTEN - compute_global_pool(data.read(), data_window); - } - } - - if (CONFIG_T::pool_op == Max) { - MaxPoolRes: for (unsigned i_res = 0; i_res < CONFIG_T::n_filt / res_T::size; i_res++) { - #pragma HLS PIPELINE - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - MaxPoolPack: for (unsigned i_pack = 0; i_pack < res_T::size; i_pack++) { - #pragma HLS UNROLL - res_pack[i_pack] = data_window[i_pack]; - } - res.write(res_pack); - } - } else { - AvgPoolRes: for (unsigned i_res = 0; i_res < CONFIG_T::n_filt / res_T::size; i_res++) { - #pragma HLS PIPELINE - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - AvgPoolPack: for (unsigned i_pack = 0; i_pack < res_T::size; i_pack++) { - #pragma HLS UNROLL - res_pack[i_pack] = data_window[i_pack] / (CONFIG_T::in_height * CONFIG_T::in_width); - } - res.write(res_pack); - } - } - -} - -template -void global_pooling1d_cl( - hls::stream &data, - hls::stream &res -) { - assert(CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - assert(CONFIG_T::pool_width == CONFIG_T::stride_width); - - typename CONFIG_T::accum_t data_window[CONFIG_T::n_filt]; - #pragma HLS ARRAY_PARTITION variable=data_window complete - - typename CONFIG_T::accum_t init = 0; - if (CONFIG_T::pool_op == Max) { - init = hls::numeric_limits::min(); - } - - PoolInitLoop: for (unsigned i_init = 0; i_init < CONFIG_T::n_filt; i_init++) { - #pragma HLS UNROLL - data_window[i_init] = init; - } - - ReadInput: for (unsigned i_iw = 0; i_iw < CONFIG_T::n_in / (data_T::size / CONFIG_T::n_filt); i_iw++) { - #pragma HLS LOOP_FLATTEN - compute_global_pool(data.read(), data_window); - } - - if (CONFIG_T::pool_op == Max) { - MaxPoolRes: for (unsigned i_res = 0; i_res < CONFIG_T::n_filt / res_T::size; i_res++) { - #pragma HLS PIPELINE - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - MaxPoolPack: for (unsigned i_pack = 0; i_pack < res_T::size; i_pack++) { - #pragma HLS UNROLL - res_pack[i_pack] = data_window[i_pack]; - } - res.write(res_pack); - } - } else { - AvgPoolRes: for (unsigned i_res = 0; i_res < CONFIG_T::n_filt / res_T::size; i_res++) { - #pragma HLS PIPELINE - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - AvgPoolPack: for (unsigned i_pack = 0; i_pack < res_T::size; i_pack++) { - #pragma HLS UNROLL - res_pack[i_pack] = data_window[i_pack] / CONFIG_T::n_in; - } - res.write(res_pack); - } - } - -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_sepconv1d_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_sepconv1d_stream.h deleted file mode 100644 index b0f6ce9..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_sepconv1d_stream.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef NNET_SEPARABLE_CONV1D_STREAM_H_ -#define NNET_SEPARABLE_CONV1D_STREAM_H_ - -#include "nnet_common.h" -#include "hls_stream.h" -#include "nnet_sepconv_stream.h" -#include "nnet_conv1d_stream.h" - -namespace nnet { - -template -void depthwise_conv_1d_encoded_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_chan], - typename CONFIG_T::bias_t biases[CONFIG_T::n_chan]) -{ - assert(CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - - hls::stream data_window[CONFIG_T::filt_width * CONFIG_T::n_chan]; - const int win_depth = CONFIG_T::out_width; - for (unsigned i_out = 0; i_out < CONFIG_T::filt_width * CONFIG_T::n_chan; i_out++) { - #pragma HLS STREAM variable=data_window[i_out] depth=win_depth - } - - #pragma HLS ARRAY_PARTITION variable=CONFIG_T::pixels complete - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - unsigned outputs_ready = 0; - - ap_uint pixel_idx[data_T::size / CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=pixel_idx complete - - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width / (data_T::size / CONFIG_T::n_chan); i_iw++) { - #pragma HLS LOOP_FLATTEN - if (CONFIG_T::strategy == nnet::latency && data_T::size / CONFIG_T::n_chan == 1) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - } - compute_scaled_indices_1d(i_iw, pixel_idx); - compute_depthwise_output_encoded(data.read(), data_window, res, res_pack, outputs_ready, weights, biases, pixel_idx); - } -} - -template -void depthwise_conv_1d_buffer_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::weight_t weights[CONFIG_T::filt_width * CONFIG_T::n_chan], - typename CONFIG_T::bias_t biases[CONFIG_T::n_chan]) -{ - assert(CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width; i_iw++) { - #pragma HLS LOOP_FLATTEN - if (CONFIG_T::strategy == nnet::latency) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - } - compute_depthwise_output_buffer_1d(data.read(), res, weights, biases); - } -} - -template -void pointwise_conv_1d_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::weight_t weights[CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - assert(CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - assert(CONFIG_T::filt_width == 1); - - #pragma HLS ARRAY_PARTITION variable=weights complete - #pragma HLS ARRAY_PARTITION variable=biases complete - - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width / (data_T::size / CONFIG_T::n_chan); i_iw++) { - if (CONFIG_T::strategy == nnet::latency && data_T::size / CONFIG_T::n_chan == 1) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - } - if (i_iw % CONFIG_T::stride_width == 0) { - pointwise_mult_buffer(data.read(), res, weights, biases); - } else { - data.read(); - } - } -} - - -template -void separable_conv_1d_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::depthwise_config::weight_t depthwise_weights[CONFIG_T::depthwise_config::filt_width * CONFIG_T::depthwise_config::n_chan], - typename CONFIG_T::pointwise_config::weight_t pointwise_weights[CONFIG_T::pointwise_config::n_chan * CONFIG_T::pointwise_config::n_filt], - typename CONFIG_T::depthwise_config::bias_t depthwise_biases[CONFIG_T::depthwise_config::n_chan], - typename CONFIG_T::pointwise_config::bias_t pointwise_biases[CONFIG_T::pointwise_config::n_filt] -) { - #pragma HLS DATAFLOW - - hls::stream depthwise_res; - unsigned res_depth = CONFIG_T::depthwise_config::out_width; - #pragma HLS STREAM variable=depthwise_res depth=res_depth - - switch(CONFIG_T::depthwise_config::implementation){ - case conv_implementation::linebuffer: - depthwise_conv_1d_buffer_cl(data, depthwise_res, depthwise_weights, depthwise_biases); - break; - case conv_implementation::encoded: - depthwise_conv_1d_encoded_cl(data, depthwise_res, depthwise_weights, depthwise_biases); - break; - } - pointwise_conv_1d_cl(depthwise_res, res, pointwise_weights, pointwise_biases); -} - -} -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_sepconv2d_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_sepconv2d_stream.h deleted file mode 100644 index 69e2726..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_sepconv2d_stream.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef NNET_SEPARABLE_CONV2D_STREAM_H_ -#define NNET_SEPARABLE_CONV2D_STREAM_H_ - -#include "nnet_common.h" -#include "hls_stream.h" -#include "nnet_sepconv_stream.h" -#include "nnet_conv2d_stream.h" - -namespace nnet { - -template -void depthwise_conv_2d_encoded_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan], - typename CONFIG_T::bias_t biases[CONFIG_T::n_chan]) -{ - assert(CONFIG_T::pad_top == 0 && CONFIG_T::pad_bottom == 0 && CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - assert(CONFIG_T::filt_height == CONFIG_T::filt_width); - - hls::stream data_window[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan]; - const int win_depth = CONFIG_T::filt_height * CONFIG_T::out_width; - for (unsigned i_out = 0; i_out < CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan; i_out++) { - #pragma HLS STREAM variable=data_window[i_out] depth=win_depth - } - - #pragma HLS ARRAY_PARTITION variable=CONFIG_T::pixels complete - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - unsigned outputs_ready = 0; - - ap_uint pixel_idx[data_T::size / CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=pixel_idx complete - - ReadInputHeight: for (unsigned i_ih = 0; i_ih < CONFIG_T::in_height; i_ih++) { - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width / (data_T::size / CONFIG_T::n_chan); i_iw++) { - #pragma HLS LOOP_FLATTEN - if (CONFIG_T::strategy == nnet::latency && data_T::size / CONFIG_T::n_chan == 1) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - } - compute_scaled_indices_2d(i_ih, i_iw, pixel_idx); - compute_depthwise_output_encoded(data.read(), data_window, res, res_pack, outputs_ready, weights, biases, pixel_idx); - } - } -} - -// Line Buffer Implementation (Phil's) -template -void depthwise_conv_2d_buffer_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::weight_t weights[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan], - typename CONFIG_T::bias_t biases[CONFIG_T::n_chan]) -{ - assert(CONFIG_T::pad_top == 0 && CONFIG_T::pad_bottom == 0 && CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - - static ap_shift_reg line_buffer[CONFIG_T::filt_height - 1][CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable = line_buffer complete dim = 2 - - ReadInputHeight: for (unsigned i_ih = 0; i_ih < CONFIG_T::in_height; i_ih++) { - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width; i_iw++) { - #pragma HLS LOOP_FLATTEN - if (CONFIG_T::strategy == nnet::latency) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - } - if (CONFIG_T::filt_height > 1) { - compute_depthwise_output_buffer_2d(data.read(), line_buffer, res, weights, biases); - } else { - compute_depthwise_output_buffer_1d(data.read(), res, weights, biases); - } - } - } -} - - -template -void pointwise_conv_2d_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::weight_t weights[CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt]) -{ - assert(CONFIG_T::pad_top == 0 && CONFIG_T::pad_bottom == 0 && CONFIG_T::pad_left == 0 && CONFIG_T::pad_right == 0); - assert(CONFIG_T::filt_height == 1 && CONFIG_T::filt_width == 1); - - #pragma HLS ARRAY_PARTITION variable=weights complete - #pragma HLS ARRAY_PARTITION variable=biases complete - - ReadInputHeight: for (unsigned i_ih = 0; i_ih < CONFIG_T::in_height; i_ih++) { - ReadInputWidth: for (unsigned i_iw = 0; i_iw < CONFIG_T::in_width / (data_T::size / CONFIG_T::n_chan); i_iw++) { - if (CONFIG_T::strategy == nnet::latency && data_T::size / CONFIG_T::n_chan == 1) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - } - if (i_ih % CONFIG_T::stride_height == 0 && i_iw % CONFIG_T::stride_width == 0) { - pointwise_mult_buffer(data.read(), res, weights, biases); - } else { - data.read(); - } - } - } -} - -template -void separable_conv_2d_cl( - hls::stream &data, - hls::stream &res, - typename CONFIG_T::depthwise_config::weight_t depthwise_weights[CONFIG_T::depthwise_config::filt_height * CONFIG_T::depthwise_config::filt_width * CONFIG_T::depthwise_config::n_chan], - typename CONFIG_T::pointwise_config::weight_t pointwise_weights[CONFIG_T::pointwise_config::n_chan * CONFIG_T::pointwise_config::n_filt], - typename CONFIG_T::depthwise_config::bias_t depthwise_biases[CONFIG_T::depthwise_config::n_chan], - typename CONFIG_T::pointwise_config::bias_t pointwise_biases[CONFIG_T::pointwise_config::n_filt] -) { - #pragma HLS DATAFLOW - - hls::stream depthwise_res; - unsigned res_depth = CONFIG_T::depthwise_config::out_height * CONFIG_T::depthwise_config::out_width; - #pragma HLS STREAM variable=depthwise_res depth=res_depth - - switch(CONFIG_T::depthwise_config::implementation){ - case conv_implementation::linebuffer: - depthwise_conv_2d_buffer_cl(data, depthwise_res, depthwise_weights, depthwise_biases); - break; - case conv_implementation::encoded: - depthwise_conv_2d_encoded_cl(data, depthwise_res, depthwise_weights, depthwise_biases); - break; - } - - pointwise_conv_2d_cl(depthwise_res, res, pointwise_weights, pointwise_biases); -} - -} -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_sepconv_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_sepconv_stream.h deleted file mode 100644 index 6c3c3db..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_sepconv_stream.h +++ /dev/null @@ -1,307 +0,0 @@ -#ifndef NNET_SEPARABLE_CONV_STREAM_H_ -#define NNET_SEPARABLE_CONV_STREAM_H_ - -#include "nnet_common.h" -#include "hls_stream.h" -#include "nnet_conv_stream.h" - -namespace nnet { - -template -void depthwise_product( - data_T data[CONFIG_T::kernel_size * CONFIG_T::n_chan], - res_T res[CONFIG_T::n_chan], - typename CONFIG_T::weight_t weights[CONFIG_T::kernel_size * CONFIG_T::n_chan], - typename CONFIG_T::bias_t biases[CONFIG_T::n_chan] -) { - #pragma HLS INLINE - - typename CONFIG_T::accum_t mult[CONFIG_T::kernel_size * CONFIG_T::n_chan]; - typename CONFIG_T::accum_t acc[CONFIG_T::n_chan]; - - // Use a function_instantiate in case it helps to explicitly optimize unchanging weights/biases - #pragma HLS function_instantiate variable=weights - - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - - #pragma HLS ARRAY_PARTITION variable=mult complete - - int multiplier_limit = ceil(float(CONFIG_T::kernel_size * CONFIG_T::n_chan) / float(CONFIG_T::reuse_factor)) - floor(float(CONFIG_T::n_zeros) / float(CONFIG_T::reuse_factor)); - CONFIG_T::mult_config::template product::limit(multiplier_limit); - - // Do the matrix-multiply - Product: for(int ii = 0; ii < CONFIG_T::kernel_size * CONFIG_T::n_chan; ii++) { - #pragma HLS UNROLL - mult[ii] = CONFIG_T::mult_config::template product::product(data[ii], weights[ii]); - } - - // Initialize accumulator with input biases - ResetAccum: for(int iacc = 0; iacc < CONFIG_T::n_chan; iacc++) { - #pragma HLS UNROLL - acc[iacc] = (typename CONFIG_T::accum_t) biases[iacc]; - } - - // Accumulate multiplication result - Accum1: for(int ii = 0; ii < CONFIG_T::kernel_size; ii++) { - Accum2: for(int jj = 0; jj < CONFIG_T::n_chan; jj++) { - int index = ii * CONFIG_T::n_chan + jj; - acc[jj] += mult[index]; - } - } - - // Cast to "res_t" type - Result: for(int ires = 0; ires < CONFIG_T::n_chan; ires++){ - #pragma HLS UNROLL - res[ires] = cast(acc[ires]); - } -} - -template -void depthwise_mult_buffer( - hls::stream data_window[CONFIG_T::kernel_size * CONFIG_T::n_chan], - res_T& res_pack, - hls::stream& res_stream, - unsigned & outputs_ready, - typename CONFIG_T::weight_t weights[CONFIG_T::kernel_size * CONFIG_T::n_chan], - typename CONFIG_T::bias_t biases[CONFIG_T::n_chan] -) { - #pragma HLS INLINE - - typename data_T::value_type data[CONFIG_T::kernel_size * CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=data complete - typename res_T::value_type res[CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=res complete - - InitData: for (int id = 0; id < CONFIG_T::kernel_size * CONFIG_T::n_chan; id++) { - #pragma HLS UNROLL - data[id] = data_window[id].read(); - } - - #pragma HLS INLINE region - if (CONFIG_T::strategy == nnet::latency) { - depthwise_product(data, res, weights, biases); - } else { - assert("Resource strategy for DepthwiseConv2D is not supported." && false); - } - - CastLoop: for (unsigned jj = 0; jj < CONFIG_T::n_chan; jj++) { - #pragma HLS UNROLL - if (res_T::size / CONFIG_T::n_chan == 1) { - res_pack[jj] = res[jj]; - } else { - res_pack[outputs_ready * CONFIG_T::n_chan + jj] = res[jj]; - } - } - - if (res_T::size / CONFIG_T::n_chan == 1) { - res_stream.write(res_pack); - } else { - if (outputs_ready == (res_T::size / CONFIG_T::n_chan) - 1) { - res_stream.write(res_pack); - outputs_ready = 0; - } else { - outputs_ready++; - } - } -} - -template -void compute_depthwise_output_encoded( - const data_T& in_elem, - hls::stream data_window[CONFIG_T::kernel_size * CONFIG_T::n_chan], - hls::stream &res, - res_T &res_pack, - unsigned &outputs_ready, - typename CONFIG_T::weight_t weights[CONFIG_T::kernel_size * CONFIG_T::n_chan], - typename CONFIG_T::bias_t biases[CONFIG_T::n_chan], - ap_uint *pixel_idx -) { - #pragma HLS INLINE - - MultLoop: for (unsigned p = 0; p < data_T::size / CONFIG_T::n_chan; p++) { - #pragma HLS PIPELINE II=CONFIG_T::reuse_factor - CopyDataFilt: for (unsigned f = 0; f < CONFIG_T::kernel_size; f++) { - #pragma HLS UNROLL - CopyDataChan: for (unsigned c = 0; c < CONFIG_T::n_chan; c++) { - #pragma HLS UNROLL - if (pixel_idx[p][f]) data_window[f * CONFIG_T::n_chan + c].write(in_elem[p * CONFIG_T::n_chan + c]); - } - } - if (pixel_idx[p][CONFIG_T::kernel_size - 1]) { - depthwise_mult_buffer(data_window, res_pack, res, outputs_ready, weights, biases); - } - } -} - - -template -void pointwise_mult_buffer( - const data_T &data_pack, - hls::stream &res_stream, - typename CONFIG_T::weight_t weights[CONFIG_T::n_chan * CONFIG_T::n_filt], - typename CONFIG_T::bias_t biases[CONFIG_T::n_filt] -) { - #pragma HLS INLINE - - typename data_T::value_type data[CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=data complete - - typename res_T::value_type res[CONFIG_T::n_filt]; - #pragma HLS ARRAY_PARTITION variable=res complete - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - - InitData: for (int id = 0; id < CONFIG_T::n_chan; id++) { - #pragma HLS UNROLL - data[id] = data_pack[id]; - } - - #pragma HLS INLINE region - if (CONFIG_T::strategy == nnet::latency) { - dense_latency(data, res, weights, biases); - } else { - dense_resource(data, res, weights, biases); - } - - CastLoop: for (unsigned jj = 0; jj < CONFIG_T::n_filt; jj++) { - #pragma HLS UNROLL - res_pack[jj] = res[jj]; - } - - res_stream.write(res_pack); -} - -// Line Buffer Implementation (Phil's) -template -void compute_depthwise_output_buffer_1d( - const data_T& in_elem, - hls::stream &res_stream, - typename CONFIG_T::weight_t weights[CONFIG_T::kernel_size * CONFIG_T::n_chan], - typename CONFIG_T::bias_t biases[CONFIG_T::n_chan] -) { - #pragma HLS INLINE - - // Thresholds - const static int lShiftX = CONFIG_T::filt_width - 1; - - // Counters - static int pX = 0; - static int sX = 0; - - static typename data_T::value_type kernel_data[CONFIG_T::filt_width * CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=kernel_data complete - - typename res_T::value_type res_out[CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=res_out complete dim = 0 - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - - // Add pixel to buffer - nnet::kernel_shift_1d(in_elem, kernel_data); - - // Check to see if we have a full kernel - if ((sX - lShiftX) == 0 && pX > lShiftX - 1) { - // Dense multiply - #pragma HLS INLINE region - if (CONFIG_T::strategy == nnet::latency) { - depthwise_product(kernel_data, res_out, weights, biases); - } else { - assert("Resource strategy for DepthwiseConv1D is not supported." && false); - } - - // Pack output - CastLoop: for (unsigned i_ic = 0; i_ic < CONFIG_T::n_filt; i_ic++) { - #pragma HLS UNROLL - res_pack[i_ic] = res_out[i_ic]; - } - - // Write output to stream when output ready - res_stream.write(res_pack); - } - - // Pointer Housekeeping - if (pX + 1 == CONFIG_T::in_width) // Includes padding, end of line (padded) - { - pX = 0; - sX = 0; - } else { - pX = pX + 1; - sX = ((sX - lShiftX) == 0) ? sX - CONFIG_T::stride_width + 1 : sX + 1; - } - } - -template -void compute_depthwise_output_buffer_2d( - const data_T& in_elem, - ap_shift_reg line_buffer[MAX(CONFIG_T::filt_height - 1,1)][CONFIG_T::n_chan], - hls::stream &res_stream, - typename CONFIG_T::weight_t weights[CONFIG_T::kernel_size * CONFIG_T::n_chan], - typename CONFIG_T::bias_t biases[CONFIG_T::n_chan] -) { - #pragma HLS INLINE - - // Thresholds - const static int lShiftX = CONFIG_T::filt_width - 1; - const static int lShiftY = CONFIG_T::filt_height - 1; - - // counters - static int pX = 0; // pixel X - static int pY = 0; // pixel Y - - static int sX = 0; // stride X - static int sY = 0; // stride Y - - static typename data_T::value_type kernel_data[CONFIG_T::filt_height * CONFIG_T::filt_width * CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=kernel_data complete - - typename res_T::value_type res_out[CONFIG_T::n_chan]; - #pragma HLS ARRAY_PARTITION variable=res_out complete dim = 0 - - res_T res_pack; - #pragma HLS DATA_PACK variable=res_pack - - // Add pixel to buffer - nnet::shift_line_buffer(in_elem, line_buffer, kernel_data); - - // Check to see if we have a full kernel - if ((sX - lShiftX) == 0 && (sY - lShiftY) == 0 && pY > lShiftY - 1 && pX > lShiftX - 1) { - // Dense multiply - #pragma HLS INLINE region - if (CONFIG_T::strategy == nnet::latency) { - depthwise_product(kernel_data, res_out, weights, biases); - } else { - assert("Resource strategy for DepthwiseConv2D is not supported." && false); - } - - // Pack output - CastLoop: for (unsigned i_ic = 0; i_ic < CONFIG_T::n_filt; i_ic++) { - #pragma HLS UNROLL - res_pack[i_ic] = res_out[i_ic]; - } - - // Write output to stream when output ready - res_stream.write(res_pack); - } - - // Pointer Housekeeping - if (pX + 1 == CONFIG_T::in_width) // Includes padding, end of line (padded) - { - pX = 0; - sX = 0; - if (pY + 1 == CONFIG_T::in_height) { // Reached bottom of image - pY = 0; - sY = 0; - } else { - pY = pY + 1; - sY = ((sY - lShiftY) == 0) ? sY - CONFIG_T::stride_height + 1 : sY + 1; - } - } else { - pX = pX + 1; - sX = ((sX - lShiftX) == 0) ? sX - CONFIG_T::stride_width + 1 : sX + 1; - } - } - -} -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_stream.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_stream.h deleted file mode 100644 index 6a13404..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_stream.h +++ /dev/null @@ -1,120 +0,0 @@ - -#ifndef NNET_STREAM_H -#define NNET_STREAM_H - -#include "hls_stream.h" - -namespace nnet { - -struct broadcast_config -{ - static const unsigned in_height = 10; - static const unsigned in_width = 10; - static const unsigned n_chan = 1; - static const unsigned n_dupl = 2; -}; - -template -void clone_stream(hls::stream &data, hls::stream &res1, hls::stream &res2) { - CloneLoop: for (int i = 0; i < N / data_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data1; - res_T out_data2; - #pragma HLS DATA_PACK variable=out_data1 - #pragma HLS DATA_PACK variable=out_data2 - - ClonePack: for (int j = 0; j < data_T::size; j++) { - #pragma HLS UNROLL - out_data1[j] = in_data[j]; - out_data2[j] = in_data[j]; - } - - res1.write(out_data1); - res2.write(out_data2); - } -} - -template -void repack_stream(hls::stream &data, hls::stream &res) { - if (data_T::size == res_T::size) { - for (int i = 0; i < N / data_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - for (int j = 0; j < data_T::size; j++) { - #pragma HLS UNROLL - out_data[j] = in_data[j]; - } - - res.write(out_data); - } - } else if (data_T::size > res_T::size) { - constexpr unsigned pack_diff = data_T::size / res_T::size; - for (int i = 0; i < N / data_T::size; i++) { - if (N / data_T::size > 1) { - #pragma HLS PIPELINE - } - - data_T in_data = data.read(); - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - - for (int j = 0; j < pack_diff; j++) { - #pragma HLS PIPELINE - - res_T out_data; - for (int k = 0; k < res_T::size; k++) { - #pragma HLS UNROLL - out_data[k] = in_data[j * res_T::size + k]; - } - res.write(out_data); - } - } - } else { // data_T::size < res_T::size - res_T out_data; - constexpr unsigned pack_diff = res_T::size / data_T::size; - unsigned pack_cnt = 0; - for (int i = 0; i < N / data_T::size; i++) { - #pragma HLS PIPELINE - - data_T in_data = data.read(); - for (int j = 0; j < data_T::size; j++) { - #pragma HLS UNROLL - out_data[pack_cnt * data_T::size + j] = in_data[j]; - } - - if (pack_cnt == pack_diff - 1) { - res.write(out_data); - pack_cnt = 0; - } else { - pack_cnt++; - } - } - } -} - -template -void broadcast_stream(hls::stream &data, hls::stream &res) { - BroadcastLoop: for (int i = 0; i < CONFIG_T::in_height * CONFIG_T::in_width * CONFIG_T::n_chan / data_T::size; i++) { - #pragma HLS PIPELINE - data_T in_data = data.read(); - for (int j = 0; j < CONFIG_T::n_dupl; j++) { - #pragma HLS PIPELINE - res_T out_data; - #pragma HLS DATA_PACK variable=out_data - for (int k = 0; k < res_T::size; k++) { - #pragma HLS UNROLL - out_data[k] = in_data[k]; - } - res.write(out_data); - } - } -} -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_types.h b/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_types.h deleted file mode 100644 index 64bc0fb..0000000 --- a/model/AE_model/hls4ml_prj/firmware/nnet_utils/nnet_types.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef NNET_TYPES_H_ -#define NNET_TYPES_H_ - -#include -#include -#include - -namespace nnet { - -// Fixed-size array -template -struct array { - typedef T value_type; - static const unsigned size = N; - - T data[N]; - - T& operator[](size_t pos) { - return data[pos]; - } - - const T& operator[](size_t pos) const { - return data[pos]; - } - - array& operator=(const array &other) { - if(&other == this) - return *this; - - assert(N == other.size && "Array sizes must match."); - - for (unsigned i = 0; i < N; i++) { - #pragma HLS UNROLL - data[i] = other[i]; - } - return *this; - } -}; - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/parameters.h b/model/AE_model/hls4ml_prj/firmware/parameters.h deleted file mode 100644 index 6814832..0000000 --- a/model/AE_model/hls4ml_prj/firmware/parameters.h +++ /dev/null @@ -1,193 +0,0 @@ -#ifndef PARAMETERS_H_ -#define PARAMETERS_H_ - -#include "ap_int.h" -#include "ap_fixed.h" - -#include "nnet_utils/nnet_helpers.h" -//hls-fpga-machine-learning insert includes -#include "nnet_utils/nnet_activation.h" -#include "nnet_utils/nnet_activation_stream.h" -#include "nnet_utils/nnet_dense.h" -#include "nnet_utils/nnet_dense_compressed.h" -#include "nnet_utils/nnet_dense_stream.h" - -//hls-fpga-machine-learning insert weights -#include "weights/w2.h" -#include "weights/b2.h" -#include "weights/w4.h" -#include "weights/b4.h" -#include "weights/w6.h" -#include "weights/b6.h" -#include "weights/w8.h" -#include "weights/b8.h" -#include "weights/w10.h" -#include "weights/b10.h" -#include "weights/w12.h" -#include "weights/b12.h" - -//hls-fpga-machine-learning insert layer-config -// dense_12 -struct config2 : nnet::dense_config { - static const unsigned n_in = N_INPUT_1_1; - static const unsigned n_out = N_LAYER_2; - static const unsigned io_type = nnet::io_parallel; - static const unsigned strategy = nnet::latency; - static const unsigned reuse_factor = 1; - static const unsigned n_zeros = 0; - static const unsigned n_nonzeros = 3200; - static const bool store_weights_in_bram = false; - typedef ap_fixed<16,6> accum_t; - typedef model_default_t bias_t; - typedef model_default_t weight_t; - typedef ap_uint<1> index_t; - template - using product = nnet::product::mult; -}; - -// dense_12_relu -struct relu_config3 : nnet::activ_config { - static const unsigned n_in = N_LAYER_2; - static const unsigned table_size = 1024; - static const unsigned io_type = nnet::io_parallel; - static const unsigned reuse_factor = 1; - typedef ap_fixed<18,8> table_t; -}; - -// dense_13 -struct config4 : nnet::dense_config { - static const unsigned n_in = N_LAYER_2; - static const unsigned n_out = N_LAYER_4; - static const unsigned io_type = nnet::io_parallel; - static const unsigned strategy = nnet::latency; - static const unsigned reuse_factor = 1; - static const unsigned n_zeros = 0; - static const unsigned n_nonzeros = 512; - static const bool store_weights_in_bram = false; - typedef ap_fixed<16,6> accum_t; - typedef model_default_t bias_t; - typedef model_default_t weight_t; - typedef ap_uint<1> index_t; - template - using product = nnet::product::mult; -}; - -// dense_13_relu -struct relu_config5 : nnet::activ_config { - static const unsigned n_in = N_LAYER_4; - static const unsigned table_size = 1024; - static const unsigned io_type = nnet::io_parallel; - static const unsigned reuse_factor = 1; - typedef ap_fixed<18,8> table_t; -}; - -// encoder_output -struct config6 : nnet::dense_config { - static const unsigned n_in = N_LAYER_4; - static const unsigned n_out = N_LAYER_6; - static const unsigned io_type = nnet::io_parallel; - static const unsigned strategy = nnet::latency; - static const unsigned reuse_factor = 1; - static const unsigned n_zeros = 0; - static const unsigned n_nonzeros = 32; - static const bool store_weights_in_bram = false; - typedef ap_fixed<16,6> accum_t; - typedef model_default_t bias_t; - typedef model_default_t weight_t; - typedef ap_uint<1> index_t; - template - using product = nnet::product::mult; -}; - -// encoder_output_relu -struct relu_config7 : nnet::activ_config { - static const unsigned n_in = N_LAYER_6; - static const unsigned table_size = 1024; - static const unsigned io_type = nnet::io_parallel; - static const unsigned reuse_factor = 1; - typedef ap_fixed<18,8> table_t; -}; - -// dense_14 -struct config8 : nnet::dense_config { - static const unsigned n_in = N_LAYER_6; - static const unsigned n_out = N_LAYER_8; - static const unsigned io_type = nnet::io_parallel; - static const unsigned strategy = nnet::latency; - static const unsigned reuse_factor = 1; - static const unsigned n_zeros = 0; - static const unsigned n_nonzeros = 32; - static const bool store_weights_in_bram = false; - typedef ap_fixed<16,6> accum_t; - typedef model_default_t bias_t; - typedef model_default_t weight_t; - typedef ap_uint<1> index_t; - template - using product = nnet::product::mult; -}; - -// dense_14_relu -struct relu_config9 : nnet::activ_config { - static const unsigned n_in = N_LAYER_8; - static const unsigned table_size = 1024; - static const unsigned io_type = nnet::io_parallel; - static const unsigned reuse_factor = 1; - typedef ap_fixed<18,8> table_t; -}; - -// dense_15 -struct config10 : nnet::dense_config { - static const unsigned n_in = N_LAYER_8; - static const unsigned n_out = N_LAYER_10; - static const unsigned io_type = nnet::io_parallel; - static const unsigned strategy = nnet::latency; - static const unsigned reuse_factor = 1; - static const unsigned n_zeros = 0; - static const unsigned n_nonzeros = 512; - static const bool store_weights_in_bram = false; - typedef ap_fixed<16,6> accum_t; - typedef model_default_t bias_t; - typedef model_default_t weight_t; - typedef ap_uint<1> index_t; - template - using product = nnet::product::mult; -}; - -// dense_15_relu -struct relu_config11 : nnet::activ_config { - static const unsigned n_in = N_LAYER_10; - static const unsigned table_size = 1024; - static const unsigned io_type = nnet::io_parallel; - static const unsigned reuse_factor = 1; - typedef ap_fixed<18,8> table_t; -}; - -// ecoder_output -struct config12 : nnet::dense_config { - static const unsigned n_in = N_LAYER_10; - static const unsigned n_out = N_LAYER_12; - static const unsigned io_type = nnet::io_parallel; - static const unsigned strategy = nnet::latency; - static const unsigned reuse_factor = 1; - static const unsigned n_zeros = 0; - static const unsigned n_nonzeros = 3200; - static const bool store_weights_in_bram = false; - typedef ap_fixed<16,6> accum_t; - typedef model_default_t bias_t; - typedef model_default_t weight_t; - typedef ap_uint<1> index_t; - template - using product = nnet::product::mult; -}; - -// ecoder_output_sigmoid -struct sigmoid_config13 : nnet::activ_config { - static const unsigned n_in = N_LAYER_12; - static const unsigned table_size = 1024; - static const unsigned io_type = nnet::io_parallel; - static const unsigned reuse_factor = 1; - typedef ap_fixed<18,8> table_t; -}; - - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b10.h b/model/AE_model/hls4ml_prj/firmware/weights/b10.h deleted file mode 100644 index 8b00837..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b10.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [32] -//Min 0.000000000000 -//Max 0.000000000000 -//Number of zeros 32 - -#ifndef B10_H_ -#define B10_H_ - -#ifndef __SYNTHESIS__ -model_default_t b10[32]; -#else -model_default_t b10[32] = {0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b10.txt b/model/AE_model/hls4ml_prj/firmware/weights/b10.txt deleted file mode 100644 index d9ed7e6..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b10.txt +++ /dev/null @@ -1 +0,0 @@ -0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b12.h b/model/AE_model/hls4ml_prj/firmware/weights/b12.h deleted file mode 100644 index 7e6c00b..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b12.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [100] -//Min 0.000000000000 -//Max 0.000000000000 -//Number of zeros 100 - -#ifndef B12_H_ -#define B12_H_ - -#ifndef __SYNTHESIS__ -model_default_t b12[100]; -#else -model_default_t b12[100] = {0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b12.txt b/model/AE_model/hls4ml_prj/firmware/weights/b12.txt deleted file mode 100644 index a8134e9..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b12.txt +++ /dev/null @@ -1 +0,0 @@ -0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b14.h b/model/AE_model/hls4ml_prj/firmware/weights/b14.h deleted file mode 100644 index 556a48b..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b14.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [32] -//Min 0.000000000000 -//Max 0.000000000000 -//Number of zeros 32 - -#ifndef B14_H_ -#define B14_H_ - -#ifndef __SYNTHESIS__ -model_default_t b14[32]; -#else -model_default_t b14[32] = {0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b14.txt b/model/AE_model/hls4ml_prj/firmware/weights/b14.txt deleted file mode 100644 index d9ed7e6..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b14.txt +++ /dev/null @@ -1 +0,0 @@ -0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b16.h b/model/AE_model/hls4ml_prj/firmware/weights/b16.h deleted file mode 100644 index 0e59240..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b16.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [100] -//Min 0.000000000000 -//Max 0.000000000000 -//Number of zeros 100 - -#ifndef B16_H_ -#define B16_H_ - -#ifndef __SYNTHESIS__ -model_default_t b16[100]; -#else -model_default_t b16[100] = {0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b16.txt b/model/AE_model/hls4ml_prj/firmware/weights/b16.txt deleted file mode 100644 index a8134e9..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b16.txt +++ /dev/null @@ -1 +0,0 @@ -0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b2.h b/model/AE_model/hls4ml_prj/firmware/weights/b2.h deleted file mode 100644 index e3ca969..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b2.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [32] -//Min 0.000000000000 -//Max 0.000000000000 -//Number of zeros 32 - -#ifndef B2_H_ -#define B2_H_ - -#ifndef __SYNTHESIS__ -model_default_t b2[32]; -#else -model_default_t b2[32] = {0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b2.txt b/model/AE_model/hls4ml_prj/firmware/weights/b2.txt deleted file mode 100644 index d9ed7e6..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b2.txt +++ /dev/null @@ -1 +0,0 @@ -0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b4.h b/model/AE_model/hls4ml_prj/firmware/weights/b4.h deleted file mode 100644 index 183c1b9..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b4.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [16] -//Min 0.000000000000 -//Max 0.000000000000 -//Number of zeros 16 - -#ifndef B4_H_ -#define B4_H_ - -#ifndef __SYNTHESIS__ -model_default_t b4[16]; -#else -model_default_t b4[16] = {0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b4.txt b/model/AE_model/hls4ml_prj/firmware/weights/b4.txt deleted file mode 100644 index 5428c9a..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b4.txt +++ /dev/null @@ -1 +0,0 @@ -0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b6.h b/model/AE_model/hls4ml_prj/firmware/weights/b6.h deleted file mode 100644 index ec63536..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b6.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [2] -//Min 0.000000000000 -//Max 0.000000000000 -//Number of zeros 2 - -#ifndef B6_H_ -#define B6_H_ - -#ifndef __SYNTHESIS__ -model_default_t b6[2]; -#else -model_default_t b6[2] = {0.0000000000, 0.0000000000}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b6.txt b/model/AE_model/hls4ml_prj/firmware/weights/b6.txt deleted file mode 100644 index c26674c..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b6.txt +++ /dev/null @@ -1 +0,0 @@ -0.0000000000, 0.0000000000 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b8.h b/model/AE_model/hls4ml_prj/firmware/weights/b8.h deleted file mode 100644 index 2c5ce78..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b8.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [16] -//Min 0.000000000000 -//Max 0.000000000000 -//Number of zeros 16 - -#ifndef B8_H_ -#define B8_H_ - -#ifndef __SYNTHESIS__ -model_default_t b8[16]; -#else -model_default_t b8[16] = {0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/b8.txt b/model/AE_model/hls4ml_prj/firmware/weights/b8.txt deleted file mode 100644 index 5428c9a..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/b8.txt +++ /dev/null @@ -1 +0,0 @@ -0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000, 0.0000000000 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w10.h b/model/AE_model/hls4ml_prj/firmware/weights/w10.h deleted file mode 100644 index 80a4c19..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w10.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [16, 32] -//Min -0.352442234755 -//Max 0.353284984827 -//Number of zeros 0 - -#ifndef W10_H_ -#define W10_H_ - -#ifndef __SYNTHESIS__ -model_default_t w10[512]; -#else -model_default_t w10[512] = {-0.2275208235, 0.3082304895, 0.1800996959, 0.2034200132, -0.2012728602, 0.3403718174, 0.0552271307, -0.2891793847, -0.2185921818, 0.0034347177, 0.1066854000, 0.1529252231, 0.2006288469, 0.0200164616, -0.2386060357, -0.2215379924, -0.1943666786, 0.2751011550, 0.2343889773, 0.2576518357, -0.1625823975, -0.2082014680, -0.0544431806, -0.1846607625, -0.2230741680, 0.2429945171, -0.0456264019, -0.0015500784, -0.1523861438, -0.2382044494, -0.0206743777, -0.1201468408, -0.0500834286, 0.2830089033, 0.1734263003, -0.3001326025, -0.0249982178, -0.1562978774, 0.2540569603, -0.0375117958, 0.2594088018, 0.1819643676, 0.0618646741, 0.1670542657, -0.2211384475, 0.1010208428, -0.0753359795, 0.2585909665, -0.0419860184, -0.2744349837, -0.1088495404, -0.2937373221, -0.2564277351, -0.0934027135, -0.1895358860, 0.1760981381, -0.1704975665, 0.3146800697, 0.2794551551, -0.1909430921, -0.2947703302, 0.0486355126, -0.2073825598, -0.2725280821, -0.3123051822, -0.2518325448, 0.3267821968, -0.1695666313, 0.2926388681, -0.2707174718, 0.2248588502, -0.2062643915, -0.0096379817, 0.1856124699, 0.1270824373, 0.1280062199, -0.0621027946, 0.2428835928, -0.1688695252, 0.0038179159, -0.2305536270, -0.2981361747, -0.0354891717, 0.1889837086, -0.1676718742, 0.0949990749, -0.1430640221, 0.3327633440, -0.2989251614, -0.0255858302, -0.0296791494, 0.2205516994, 0.2434230745, -0.2237346917, 0.0172477663, -0.0340667963, -0.0250683427, 0.1297706366, 0.2070741951, -0.1528227776, 0.3200515211, 0.2612022460, 0.1921924651, 0.1856037676, -0.2289730310, 0.2478084862, -0.0195558071, -0.3100901246, 0.1197377741, 0.0911069810, -0.0973462462, 0.1519419253, -0.2641048729, 0.1817909777, 0.1669467986, 0.1207279563, -0.2031643242, 0.2504229844, 0.1907920539, -0.2448119819, 0.3232031763, -0.0003559589, -0.1392454356, 0.3222679198, 0.1453048885, -0.1475199461, -0.0944620371, -0.3032215238, -0.2584781945, 0.0206812024, -0.0680159926, -0.1113737226, 0.2259374559, -0.0470007360, -0.0017995834, -0.2735584080, -0.2055287659, 0.3301214874, -0.3305052221, -0.1984400004, 0.3205256760, -0.2580772042, 0.0337751210, -0.3335041404, 0.0527746677, 0.0538113117, 0.0874045491, 0.2172114551, -0.0386245549, 0.0051392913, 0.2905812562, 0.2711844742, -0.1483853906, 0.2032188475, 0.3489165604, 0.3188896477, 0.0740482211, 0.1293331683, 0.1538384259, -0.0001787841, -0.0571397543, -0.0756666660, 0.0575815439, 0.1682687700, -0.3345464170, -0.3232658207, 0.3217707574, -0.2350947857, -0.3503476977, 0.1773255169, 0.3518048227, 0.3157989085, -0.1693667769, 0.0898123085, 0.3164514005, -0.1126992404, -0.1238104105, -0.0317032933, 0.1683525741, 0.1713339388, 0.3251459301, -0.1304003298, -0.0012708902, 0.1764050424, -0.2865330577, 0.0340652764, 0.2378383577, 0.2835174501, 0.3294073045, 0.3357509673, -0.2560856938, 0.1859615147, -0.1769715846, -0.0138154030, 0.0598699450, -0.0158913136, -0.0823198855, -0.3209212720, 0.2009522021, 0.1615334451, -0.2744819522, 0.2974085510, -0.0242449641, -0.1606869698, -0.0904551446, 0.0647872984, 0.1983544528, -0.2649611235, 0.0372025967, -0.2680608630, 0.2946036756, -0.2519363165, 0.2252288163, 0.3275773823, 0.3217299879, 0.1293477416, -0.2317273319, -0.1237588227, 0.2920588553, -0.1846632957, 0.1090042293, 0.2829982340, 0.0323745012, 0.2401002347, -0.3142516017, -0.1833192259, -0.0134719908, 0.1981300414, -0.1268013269, 0.3442352116, -0.2948865891, 0.1550362408, 0.0559218824, 0.1604460776, 0.1468872726, 0.2586494982, -0.3052357435, -0.2239862978, 0.1687305868, 0.1208128333, -0.0408568978, -0.0837748647, 0.3109740317, -0.0041743815, 0.0568111837, 0.0383190811, 0.3488295376, 0.2498562038, -0.1540075392, -0.1497431099, -0.0105088949, -0.2882824242, 0.1072375178, -0.2092705667, -0.2842192054, -0.0818458796, 0.0888592005, -0.2449749261, 0.1559201777, 0.0121440291, 0.1697528064, -0.3279210329, 0.2657649815, -0.0883849859, 0.2200192511, 0.0825938284, -0.1252645552, -0.2444246560, 0.1989120543, -0.3044442236, -0.2206419557, 0.1049216986, -0.2193154246, -0.2021956295, 0.1016009748, 0.2773639262, 0.0305283964, -0.3334370255, 0.2189579904, -0.3329224288, -0.0990564823, -0.2395814806, 0.2561912835, 0.3003133237, -0.1498526186, 0.2240231335, -0.1039067358, -0.3126262724, 0.0546000600, 0.1377198696, 0.0142539740, -0.0403669775, 0.2716446817, 0.0849537849, 0.2066553533, 0.0232850313, 0.0283947587, 0.1651740968, -0.2420846671, 0.1136370003, 0.1579180658, 0.0222873390, 0.1361654103, 0.0368761420, 0.0152870715, -0.1454091519, 0.0371851623, -0.0405742526, -0.3153141439, 0.1823998392, 0.2476879060, -0.2991707325, -0.2754312456, 0.3281438053, -0.0809356868, -0.2331432104, -0.0189241171, -0.2451652586, -0.0554777384, 0.1770366728, 0.2742199600, 0.1006063819, 0.0027036369, 0.3374569118, 0.2065615356, 0.0347138345, -0.0344504118, 0.1312245429, -0.2965571880, -0.1272049993, 0.3072389662, 0.2842449248, -0.1949390322, 0.3067487180, 0.2188158333, 0.3271263540, 0.1239545643, 0.2380576432, 0.2236246765, 0.3125979602, 0.3317807615, -0.2899005115, 0.2299596965, 0.0755452812, -0.0738242567, 0.2793456018, 0.1621693671, -0.1736021042, -0.2024077922, -0.1837069839, -0.2360445261, 0.2599993646, 0.2313966453, 0.0090459883, -0.1647223532, -0.1870670915, -0.2583354712, 0.0362845659, 0.3091036379, -0.1685210466, 0.2177402079, -0.1970733553, -0.2762058377, 0.3503495753, -0.3517559767, -0.0198392868, 0.0988778472, -0.0198321044, -0.3172486722, 0.2134489119, 0.0843075216, 0.1069885790, -0.3499679565, 0.0172621608, 0.0985274315, 0.0554323792, 0.1148934066, 0.0549394190, -0.3256316185, 0.3376344144, -0.2817167044, 0.2541795671, 0.0268414617, 0.2324669063, -0.2455783784, 0.1935249269, 0.2145981491, 0.2112136781, -0.2156590074, -0.2829781473, 0.3300987184, 0.3113561571, 0.3264960349, 0.0582289994, 0.1019130051, 0.2173345983, 0.2879592478, 0.2343896925, -0.2478350997, 0.3274871409, -0.0566456020, 0.1604240239, -0.3197723627, -0.2133100927, -0.1360211074, 0.2356049120, 0.3413688838, 0.1455393732, 0.3532849848, -0.0814617574, 0.2958364189, 0.1677473485, -0.0268767178, 0.0623139441, -0.1997307986, -0.2405238748, -0.0358990729, -0.2438806295, -0.0334214270, 0.2349555194, -0.2430299371, 0.0684872866, -0.3123852015, -0.1247319877, 0.2807880342, 0.1596897542, -0.1556291729, -0.1991823763, -0.2299897075, 0.2231928408, -0.2827836871, 0.2426159084, 0.2350266874, 0.1445495188, 0.1385463774, -0.3060532212, 0.0994293094, -0.1782524288, -0.2762955129, -0.1580466330, 0.1518516243, 0.2684151232, -0.1426591575, -0.1338749975, 0.1857272685, -0.2408898026, 0.0142179728, 0.0454348028, 0.1615466177, -0.0562961400, -0.0030682087, -0.1716280282, -0.3262225986, -0.2977030873, -0.2761867642, 0.3104097545, 0.0431731343, 0.1607292593, -0.2202814221, -0.3079095185, 0.0120231509, 0.2395457327, -0.3013288081, -0.3102622628, -0.1645497233, -0.1331436634, -0.2354290038, 0.1451896429, 0.2363980711, -0.0919347405, -0.0787511468, -0.3524422348, -0.1219792217, 0.2951319516, 0.2808180153, 0.0521595776, -0.0167918205, -0.1291591823, -0.3424662352, -0.2386297286, 0.1986821592, -0.0417306125, 0.2804038227, -0.1158757657, -0.1685333550, -0.0006595850, -0.1064274460, 0.0177696049, 0.3072566092, 0.1207943857, -0.1897403002, -0.2407633662, 0.0751309693, 0.3414125741, 0.2464052141, 0.2492965758, -0.2320017815, 0.1933802068, 0.1327735186, -0.2997762859, -0.0531712770, 0.3480670154, 0.1225398481, -0.2862635851, 0.3479690254, -0.2709419429, -0.2005229890, 0.2839653790, 0.2844883502, 0.2537063062, 0.0603832006, -0.2051936090}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w10.txt b/model/AE_model/hls4ml_prj/firmware/weights/w10.txt deleted file mode 100644 index e5ee67e..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w10.txt +++ /dev/null @@ -1 +0,0 @@ --0.2275208235, 0.3082304895, 0.1800996959, 0.2034200132, -0.2012728602, 0.3403718174, 0.0552271307, -0.2891793847, -0.2185921818, 0.0034347177, 0.1066854000, 0.1529252231, 0.2006288469, 0.0200164616, -0.2386060357, -0.2215379924, -0.1943666786, 0.2751011550, 0.2343889773, 0.2576518357, -0.1625823975, -0.2082014680, -0.0544431806, -0.1846607625, -0.2230741680, 0.2429945171, -0.0456264019, -0.0015500784, -0.1523861438, -0.2382044494, -0.0206743777, -0.1201468408, -0.0500834286, 0.2830089033, 0.1734263003, -0.3001326025, -0.0249982178, -0.1562978774, 0.2540569603, -0.0375117958, 0.2594088018, 0.1819643676, 0.0618646741, 0.1670542657, -0.2211384475, 0.1010208428, -0.0753359795, 0.2585909665, -0.0419860184, -0.2744349837, -0.1088495404, -0.2937373221, -0.2564277351, -0.0934027135, -0.1895358860, 0.1760981381, -0.1704975665, 0.3146800697, 0.2794551551, -0.1909430921, -0.2947703302, 0.0486355126, -0.2073825598, -0.2725280821, -0.3123051822, -0.2518325448, 0.3267821968, -0.1695666313, 0.2926388681, -0.2707174718, 0.2248588502, -0.2062643915, -0.0096379817, 0.1856124699, 0.1270824373, 0.1280062199, -0.0621027946, 0.2428835928, -0.1688695252, 0.0038179159, -0.2305536270, -0.2981361747, -0.0354891717, 0.1889837086, -0.1676718742, 0.0949990749, -0.1430640221, 0.3327633440, -0.2989251614, -0.0255858302, -0.0296791494, 0.2205516994, 0.2434230745, -0.2237346917, 0.0172477663, -0.0340667963, -0.0250683427, 0.1297706366, 0.2070741951, -0.1528227776, 0.3200515211, 0.2612022460, 0.1921924651, 0.1856037676, -0.2289730310, 0.2478084862, -0.0195558071, -0.3100901246, 0.1197377741, 0.0911069810, -0.0973462462, 0.1519419253, -0.2641048729, 0.1817909777, 0.1669467986, 0.1207279563, -0.2031643242, 0.2504229844, 0.1907920539, -0.2448119819, 0.3232031763, -0.0003559589, -0.1392454356, 0.3222679198, 0.1453048885, -0.1475199461, -0.0944620371, -0.3032215238, -0.2584781945, 0.0206812024, -0.0680159926, -0.1113737226, 0.2259374559, -0.0470007360, -0.0017995834, -0.2735584080, -0.2055287659, 0.3301214874, -0.3305052221, -0.1984400004, 0.3205256760, -0.2580772042, 0.0337751210, -0.3335041404, 0.0527746677, 0.0538113117, 0.0874045491, 0.2172114551, -0.0386245549, 0.0051392913, 0.2905812562, 0.2711844742, -0.1483853906, 0.2032188475, 0.3489165604, 0.3188896477, 0.0740482211, 0.1293331683, 0.1538384259, -0.0001787841, -0.0571397543, -0.0756666660, 0.0575815439, 0.1682687700, -0.3345464170, -0.3232658207, 0.3217707574, -0.2350947857, -0.3503476977, 0.1773255169, 0.3518048227, 0.3157989085, -0.1693667769, 0.0898123085, 0.3164514005, -0.1126992404, -0.1238104105, -0.0317032933, 0.1683525741, 0.1713339388, 0.3251459301, -0.1304003298, -0.0012708902, 0.1764050424, -0.2865330577, 0.0340652764, 0.2378383577, 0.2835174501, 0.3294073045, 0.3357509673, -0.2560856938, 0.1859615147, -0.1769715846, -0.0138154030, 0.0598699450, -0.0158913136, -0.0823198855, -0.3209212720, 0.2009522021, 0.1615334451, -0.2744819522, 0.2974085510, -0.0242449641, -0.1606869698, -0.0904551446, 0.0647872984, 0.1983544528, -0.2649611235, 0.0372025967, -0.2680608630, 0.2946036756, -0.2519363165, 0.2252288163, 0.3275773823, 0.3217299879, 0.1293477416, -0.2317273319, -0.1237588227, 0.2920588553, -0.1846632957, 0.1090042293, 0.2829982340, 0.0323745012, 0.2401002347, -0.3142516017, -0.1833192259, -0.0134719908, 0.1981300414, -0.1268013269, 0.3442352116, -0.2948865891, 0.1550362408, 0.0559218824, 0.1604460776, 0.1468872726, 0.2586494982, -0.3052357435, -0.2239862978, 0.1687305868, 0.1208128333, -0.0408568978, -0.0837748647, 0.3109740317, -0.0041743815, 0.0568111837, 0.0383190811, 0.3488295376, 0.2498562038, -0.1540075392, -0.1497431099, -0.0105088949, -0.2882824242, 0.1072375178, -0.2092705667, -0.2842192054, -0.0818458796, 0.0888592005, -0.2449749261, 0.1559201777, 0.0121440291, 0.1697528064, -0.3279210329, 0.2657649815, -0.0883849859, 0.2200192511, 0.0825938284, -0.1252645552, -0.2444246560, 0.1989120543, -0.3044442236, -0.2206419557, 0.1049216986, -0.2193154246, -0.2021956295, 0.1016009748, 0.2773639262, 0.0305283964, -0.3334370255, 0.2189579904, -0.3329224288, -0.0990564823, -0.2395814806, 0.2561912835, 0.3003133237, -0.1498526186, 0.2240231335, -0.1039067358, -0.3126262724, 0.0546000600, 0.1377198696, 0.0142539740, -0.0403669775, 0.2716446817, 0.0849537849, 0.2066553533, 0.0232850313, 0.0283947587, 0.1651740968, -0.2420846671, 0.1136370003, 0.1579180658, 0.0222873390, 0.1361654103, 0.0368761420, 0.0152870715, -0.1454091519, 0.0371851623, -0.0405742526, -0.3153141439, 0.1823998392, 0.2476879060, -0.2991707325, -0.2754312456, 0.3281438053, -0.0809356868, -0.2331432104, -0.0189241171, -0.2451652586, -0.0554777384, 0.1770366728, 0.2742199600, 0.1006063819, 0.0027036369, 0.3374569118, 0.2065615356, 0.0347138345, -0.0344504118, 0.1312245429, -0.2965571880, -0.1272049993, 0.3072389662, 0.2842449248, -0.1949390322, 0.3067487180, 0.2188158333, 0.3271263540, 0.1239545643, 0.2380576432, 0.2236246765, 0.3125979602, 0.3317807615, -0.2899005115, 0.2299596965, 0.0755452812, -0.0738242567, 0.2793456018, 0.1621693671, -0.1736021042, -0.2024077922, -0.1837069839, -0.2360445261, 0.2599993646, 0.2313966453, 0.0090459883, -0.1647223532, -0.1870670915, -0.2583354712, 0.0362845659, 0.3091036379, -0.1685210466, 0.2177402079, -0.1970733553, -0.2762058377, 0.3503495753, -0.3517559767, -0.0198392868, 0.0988778472, -0.0198321044, -0.3172486722, 0.2134489119, 0.0843075216, 0.1069885790, -0.3499679565, 0.0172621608, 0.0985274315, 0.0554323792, 0.1148934066, 0.0549394190, -0.3256316185, 0.3376344144, -0.2817167044, 0.2541795671, 0.0268414617, 0.2324669063, -0.2455783784, 0.1935249269, 0.2145981491, 0.2112136781, -0.2156590074, -0.2829781473, 0.3300987184, 0.3113561571, 0.3264960349, 0.0582289994, 0.1019130051, 0.2173345983, 0.2879592478, 0.2343896925, -0.2478350997, 0.3274871409, -0.0566456020, 0.1604240239, -0.3197723627, -0.2133100927, -0.1360211074, 0.2356049120, 0.3413688838, 0.1455393732, 0.3532849848, -0.0814617574, 0.2958364189, 0.1677473485, -0.0268767178, 0.0623139441, -0.1997307986, -0.2405238748, -0.0358990729, -0.2438806295, -0.0334214270, 0.2349555194, -0.2430299371, 0.0684872866, -0.3123852015, -0.1247319877, 0.2807880342, 0.1596897542, -0.1556291729, -0.1991823763, -0.2299897075, 0.2231928408, -0.2827836871, 0.2426159084, 0.2350266874, 0.1445495188, 0.1385463774, -0.3060532212, 0.0994293094, -0.1782524288, -0.2762955129, -0.1580466330, 0.1518516243, 0.2684151232, -0.1426591575, -0.1338749975, 0.1857272685, -0.2408898026, 0.0142179728, 0.0454348028, 0.1615466177, -0.0562961400, -0.0030682087, -0.1716280282, -0.3262225986, -0.2977030873, -0.2761867642, 0.3104097545, 0.0431731343, 0.1607292593, -0.2202814221, -0.3079095185, 0.0120231509, 0.2395457327, -0.3013288081, -0.3102622628, -0.1645497233, -0.1331436634, -0.2354290038, 0.1451896429, 0.2363980711, -0.0919347405, -0.0787511468, -0.3524422348, -0.1219792217, 0.2951319516, 0.2808180153, 0.0521595776, -0.0167918205, -0.1291591823, -0.3424662352, -0.2386297286, 0.1986821592, -0.0417306125, 0.2804038227, -0.1158757657, -0.1685333550, -0.0006595850, -0.1064274460, 0.0177696049, 0.3072566092, 0.1207943857, -0.1897403002, -0.2407633662, 0.0751309693, 0.3414125741, 0.2464052141, 0.2492965758, -0.2320017815, 0.1933802068, 0.1327735186, -0.2997762859, -0.0531712770, 0.3480670154, 0.1225398481, -0.2862635851, 0.3479690254, -0.2709419429, -0.2005229890, 0.2839653790, 0.2844883502, 0.2537063062, 0.0603832006, -0.2051936090 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w12.h b/model/AE_model/hls4ml_prj/firmware/weights/w12.h deleted file mode 100644 index bfdffc9..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w12.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [32, 100] -//Min -0.212805762887 -//Max 0.213140934706 -//Number of zeros 0 - -#ifndef W12_H_ -#define W12_H_ - -#ifndef __SYNTHESIS__ -model_default_t w12[3200]; -#else -model_default_t w12[3200] = {0.0299687982, -0.0200913697, -0.1628506184, -0.1068779975, 0.0424054265, 0.0826480091, 0.0613067746, -0.0700136125, -0.0242939144, 0.1030909717, 0.0650041699, -0.0830966085, 0.0960527658, 0.1947352886, -0.2073853463, 0.0206085145, 0.2071990073, 0.0054719150, -0.0430176705, 0.0793472528, 0.0041321069, -0.0060941279, -0.1071751043, 0.0795918703, -0.1221742183, 0.1073543727, 0.1956848502, -0.0784232020, 0.1237751544, 0.2066734433, 0.1868695319, 0.1677424908, 0.0094357580, -0.0799254626, 0.2026934922, -0.0076247603, -0.0580709279, -0.0180531889, -0.1637006700, -0.1638052166, 0.0779233277, -0.1231834143, 0.0149706006, -0.0556826741, -0.1517318487, 0.0896132588, 0.0733369887, -0.0469554067, -0.2075115591, 0.2020627260, -0.1361604631, -0.0397243351, -0.0796420276, -0.0720068067, 0.1404963732, -0.1644846797, -0.1368613839, 0.1972313821, 0.1479609013, 0.1812329292, -0.0925163031, 0.1341431439, 0.0459197760, 0.2102182209, 0.1156741083, -0.1755264401, -0.1409626305, -0.0525652170, -0.1710569263, 0.1657299995, -0.1696748286, -0.1518070698, 0.1033410728, -0.1277162135, -0.1875155568, -0.0796543807, 0.1871464550, 0.0151327997, -0.1990237534, -0.0622079521, 0.0616436303, -0.0678324550, -0.0198629797, -0.0415979624, -0.1598083824, -0.0991619006, -0.0476939231, 0.1539309919, 0.0488269925, -0.0068289489, 0.0577009320, 0.0779598355, 0.0286590308, 0.1280354857, -0.0991276950, -0.1547031701, -0.0801663995, -0.2033021450, -0.0365294069, -0.0199189931, -0.1896166503, -0.1620380282, -0.1860011518, -0.1301473677, -0.1325807571, -0.1151512563, 0.0179842710, -0.0323763490, -0.0208511800, -0.0292268693, 0.0576676726, 0.1994232237, -0.1680585593, 0.1120285392, 0.2034228742, -0.1939662695, 0.1442087591, 0.0624234378, 0.1286650300, 0.2087322176, 0.0912633240, -0.0376317203, 0.0205214471, -0.0496083796, -0.2016787976, -0.1382226348, 0.0664850473, 0.0934087038, 0.0602796376, -0.0408537984, -0.1239186376, 0.1804018617, -0.1277865171, -0.1906520277, 0.0994181335, 0.0932106972, 0.1030148864, 0.1116523147, 0.0058985800, 0.0763316154, 0.0466108620, -0.0782565325, -0.1931094080, -0.1808894277, 0.0781139433, 0.0563023686, -0.0503799319, -0.0703481436, 0.0061757714, -0.0098461658, -0.2114745528, 0.0153114647, -0.1681676507, -0.1633462161, -0.0197864771, -0.1017761901, 0.0926398337, -0.0084916204, 0.1515615582, -0.0639852583, 0.0894241929, -0.1429507434, -0.2018470466, 0.1891367435, -0.1565079689, -0.1863281429, -0.0731568635, 0.1096500158, -0.1922487319, -0.0225030929, -0.0464011431, 0.0343073308, -0.0230456144, -0.0067266226, -0.1473098993, 0.0474331081, 0.1361288130, 0.1835507452, -0.0805701017, 0.1962219775, -0.0072854012, 0.1076261401, 0.1758356094, 0.2032818198, 0.1188454628, -0.0964757353, 0.0214861184, -0.0365467817, 0.1914212108, -0.1486441642, -0.0549377054, -0.1208507791, -0.0835755914, -0.1265096366, -0.2034690231, 0.0648523271, -0.1897552162, -0.0336513519, -0.1699216664, 0.0531323850, -0.1490594000, -0.0797703713, 0.2046851516, -0.1592926085, -0.1386430115, 0.0487061739, 0.0597852468, -0.1644745171, 0.1618199646, 0.0082582086, 0.1800731719, -0.0387442112, -0.0123487860, 0.1716650128, 0.1768315434, 0.0235440135, 0.1460557878, 0.1448304057, 0.1400508285, -0.2036625296, -0.0995768830, 0.1586339772, -0.1803688109, -0.1290575564, 0.1552039683, -0.0657280087, -0.1672912240, 0.0555873215, -0.1085671112, 0.0801717937, 0.0385826826, 0.0135929286, 0.0630749464, 0.0029980689, -0.1597732604, 0.0757490993, -0.0452418327, 0.0770318210, 0.0499458313, -0.0152857453, 0.0045678318, -0.0506545305, 0.0333602875, 0.0823979974, -0.1917371154, -0.1759482026, 0.0670691431, -0.0253701657, 0.2032220960, -0.1656939983, -0.0252533555, -0.2011405975, -0.1797123849, 0.0893137455, -0.1314969361, -0.1712016910, -0.1751994491, -0.1736104190, -0.1309947222, -0.1455578506, -0.0290444344, 0.1079195142, -0.0198743641, -0.1168765575, -0.1956928372, 0.0749217570, 0.1197899282, 0.1492062509, 0.0845648646, 0.1910144687, 0.0714731812, 0.0896423161, 0.0886339843, 0.0424313843, -0.1047299802, 0.1140542328, -0.0675532520, -0.0491651744, 0.1374236345, 0.0591898561, 0.0204799175, -0.2117312998, -0.0115324855, -0.1409758925, -0.1222114265, -0.0760993063, -0.1121596992, 0.0451081991, 0.1246991456, 0.0530746877, -0.1226361692, -0.1766454428, -0.1873668283, 0.0489591658, 0.1323884130, -0.0933586806, 0.0075565875, -0.0572030842, -0.1902633309, -0.1812438220, -0.0443895608, 0.0993377864, 0.1648918986, 0.0184242576, 0.1783342957, -0.1467216909, 0.1525241435, 0.0741368234, 0.1681051254, 0.2015506625, -0.1783226132, 0.0273520201, -0.1540651917, 0.1322736740, 0.1993274987, 0.0856180787, 0.2101798356, 0.1924318671, -0.0558870733, 0.0282167494, -0.1529767513, 0.2130309939, 0.0657108724, 0.0723687112, 0.0556191802, -0.0014367402, 0.1229352653, -0.2076495588, 0.1529274285, -0.0508707613, -0.1626865268, -0.0902138129, -0.1416822970, 0.1324886978, 0.1586819291, 0.0451759696, 0.0123371929, 0.0383366346, 0.1934813261, 0.1374279857, 0.1389309764, -0.1145577505, 0.1496672928, 0.0143344998, -0.1715855300, 0.0703697503, 0.0756785870, 0.0705799758, 0.0685043037, -0.0987578928, -0.1857370734, 0.0366628915, 0.0343631357, 0.1183466315, 0.0785025656, -0.1750455797, 0.1534826159, 0.1441718042, 0.0897021592, 0.0018040389, -0.0981088355, -0.1238731444, 0.1437948942, -0.1384842694, 0.0986107290, 0.0601267219, 0.0760452747, -0.0176557451, -0.2066420913, 0.1434316337, 0.1618829966, 0.1882940829, 0.0081178099, 0.0319456607, -0.0112308115, -0.0579738915, 0.1688969731, -0.0522499532, 0.0275250971, 0.1130464971, -0.1198113412, -0.1739815474, -0.2051894963, -0.0725248307, 0.0653609931, 0.1268644333, 0.0542542338, -0.1434755027, -0.1683304012, -0.0638830960, 0.1737835407, 0.0660760403, -0.0277434587, -0.1337418258, -0.0600245148, 0.1939641833, -0.0056484491, -0.0793008059, -0.1560899913, 0.1696815491, -0.0796096027, 0.1000609398, 0.1038047075, -0.1127653494, 0.0950272083, -0.1602330208, -0.1877627373, -0.1061679423, -0.1238565221, 0.1439324915, 0.1299566925, 0.0472214520, -0.0069753826, -0.1149794459, -0.2021604776, 0.1122357845, -0.1002883688, 0.0194462240, -0.0018406361, -0.0953991339, 0.0182069540, 0.0094234645, -0.0216829777, -0.0452967286, -0.0725801289, 0.0355390161, -0.1340863109, 0.1887212694, -0.1611262858, 0.1702066660, 0.0964568853, -0.1035552248, -0.0042550117, -0.0943432227, 0.1989069283, -0.0933973119, -0.0053331405, 0.0471409857, -0.0212728232, 0.2078837454, 0.2041386068, 0.0111851543, -0.1873343438, 0.1273722947, 0.2028470039, 0.0488651693, 0.1237006783, -0.0178181976, 0.0472271442, -0.0325583816, 0.1946828663, 0.1655352712, 0.2027935684, 0.1411809027, 0.1962138116, 0.1080618501, -0.0607369095, -0.0708165020, 0.1253030300, -0.0159034431, 0.1700783670, -0.0541625768, -0.0760538131, -0.0406669974, -0.0891414285, 0.1450912356, 0.0859740376, 0.2055131793, 0.1083478332, 0.0022055060, -0.0290104300, -0.0267654210, -0.0207869411, -0.1194224805, 0.0018991977, -0.0272793770, -0.1055083573, 0.0597414970, -0.1958667785, 0.0869557858, 0.0951965749, -0.1256363094, -0.0545191616, -0.1926113069, -0.0835183561, 0.0878288150, -0.1846973300, 0.0389287770, 0.0536273718, -0.1922698766, -0.1813737452, -0.0055727065, 0.0913288891, -0.0415549576, 0.0197254270, 0.1108522117, 0.0002185702, 0.0923810899, 0.0573065877, 0.0757805109, 0.1220797300, -0.0833618939, 0.1317946017, -0.0430670381, -0.0967186093, -0.0560624450, 0.0935617089, 0.0121237487, -0.0303220153, 0.0375040770, -0.0382418483, 0.0393078625, 0.0130563527, -0.0055943131, -0.1761269718, -0.0499690771, -0.0106518418, -0.0307799578, 0.0621480346, 0.0695970654, 0.1028584838, 0.0719177127, 0.0005092323, 0.1469067037, 0.1609019041, 0.1450909674, 0.0792758465, -0.0519316047, -0.2121607214, 0.0241434127, -0.0808357447, -0.2041620016, -0.1480538100, 0.1651775241, -0.2083772123, 0.1574057937, -0.1065901965, -0.0385201424, 0.1561101079, -0.1631736457, 0.0538884401, -0.1054305360, -0.2048415542, 0.0021589994, -0.0986903384, -0.0747502595, 0.1790751219, -0.1251314580, 0.1173853278, -0.1656351984, 0.0950775146, -0.1212994158, -0.0788257867, -0.1449895203, -0.1379195750, -0.1993272603, 0.1146961153, -0.0986853093, 0.0152729899, 0.0105710775, 0.1330817044, 0.1422324777, 0.0992231071, 0.1181887984, -0.1909636706, 0.0078451037, -0.1997201741, -0.0151363015, 0.1178297997, -0.1558717191, -0.0950169861, -0.1872103661, 0.2013084590, 0.0404230654, -0.1430938244, -0.0383232236, -0.1629514694, 0.1915737987, 0.0239459276, -0.1554045379, -0.0571268350, -0.0343904793, -0.0432691872, -0.1243529916, 0.0900253952, 0.0138496757, 0.2025043070, 0.0890162289, 0.2063539922, -0.0377029926, 0.0664572418, -0.1869729310, -0.0886757150, -0.1995316446, 0.1380406618, -0.0402527303, -0.0892176777, 0.1503989995, 0.0581840277, -0.1900311857, -0.0375838876, 0.1521078944, 0.0178539306, -0.0032742321, -0.1492450833, -0.1072543487, -0.0301053226, -0.0052204430, 0.1500692666, 0.1414586008, 0.1079036295, 0.0571198165, 0.0485185683, 0.1213852763, -0.1186918393, 0.1275147796, -0.0365253836, -0.1145128161, 0.0286160856, 0.1659997106, -0.2049054056, -0.0777986497, -0.0125737637, 0.0773003101, -0.0892232209, 0.2025945783, 0.0550533831, 0.0385752916, 0.1083570719, 0.1414549351, -0.0111115575, 0.0712562799, -0.1094422191, 0.1511150599, 0.0087268203, 0.0202568769, -0.0386397541, 0.1489885449, -0.1213671267, -0.2128057629, 0.1057298183, 0.0510607064, -0.1561504751, -0.1614055485, 0.1519888341, -0.0476292223, 0.2093452513, 0.0253442973, 0.1837027073, 0.0339175016, -0.0858129710, -0.0682265610, -0.1138197854, -0.1712946147, 0.0106116384, -0.0390239358, -0.1540293545, 0.1809662879, 0.1934553981, -0.0429925621, 0.0340826064, -0.1216562018, 0.1013063490, 0.0999135971, -0.0800538063, 0.0211647600, 0.1619406939, -0.0261410177, -0.0756101608, -0.0725631565, -0.0672484189, -0.1443044245, -0.2104350030, 0.1078053117, -0.1717941314, 0.0366245061, -0.1369144022, 0.0730428398, -0.0014251471, 0.0019932836, -0.0347588062, -0.1416097581, -0.0373671502, 0.1879232824, -0.0678206235, -0.0094726086, -0.1668108106, -0.2068654895, -0.0293164849, 0.1029573083, 0.0726135373, -0.1451911032, -0.0059137344, 0.2113559544, -0.1072068214, 0.2105501294, -0.0070212930, 0.2129808664, -0.1996234953, 0.0191973448, -0.0369255245, -0.0173931569, 0.0040988028, -0.1652255356, 0.0166354179, 0.0675693154, -0.1846835017, -0.0812719762, 0.1431894898, -0.0498331934, -0.0058604628, 0.0493593514, -0.1396758854, -0.1841018498, 0.1082337499, 0.1404029727, -0.0944251642, -0.1443277895, 0.1943573952, -0.0410360843, -0.0552903116, 0.1141994894, -0.2049532384, 0.1282199025, 0.1656420529, 0.1564200521, -0.1017887443, 0.1943162382, -0.1167149171, 0.1902273893, -0.0146615952, 0.0996394455, 0.1081024110, -0.0095883608, 0.0467160344, -0.1426015794, 0.1132473648, -0.0834285319, -0.2006640136, -0.0626687407, 0.1497789025, 0.0997542739, 0.0486185551, -0.1117992550, 0.1593234539, -0.0817669630, -0.1094438434, -0.2040923089, -0.0345581174, -0.1097800955, 0.1097026765, -0.1717210412, -0.1104205102, -0.2118057609, -0.0631954968, 0.1601560116, 0.0353156626, -0.0384458303, 0.0104279816, -0.0868183523, 0.0248557031, -0.0272359103, 0.1344070435, 0.1277020872, -0.0776934773, -0.1456069648, 0.1698482037, -0.0428069234, -0.0244031101, -0.0958980396, -0.1205567792, -0.0047460347, -0.0705674291, 0.1576403379, 0.2007039785, 0.0109769553, 0.1511013210, -0.1129482910, 0.1351296306, -0.2037522495, 0.0605449677, 0.0585310459, -0.1157551780, 0.0295844674, -0.1049444377, 0.1212015152, 0.1379203498, -0.0699597448, 0.0286668092, -0.0065829754, -0.1788249761, -0.1312187314, 0.1286323965, 0.1392367184, 0.1908683181, 0.0242387205, 0.1691608727, -0.2020194232, -0.0678330660, -0.0243738294, -0.0575586557, -0.0077267736, -0.1400625110, 0.1848634481, 0.1182062626, 0.0595957637, 0.1738096774, 0.1422152519, -0.2081463337, 0.0900264084, 0.1681007445, -0.1872164607, 0.0730664432, 0.1905981898, 0.0831505358, -0.0544702560, 0.1223368645, 0.1236465275, 0.1874395013, 0.0316298008, 0.1114262044, 0.0823487937, 0.0209904611, -0.1241559684, -0.1212982461, -0.1685856283, 0.1621521115, -0.0055004209, 0.0879061222, -0.1197008863, 0.0481621325, 0.1770572662, 0.2034153938, 0.0980803668, 0.1807042062, -0.0962149203, 0.0693045855, 0.1404873729, -0.0112236440, -0.1166152358, 0.0854465663, 0.0849801004, 0.1941885948, 0.1874067187, -0.1194612682, -0.0316866338, 0.1586165428, 0.1986514628, -0.0514322966, 0.0083613992, 0.0338022709, -0.0840201527, 0.1076180935, -0.1840358078, -0.0786230713, 0.1650006175, 0.1759569347, -0.0984335914, 0.0937895179, -0.1591776758, -0.0548721850, 0.2099168897, -0.0761839002, -0.1439442784, -0.1180057228, -0.0115567297, 0.2119663954, -0.2084765881, -0.1429431587, 0.1304834485, 0.0253197849, -0.0495870262, -0.1593472958, 0.1906189919, -0.0755666047, 0.0204891115, -0.2027017176, 0.0845215023, -0.0375019461, -0.0741307288, -0.1682538986, -0.0986525714, -0.1323923767, 0.0248608440, 0.1058465838, 0.1753382683, -0.1236304268, 0.1611528993, -0.0788172930, 0.2003071308, 0.0172708482, 0.1628030837, 0.0418015420, -0.0545591116, -0.0956913158, -0.1495652795, -0.1087132543, -0.1375667155, 0.1122941375, -0.1753409654, -0.1203577742, -0.1041368321, 0.1671169102, -0.0055812448, 0.1678700149, 0.0990319848, -0.1881180555, 0.1386297345, -0.0494644642, -0.0536248833, -0.1219948381, 0.0529752672, -0.0706597269, 0.0397333801, -0.1728109568, -0.0324662775, -0.1066334024, 0.0403463542, -0.0274363458, 0.0952627063, -0.1018335298, 0.0583408773, 0.1738654077, 0.1537837386, 0.0972969532, -0.1946167499, 0.0721558928, -0.0901098624, -0.0134937465, 0.2068599164, -0.1080145761, 0.0695914626, 0.1576732397, 0.1439830065, -0.1283816546, -0.0403546393, 0.1978405118, 0.0215785801, 0.1189253926, -0.1251751781, -0.1324729919, -0.0573372245, 0.1317686737, 0.1840246916, -0.0632864386, -0.1593850106, -0.2103401572, -0.0452760458, 0.0562445223, -0.0672827810, -0.1317190230, -0.1057995185, 0.0628919005, 0.1449728310, 0.1558126509, -0.1442781389, 0.1884695888, 0.1673473418, -0.0872376114, 0.1140232086, -0.0252642781, 0.0438523591, 0.1734786332, -0.0142899752, 0.0308145732, -0.1282856315, -0.1500093937, -0.0310410261, -0.0346261412, 0.0138389915, -0.0564204454, 0.1973220706, -0.1628828943, 0.2086023390, -0.0911404118, 0.1388567388, -0.0801965445, 0.1897435784, -0.0078805834, 0.0966969132, -0.1342030764, -0.1829697788, 0.0274105668, 0.0954551399, 0.0424244702, 0.0432503819, -0.1348703206, 0.0819534659, 0.1172466576, -0.1045202017, -0.0274430066, -0.2078236043, 0.1791496873, -0.0249381959, -0.0028370321, -0.1151518151, -0.0351021737, 0.1781578660, 0.1670326293, 0.1231856048, 0.0522374511, -0.0416953564, -0.0919703320, 0.2049568295, 0.0597164333, -0.1264267862, 0.0250963420, -0.1367215514, 0.2062895894, -0.2021236271, -0.0789147466, -0.1009974107, -0.1868142933, 0.1095725596, 0.0458966494, 0.1690641642, -0.0414194912, 0.0501979589, -0.1225041598, -0.0142165720, 0.1769432127, 0.0690946877, -0.0368168950, -0.2125138342, 0.1564998329, 0.1774396300, -0.0208842754, -0.1699668020, 0.1192377508, 0.2057524025, -0.0954460502, 0.0930086076, 0.1147645712, -0.1254046261, 0.1324979365, -0.1101972088, -0.0763699412, 0.0361105055, 0.0514391661, 0.0420373082, -0.0369996876, 0.0854761600, 0.1843793690, -0.1736085415, -0.0634968281, 0.1430990696, 0.1729621291, 0.1585301757, -0.1438342333, 0.0730384588, -0.1971729845, 0.0652405918, 0.0152683109, -0.1353506446, 0.1925430894, 0.0246178210, 0.1677184999, -0.0048195422, -0.1687426418, -0.0789889991, 0.0222119838, 0.1184870303, -0.0578724742, 0.0195703506, 0.1599646807, -0.0953619257, -0.1090037525, 0.0946376324, -0.0791863799, -0.0674538761, 0.1205617189, -0.0457265675, -0.0772978514, 0.0474117100, 0.1960088611, 0.0076489449, -0.1340975463, 0.0089059472, -0.0732634515, -0.0593659431, 0.1910074353, -0.0600316823, 0.1865903735, 0.2039996982, 0.0955586433, 0.0850807428, 0.0748503804, 0.1393448412, 0.1457204521, -0.1769429147, -0.1073040143, -0.1568056345, -0.1769776195, 0.0820996165, -0.0717875659, 0.0552145839, 0.0963548124, -0.1853030771, -0.0829025805, 0.1825232804, -0.0630365610, 0.1861030757, 0.0656674206, -0.0497936457, 0.1127585769, 0.1411151290, -0.1029667556, 0.2078949213, 0.0462093055, 0.0898126066, 0.0131751001, 0.1630607545, 0.0629414618, 0.2107377648, 0.0717314482, -0.0816785246, 0.0140785575, 0.0746624172, 0.1485654712, 0.0411568582, -0.0456013680, 0.1087857783, 0.0439174473, -0.0011476576, -0.1062764674, 0.0663406253, 0.2129457891, 0.0096564740, -0.1795127243, 0.1119864583, -0.0606164932, 0.1801105440, 0.0738519132, -0.0362794101, 0.0169439614, 0.1146946251, -0.0022736192, -0.2109142840, 0.0731431842, -0.2111463845, -0.0210354924, 0.1228208840, 0.1741955280, -0.1463062465, 0.0535667241, 0.0714875758, 0.1088028550, 0.1164041460, 0.2026323378, -0.0252092779, 0.0014938712, -0.1912081689, -0.1331903189, 0.1476591229, -0.1678193510, -0.0322937071, 0.1266770959, -0.0697968751, -0.0139189065, -0.1026626825, -0.0157848597, 0.0318510234, 0.1830307841, -0.0639783591, 0.0032776296, 0.1112110913, 0.1398272812, 0.2115580142, 0.0822045207, 0.1698623598, 0.1983507574, 0.1014650464, 0.0911060572, -0.1313718259, 0.1438991427, -0.0996037722, 0.0321595073, 0.0923565328, -0.0361539572, -0.2123867571, 0.1487106979, -0.0159201771, 0.1643887162, 0.0597353876, -0.1827633679, 0.1444546580, 0.0984890461, 0.0160970092, 0.0142266899, 0.0770986378, -0.0505784303, -0.0323747844, -0.1830642819, 0.0064463913, 0.0076768547, -0.1202597693, -0.2009681910, -0.1707529575, 0.1267985106, -0.0900287405, -0.0438698083, -0.1021372974, 0.0055644661, -0.0194720328, 0.1149333417, -0.0809840262, -0.1144135445, 0.2040384710, -0.0188029557, 0.1048910618, 0.1795919538, -0.1614289731, 0.0341091901, -0.0088966489, 0.0277018845, 0.1153512597, 0.0880717933, -0.1324718297, 0.1717734039, -0.2016137391, -0.1045009866, 0.1157133877, -0.0166334361, -0.0154671073, 0.1994017363, -0.1078871936, 0.1074694693, 0.1580016911, 0.1991653144, 0.1872931123, -0.1518543363, 0.0200148076, -0.1169207320, 0.0856198668, 0.0655365288, 0.1064652503, 0.1896738410, 0.0871496797, 0.2046217620, 0.1393769979, 0.0166612864, -0.0847424716, -0.1429281235, 0.0346267968, 0.1239484847, 0.0759538710, 0.0976523757, 0.0261277556, 0.0197988302, -0.0161558241, 0.0142623633, -0.1662683934, 0.1792075336, 0.0535419285, -0.1046166271, 0.0217982680, 0.1907408237, -0.0097986907, -0.0788309723, -0.1983426064, 0.1801694930, 0.1988052130, 0.1525231898, -0.0462639928, -0.1794506609, -0.1983816922, -0.0863542110, 0.1962837577, 0.0113638788, -0.1423419416, 0.2009785175, 0.0230496824, -0.0825804174, 0.0670066476, 0.0893870592, 0.1693057418, -0.0931251049, 0.0395222306, -0.0908814818, -0.0015156865, -0.1482891142, -0.1197384968, 0.0808253288, 0.1706576049, 0.1219940186, -0.0090284497, -0.1708687544, -0.0672705173, 0.1744294167, -0.0471183211, 0.1627449393, 0.0505898595, 0.1289803386, 0.1933867931, -0.0364499092, 0.2092516422, -0.0879659653, -0.1325432360, -0.1883024126, 0.1935233176, 0.0722268522, -0.0351103544, -0.1282860935, -0.1669809967, 0.0634535849, 0.1463640928, 0.1115628481, 0.1915774643, -0.1330951154, -0.0498410761, 0.1824287474, -0.1198925152, -0.1558498144, 0.0115216672, -0.0575571805, 0.1512074769, -0.0792186111, -0.1005453169, 0.1918959022, 0.1577787995, -0.0474315286, 0.1767385006, 0.1532249153, 0.0381480753, -0.0994352177, -0.1345816553, -0.0714825839, 0.1817150712, -0.0423345566, 0.0728407800, 0.0606569946, 0.1074360311, -0.1082013845, -0.1286506951, -0.1654386818, 0.0755141973, 0.1346943080, 0.0741473436, 0.0272509605, -0.1022430733, -0.1535176337, -0.1437671334, 0.0033517927, 0.0385562479, -0.2093280107, -0.1801258922, 0.1942785680, 0.1442832649, 0.0647675097, 0.0466073155, -0.0312325507, 0.1904779971, -0.0702055097, 0.1841617227, 0.0860672593, -0.0434789211, -0.1418571472, -0.0536649376, 0.0984870791, -0.1137775481, 0.0694874823, 0.0945133567, -0.1912234277, 0.1735962331, -0.0742257386, 0.1887037754, -0.1645788699, 0.0214261860, 0.1316542625, -0.1871816963, 0.0810263753, 0.1041027904, -0.1497622430, -0.0212554485, -0.1823785156, 0.1808028221, 0.1183961034, 0.1672869921, 0.1207077503, 0.0926214755, 0.1032781005, 0.0705330670, -0.0409869701, -0.1389550120, 0.0041922331, -0.0760333836, -0.0342211723, -0.0022919774, 0.0694222152, -0.1467096359, 0.0167407840, 0.2002843916, -0.2026804835, 0.0219483674, 0.1510784626, -0.2011389732, 0.1555231214, -0.0785504282, -0.0242179781, 0.0736868083, 0.0837689936, -0.2070930153, 0.1436602771, -0.1341157854, -0.0420701355, -0.1833635718, 0.0336981118, -0.1235698834, 0.0389548540, 0.0881867111, 0.0741657019, -0.1485468149, -0.1753440648, 0.0552891493, 0.1398189962, 0.0925252438, -0.0714594126, 0.1528547406, 0.0452864170, 0.1368271112, -0.1442251801, -0.1871099770, 0.1367825866, 0.0078157187, 0.0879496336, -0.1634112298, -0.1578331888, -0.1039924771, 0.1737509668, -0.2009857148, 0.0084375441, -0.0871703029, 0.1638271213, -0.1012258977, 0.0226652473, 0.2094560564, -0.2052043378, -0.1554896235, 0.1281714737, 0.1526623070, 0.0711450577, -0.1538139880, 0.1103184819, -0.1276670098, -0.1715557873, -0.0104382038, -0.1191718876, 0.1682462394, 0.1613282859, 0.0988994539, 0.0623968840, 0.0341099948, 0.1983372867, -0.1309966445, 0.1504108608, 0.0166955441, 0.1539048254, 0.0171548128, -0.1117881685, 0.1348723173, -0.0929081589, 0.0306994468, -0.0673389435, 0.1843204200, -0.0494693965, 0.0026714802, 0.1970034242, 0.1465358436, -0.2089259773, -0.0306969434, -0.0623424053, 0.1178109348, -0.1690531224, -0.1106899157, -0.0879889876, -0.0418089181, 0.0957140326, 0.1265924871, -0.0413431525, -0.1948350221, 0.0549199581, -0.1067268252, 0.1657143831, -0.0590002686, -0.1327666938, 0.1300134361, -0.0232419223, 0.2081829906, -0.0133474618, -0.1192633808, 0.0818081498, 0.0748744309, 0.1030098200, 0.1931266487, -0.1345575154, 0.1282161474, 0.0507016480, -0.0075940490, 0.1418971121, 0.2076115310, 0.0331827849, -0.0025079995, -0.0684792399, -0.2117804438, 0.0889830291, -0.0081021041, 0.0968770087, -0.0448308140, -0.2018771470, 0.1256079674, -0.1889444590, -0.1807408929, -0.1891945004, 0.1386094987, 0.1040057838, 0.2109294832, -0.1347030997, -0.0752518028, -0.1905307919, -0.0660125017, -0.1359195858, 0.0700816810, -0.1311333477, 0.1863650084, 0.0182687193, -0.1991056353, -0.1986645758, 0.0332740843, 0.1223597527, 0.1440291107, -0.1991315633, -0.1418480575, -0.1046753898, 0.1215175390, -0.1528828144, -0.0192871094, -0.0392865241, 0.1554636955, 0.1521648169, -0.0530413985, 0.1745767593, 0.1329261065, 0.1173268855, -0.0834161788, 0.1669941545, -0.1135928258, -0.0104432255, 0.2093745172, -0.1487203538, -0.0243670642, 0.0781385601, -0.0863867402, -0.1772288829, 0.0374935269, 0.0326699018, -0.1416948438, 0.1712468863, -0.2092596889, -0.0162612945, 0.1995322108, -0.0407852232, 0.1391594112, 0.1703530252, -0.1247310713, 0.0101923794, -0.1614331901, -0.1967547536, 0.1085800827, 0.0099474788, -0.1713281572, -0.0349265933, -0.1580587327, -0.0134223402, -0.1268889010, -0.0272006392, 0.0517058074, 0.0707002580, -0.0472020358, -0.0683047771, 0.0666269660, 0.0012337267, 0.1978390217, 0.1685774326, 0.0937682688, 0.1021435857, -0.1766422987, 0.1285056174, 0.0278677493, 0.2131409347, -0.0197218806, -0.0183848143, 0.1801211238, -0.2011249512, -0.1342885196, -0.1063225642, -0.1096163169, -0.0815093517, 0.1041289568, 0.1356954575, 0.0624127984, -0.1830896437, -0.1202615499, 0.0235555023, 0.1180990338, 0.0151791573, -0.1735906005, -0.0099890083, 0.1042123735, -0.1211249679, -0.0183042437, 0.0646506846, -0.1295357645, -0.2120593637, -0.0708652437, 0.1243365109, -0.0544359982, -0.0681137592, -0.0318974257, -0.0399938375, -0.2073388398, 0.1302348375, 0.1618840694, 0.0332589298, 0.1849151850, 0.1767701805, -0.1539921910, 0.0606725514, -0.2084412575, -0.1359802783, -0.1610464752, -0.0460764319, -0.0974373594, -0.0677113235, 0.0968209207, 0.1616028249, 0.0057454854, 0.1070614457, -0.1252095997, 0.1165149510, 0.1797955036, 0.0990042090, -0.0438649803, -0.2108273208, -0.1882810742, 0.0832380652, 0.1381633580, -0.1082440838, -0.2057079226, 0.1687243879, 0.0165371001, -0.0090067983, 0.0030519515, -0.1095453575, 0.0558823049, 0.0032670647, 0.0653376877, -0.0037532598, 0.0686316192, -0.0914803669, 0.1204346418, 0.0681389868, 0.0972673297, 0.1868832707, -0.1156612411, 0.0290973932, 0.1910237670, 0.0628211200, 0.0652168095, -0.1818069816, 0.0808030069, -0.2054787725, 0.1728060246, 0.1067647040, -0.0791605115, -0.1227906942, 0.2060981393, 0.0920174122, 0.0442633331, -0.0913680345, 0.0774338245, -0.1595715582, 0.0464090705, 0.0904039145, 0.0160845071, -0.0072901845, 0.1936618984, 0.1889795959, -0.0602845103, 0.1024118364, -0.0906693637, 0.0332486182, 0.1135805845, -0.0269023627, 0.1737165153, 0.0655167997, 0.2131136060, -0.0408491194, 0.1877136528, 0.1271311045, 0.0442544520, 0.1611259580, 0.1131458282, 0.0869052708, 0.0794386566, -0.1972284913, -0.1239228025, 0.0040045232, -0.0112203807, 0.0104427189, 0.0851106346, 0.1309471428, -0.1934918612, -0.0773466080, 0.1444209814, 0.0258134604, 0.0405142605, -0.2011807114, -0.0524137318, -0.0633147508, 0.0562126935, 0.0138960779, 0.0027410090, -0.0553597510, 0.1429971457, -0.0844705701, -0.1139667407, 0.1930039823, 0.1534200013, 0.0817907155, -0.0481107384, 0.1761950254, -0.0427481681, -0.0800165981, 0.1292200089, -0.0713572800, -0.1633257270, -0.1784992516, 0.2117676437, 0.0497537553, -0.1343480349, 0.1995138526, 0.1230620742, 0.1978739500, 0.0688371956, -0.1255532205, 0.0393286645, 0.1028071940, -0.0379785895, 0.1169190407, -0.1697795391, 0.0002817065, -0.0651353747, -0.0321286619, -0.0973549113, -0.0383515954, -0.0690279007, 0.0932333767, -0.0843957514, 0.1068355143, -0.1142790467, 0.1139979362, -0.2103314102, -0.1968776584, -0.0599546731, 0.0578142405, -0.1474400312, -0.0340850949, -0.1431041956, -0.1225979477, 0.0317832083, 0.2002293169, 0.1547575593, -0.0025028139, 0.0855506361, 0.2077602744, 0.1482928097, 0.1962883770, -0.0263144523, 0.0999545455, -0.1755501330, 0.0907763541, 0.2108449042, 0.1564360857, -0.1490325630, -0.2122148573, 0.1328415275, -0.0560300648, 0.0927752256, -0.1412148029, 0.1037666798, -0.0936286896, 0.1331335306, 0.1564979255, 0.0636173487, 0.1403563321, -0.1232199147, 0.2115045786, 0.1556344926, 0.1365908086, -0.1735243648, 0.0514004230, 0.0813339949, -0.0397134125, 0.0008128434, 0.1764344871, 0.0534341335, -0.0965536609, -0.0563279837, -0.0701866448, 0.1678231657, -0.1305635720, -0.1049790010, 0.1803027987, -0.1480420679, -0.0221689790, 0.0227394551, -0.0514955819, 0.0391811430, -0.0903801844, 0.0161486119, -0.1661705375, 0.0148486495, -0.1189615428, -0.2023089528, 0.1500414014, 0.1575564146, 0.2006876469, -0.1427052170, 0.1038216352, 0.1328781247, -0.0355130285, -0.0493305773, 0.1476909816, -0.1162002012, 0.0018752515, 0.1564856172, 0.1089758575, 0.1843735874, -0.1625342369, 0.2025069296, 0.0816542208, -0.2002037317, 0.1977411807, 0.1830754280, 0.1948248446, 0.0473127961, 0.0856705010, -0.1472903192, 0.0240328014, -0.1473911256, 0.1059477031, -0.1635962129, 0.0690924525, 0.1293298900, 0.0291915834, 0.1522969902, 0.1869597137, 0.0537905991, -0.1628608406, -0.0562254041, -0.0952598080, -0.0580354929, 0.0834422708, -0.0904143378, -0.0870322436, 0.0731475651, 0.1328050792, 0.0595055819, -0.1284235865, 0.0775947571, 0.1282472014, -0.0781846493, -0.1768473983, -0.1059038192, 0.0783807635, 0.0185207874, 0.1210107505, -0.0355900973, -0.1083190590, 0.0551561117, -0.0146243870, -0.1358241141, 0.0594488978, -0.1208960190, 0.1518229246, -0.1121866331, -0.1449517012, -0.1512638927, -0.2059335560, -0.0745748878, 0.1951863468, 0.1911711693, -0.1959552318, 0.0085752457, 0.1613205969, -0.1183672324, -0.1731554866, -0.0484661460, 0.0297663808, 0.0933525264, -0.0036646575, -0.1410296857, 0.2080911398, -0.0710754842, -0.1831357479, -0.1716746837, 0.1974130571, -0.0352466851, 0.1570383608, -0.1903720498, -0.1753707528, -0.1628082246, -0.1246879175, -0.0627532750, 0.1821535826, -0.1860825270, 0.1057403088, 0.1573023498, -0.1415687501, -0.1320505738, 0.1899049580, -0.0032659471, 0.1987372637, -0.0291750133, -0.0125812888, 0.1250814497, 0.1543976665, 0.1588623226, -0.0772247612, 0.1269832850, 0.0809114277, -0.2079120576, -0.2060230672, 0.1824369133, -0.0100146681, 0.2086891532, 0.1752610207, 0.1876649559, -0.0246680826, -0.0451197475, 0.0043716729, -0.1415401697, -0.1758477986, -0.0596223921, 0.1316759586, -0.0559997708, -0.0688156337, 0.0573354363, 0.0119467080, -0.1301584542, 0.1751771867, 0.1697615385, 0.1741175056, 0.1899056733, -0.1500841081, -0.1966127753, -0.1269682944, 0.0956632495, -0.0649770349, 0.0084272772, 0.2049444020, -0.1740206331, 0.1296412945, 0.1302121878, 0.0303550661, 0.1835718751, -0.0123747587, -0.0687476248, -0.0049850494, 0.1179048121, 0.1232193112, 0.1716808677, 0.1933630109, 0.0383467674, 0.1538934708, 0.0399881005, -0.0753969848, 0.1629869342, 0.1576235592, -0.2061833888, -0.1943323910, -0.1071545705, -0.1535230726, -0.1996119171, 0.1132124662, 0.2103752792, -0.1986448467, -0.1092130244, -0.0629687458, 0.0168035626, -0.0435729027, 0.0788228810, 0.1089095175, 0.0574910045, -0.0307945460, -0.0557697564, -0.1573819667, 0.0387057960, -0.1841708720, 0.0259755105, 0.1528935432, 0.0440687537, -0.1419970393, -0.0956466347, -0.1713100672, -0.1513942778, -0.1747036427, -0.0862678587, -0.1714905649, -0.0699100792, 0.1882464886, 0.1420514286, -0.0752908885, 0.1676419377, 0.1588957012, -0.1760142744, -0.1110270768, 0.1897342205, -0.2016245723, 0.1889849305, 0.0963345766, 0.1372450590, -0.0214768201, -0.0735859275, 0.0885555148, 0.1388621330, -0.0230655819, 0.1722593904, 0.2026747465, -0.1153706908, 0.0849388838, 0.1582046151, -0.1976340264, 0.0836519301, 0.1209901571, -0.1021070480, -0.1253621280, 0.0024885833, -0.1998213828, 0.1640697122, -0.0472567230, -0.2121480554, -0.0621883422, 0.0732249320, -0.1825171858, -0.1615246385, -0.0747048706, -0.0765175521, 0.1380745769, 0.1035941541, 0.0566515625, -0.1656499356, -0.0494195819, 0.0154630542, -0.0155421346, 0.0999943018, -0.0983497724, -0.0023596287, -0.0089180022, 0.0952349901, 0.2121636569, 0.1911831498, -0.1771416515, 0.1345708370, 0.0569574237, 0.0976062715, 0.0373338163, 0.1374650598, 0.1132061481, 0.0398771465, -0.1904560328, -0.0199830383, 0.1737166047, 0.0579673350, -0.1397959590, 0.0845487416, 0.0635729134, -0.1875258237, 0.0082111955, -0.0156118274, -0.0246786624, 0.0612721145, -0.1228818372, -0.0824263990, 0.0642475486, -0.0011276305, -0.1635920405, 0.0701577365, -0.1154046953, 0.0584930182, 0.2104386091, 0.1489616632, -0.1016275138, -0.1633670628, 0.0255742520, 0.1254868209, -0.0513779521, -0.1428818554, -0.1509671360, 0.0329130292, -0.1813355684, 0.0400531590, 0.0307151526, 0.1701872051, 0.1005813181, 0.1923497319, -0.0850675851, 0.1909916401, 0.1995913386, -0.2029951215, 0.1294534206, 0.1793923080, 0.1737214327, -0.1812362373, -0.0247590691, -0.1586031765, -0.1100956500, -0.1073428467, -0.1396663934, 0.1241170764, 0.1778326631, -0.1573841572, -0.2054813653, -0.0386196226, -0.0788801759, -0.1261099130, 0.0681798458, -0.1681665778, -0.1431814581, -0.0348086655, 0.1602859497, -0.0285475105, -0.0923261940, -0.0164624304, -0.0991970226, -0.0123434514, 0.0399152040, -0.1202259138, -0.0785073340, 0.1368511617, -0.1663074791, 0.1028437316, 0.0936442316, 0.1018613279, -0.0085767657, -0.1116045192, 0.1987394094, 0.0133036524, -0.0635730773, 0.0212164521, 0.1224555671, -0.2004901171, 0.0609331131, -0.0939833373, -0.1074724123, -0.0456439555, -0.1393577456, 0.2108364701, -0.1564366072, 0.1102900207, -0.1210132912, 0.2025828958, -0.0019102842, -0.1822917014, 0.0851008594, 0.1891973019, -0.0883233026, 0.0805514455, -0.1029163301, -0.0362101346, -0.1989262998, 0.1424619555, 0.1177086234, -0.0348578691, 0.0526777506, 0.0025217235, -0.1254328489, -0.2027739584, 0.1317826509, -0.2042178661, -0.1840894967, 0.0762514472, 0.2096597254, -0.1821867377, -0.1721322089, 0.1988409162, -0.0269709826, -0.0497884154, 0.1787462831, 0.0205632746, -0.0181038231, -0.0163949877, 0.0733549595, 0.0962017179, 0.0804091096, 0.1289397180, -0.1992752105, -0.0732874870, -0.1382424533, -0.1074526906, 0.0234863609, -0.1498726010, 0.1014916301, -0.1051092297, 0.0120407492, -0.0532581955, -0.1761582792, -0.1231599301, 0.1514270604, -0.0693330914, -0.0399371088, -0.1808742732, 0.0967165828, 0.0503450036, 0.0447240770, -0.0834280699, -0.1418748945, 0.1757943928, -0.0100928098, -0.1883556843, -0.1606097370, -0.0556207746, 0.0232119858, -0.0959400758, -0.0751698166, 0.0568815768, 0.1121352017, -0.1729973555, -0.2019679844, -0.0289052129, -0.0151661485, -0.1674913317, 0.1589995623, 0.0899834037, 0.1433444321, -0.0225699395, 0.1180243194, 0.2110497952, 0.0646307766, 0.1859165132, -0.0485507846, 0.1991371512, 0.0911098719, 0.2106680572, -0.1714508235, -0.1939509660, 0.0791778266, -0.0754837543, -0.0327089429, 0.1121619940, 0.2039345801, -0.1273471415, -0.2015063763, -0.0674412698, -0.0352532864, 0.0634191632, 0.0450389683, 0.0261033475, 0.0950153172, -0.1664189100, 0.1172609031, -0.1009978130, 0.1553344429, 0.0687726438, -0.0394574255, -0.1875092536, 0.1070518792, 0.1996398270, -0.0200542510, -0.0682562441, -0.0071145147, -0.1617317200, -0.0876040459, -0.1677239388, 0.1637404561, -0.1399584115, 0.1566878259, -0.1262205243, -0.2000394017, -0.0376290232, 0.1243444383, 0.1360243857, 0.1490159035, -0.1438673735, -0.1607309133, -0.0636731088, -0.0899126381, 0.0921191573, -0.0427442491, 0.0562658012, 0.0478655696, 0.0427762866, 0.0448572934, 0.0992826223, 0.1593501866, 0.0214248151, -0.0314345062, 0.0521414280, -0.0732607543, -0.1107577235, -0.0309938043, 0.1126447618, -0.1880721003, -0.1696287394, -0.0810296685, 0.1370448172, 0.0319990814, 0.0231824517, -0.0773761868, 0.1445294023, -0.0761980265, -0.1314511299, 0.1056902707, 0.0578934848, 0.0492510796, 0.2056159675, 0.1874613762, 0.1695712507, -0.1180968583, -0.1972379982, -0.0108184218, -0.0791732669, 0.1048881114, 0.1979803443, 0.2024841607, 0.1388750672, 0.1141068339, 0.1264521480, -0.1981775612, -0.0573552251, 0.0723751187, -0.1998384148, -0.1825031638, 0.1997896731, 0.0256707221, 0.1526589394, -0.0417924523, -0.1898938417, -0.2010440826, 0.1861183643, -0.1606833935, -0.2109050304, -0.0684543848, -0.1897711307, -0.0417264700, -0.0888886005, -0.1028481126, 0.1220721900, 0.0838447511, -0.1525900662, 0.0044677407, -0.1151472405, 0.0706208050, -0.1393886507, -0.1777141094, -0.1873037368, -0.1871229857, 0.0860051513, 0.1032820046, 0.0603369176, 0.0606627464, -0.0815231800, 0.1486389339, -0.1946210712, -0.0372415483, 0.0269194990, -0.1937365085, 0.0906293988, 0.0503427684, 0.0503278971, 0.2001654506, -0.1801522225, 0.0419180095, 0.1578094661, -0.0037205815, -0.0345633030, -0.0801014453, -0.0104420632, 0.1217197776, 0.1103863418, -0.1894428581, 0.0520878136, -0.1004308462, 0.0276933908, 0.0552809536, -0.1131219789, 0.1236320138, 0.0618739426, 0.1961426437, 0.1427689195, -0.0817000270, 0.0674391389, 0.0967779160, -0.0040636808, -0.1892023832, 0.1024222970, 0.1905990243, 0.0761097372, 0.1403602958, 0.2085951269, -0.1978327781, -0.1386842430, 0.0716426373, -0.1514661461, 0.1604115963, 0.1293117702, 0.0809597671, 0.1760691106, -0.1881445944, -0.2093095034, 0.0757643282, 0.0491489172, 0.0915529430, -0.1682676375, 0.0580054522, 0.0966015458, 0.1935326159, 0.2076593339, 0.1939801872, 0.1266939640, 0.0558563173, -0.1001905203, -0.2072352469, 0.0404997170, -0.0043535680, -0.0369075388, 0.0924699605, 0.1955164075, 0.0661515296, -0.1610964835, 0.1529740095, -0.0638748109, -0.0208785385, -0.0419577509, 0.1858939528, -0.1960482001, -0.0744788647, 0.0906780958, -0.0887935981, 0.0468099117, -0.0935182869, 0.0357558578, 0.1774282455, 0.1700491011, -0.0210153759, -0.1612454206, 0.1797387004, -0.1056237966, 0.0738513470, 0.1883957982, -0.0871931314, 0.1078689396, -0.0225079209, 0.1023400724, 0.0868689418, -0.1747629195, -0.0368673801, 0.0986522734, 0.2037334442, -0.1426269412, -0.0711795837, 0.1987050474, 0.1878060997, 0.1339875460, -0.0994506180, 0.0646777451, 0.1630476415, 0.2040054798, -0.1387091875, -0.0780089796, 0.1923853159, -0.0326879025, -0.0326911509, 0.0727188587, 0.1397978961, -0.0133277923, -0.0764702260, 0.2108619809, -0.0837472975, -0.0571934283, -0.1908024848, -0.0166734308, 0.2078124285, -0.1086236387, 0.2005369365, 0.1395209134, 0.1248455942, 0.0990054011, -0.1519040614, 0.2061503530, 0.1659146547, -0.1723120511, 0.1742579043, 0.0923238099, -0.2108805329, 0.1853901148, -0.1210635602, -0.1610381305, 0.2092482150, 0.1099981070, -0.1123044118, 0.1142407656, 0.0639456213, -0.1164770797, -0.1839908361, -0.0080247372, -0.1194459125, 0.0586822033, 0.1616915762, -0.0002340227, 0.0028121769, -0.1835221648, 0.1208060980, -0.2078100890, 0.0155630857, 0.2087851763, -0.0807315856, -0.1970693469, -0.0661643893, 0.0090000927, 0.1261626780, -0.1204295978, 0.0437651873, -0.1915783733, -0.1516554952, 0.0651507080, 0.1397578418, -0.1196567118, -0.0727079660, -0.1299479604, 0.0757280290, -0.0095487535, -0.1183249354, -0.0271632820, 0.1173901558, 0.1588713527, 0.0924242437, -0.2049111426, -0.1289208233, 0.1828841865, -0.0855947435, -0.0643326938, -0.0527134836, 0.1769357920, 0.0774650872, 0.1172084808, -0.0975405425, 0.0255076140, 0.1517721117, 0.1112448871, -0.0195154548, 0.0205666870, -0.0908947960, 0.0713352263, 0.0169820338, -0.0227927715, 0.0229648352, 0.1850242615, 0.0407651067, 0.1555531621, -0.0662065744, -0.1438441426, -0.1127760187, -0.1377274990, 0.2091112137, -0.0072878450, -0.1981091946, -0.0098019540, -0.1877576113, 0.1508529782, -0.0234492570, 0.0491071939, 0.0448753834, -0.0734052658, -0.0165965855, 0.1248821020, 0.0734958947, 0.1669113934, -0.0577529222, 0.2000485361, -0.1228384748, -0.1255454868, -0.1971827000, -0.1230085567, 0.1180750430, -0.0093547851, -0.0230401754, -0.0049679726, 0.2042787969, -0.1283455640, -0.1552554518, -0.0012578666, -0.1631354690, -0.1329830885, 0.0765587687, -0.0761249810, 0.1577172577, 0.0429348648, 0.1620784402, 0.0867160857, 0.1138004661, 0.0462742150, -0.1812913418, -0.0250388533, -0.0280440748, 0.0066502243, -0.1858594716, -0.0276051015, 0.1421964169, 0.0813965499, 0.1068108976, 0.0059656799, -0.1877613217, 0.0368406475, -0.0483537614, 0.1361891031, -0.1244090050, 0.0797127783, -0.1442604959, 0.1093797982, 0.1205075085, 0.0501118004, -0.0564092100, -0.1988244951, 0.2009366155, -0.1583352536, -0.0167462230, 0.0865212083, -0.2071752548, -0.1965620518, -0.1771773398, -0.1335911155, 0.0192012042, 0.1224520504, -0.1708127856, 0.0516567528, 0.1172842681, 0.1654311419, 0.1693318784, 0.1837634742, -0.0850449055, 0.0907040834, 0.0058849603, -0.0235214978, 0.0194096118, -0.1881018877, 0.2034058869, -0.1333278120, -0.1030089483, -0.1997814327, 0.0269460827, -0.0611050725, 0.0560825169, 0.1283653378, -0.1056428030, 0.1983804405, 0.0421571434, -0.0861751437, 0.0508041084, -0.2116856426, -0.0863313377, 0.0239236653, 0.0539779663, 0.0233431309, 0.1606138051, -0.0920646712, 0.1922321022, -0.0452404171, -0.1105760559, 0.2106334865, -0.1054409519, -0.0556141138, -0.1781117618, 0.1360196769, 0.1802893281, -0.0936985314, 0.1165351272, 0.0552333295, -0.0636999011, 0.1994484961, 0.0636085570, -0.0902845711, -0.0198717266, 0.1379822493, -0.0663420409, 0.1304030120, 0.1364517808, -0.1937849969, -0.1414416730, -0.0128650218, 0.1679543555, 0.0158417374, -0.1752573997, 0.0270776749, 0.1726594865, 0.0408231914, 0.2081383169, -0.1346630901, 0.0387143195, -0.1806079745, 0.1326352954, -0.0630900264, -0.0658071935, -0.1518288255, 0.1277736127, -0.0592663139, -0.0034587383, -0.1979734749, 0.1719286740, 0.0123056769, -0.1612582803, 0.2065779865, -0.0637299865, -0.1479045153, -0.0260363519, -0.2057416737, -0.0346208513, 0.2064574659, -0.0264683217, -0.0883198008, 0.1408757567, 0.1289643645, 0.1855285168, -0.1804073453, -0.0537951142, 0.0668195486, -0.1226902008, 0.0524666011, -0.1067594588, 0.1907449961, -0.0393671393, 0.1491917074, -0.1861257851, 0.1008849740, 0.2036682665, 0.1965058446, 0.0960520506, -0.0340944976, -0.0966986790, 0.0040719211, 0.0189812630, -0.1239445582, 0.1392132342, 0.2128939629, -0.2059993297, 0.0990686119, 0.0473121703, 0.0808303058, 0.2105965018, -0.1099056453, -0.1748321503, 0.0744347870, -0.1461552233, 0.1689332724, 0.0095289350, -0.1977693886, 0.0245501548, -0.1985494345, 0.0792918503, -0.0335043967, -0.0181492567, 0.0773982406, -0.1040530652, 0.0992784202, 0.0055586696, 0.1237892807, -0.1484608054, 0.0555051267, -0.1437306851, -0.0632395744, -0.1463977993, 0.1064682007, -0.0560435802, 0.0960682333, 0.0719676018, 0.0245992690, -0.0462644100, -0.0785900801, -0.0558394939, 0.1865259707, -0.0731129944, 0.1052559912, -0.0146709979, -0.1061939150, 0.0801361501, 0.0586482584, 0.1610437334, 0.1619606316, 0.0940272212, -0.0385499299, -0.0123391300, 0.1672401428, 0.1551659405, 0.0083943903, -0.1835677177, -0.0897399187, 0.1685397923, -0.1080016717, -0.0534483045, 0.1901096106, 0.1756649613, 0.0774500966, -0.1757703424, -0.1224443838, 0.0554220080, -0.0717803538, -0.0245188475, -0.0113737881, -0.0852353275, 0.0548189580, -0.0362652838, 0.0551236272, 0.1079287827, -0.0623466223, -0.0302456766, 0.0536195636, 0.1808533370, -0.0254818946, -0.1045151204, -0.0699811429, 0.2028083801, 0.1999809444, -0.0528029501, 0.1118593216, -0.1497626901, -0.1521579623, -0.1569841057, -0.0230683386, 0.1878478229, 0.0261472762, -0.1194706187, 0.0159520358, -0.0970126167, -0.1212493479, 0.0610946119, -0.0846420228, 0.1101294160, 0.1159366071, 0.0047756732, 0.1573970020, -0.1000526622, 0.2035552263, -0.1226661578, 0.0103985518, -0.0672702640, -0.1391693056, -0.2008733302, -0.1600718349, 0.1714603305, 0.0079642981, 0.1395266652, 0.1262914836, 0.1683962941, 0.0637745559, -0.1979252845, 0.0519728661, 0.1328639686, 0.1291106045, -0.0457876623, 0.2084420621, -0.1958028972, 0.1884651780, 0.0992593467, -0.1925799996, -0.1031548306, -0.1922521442, 0.0982190967, 0.1479490399, 0.1115373671, 0.0264677554, -0.0409521610, 0.0600257218, -0.1780522466, -0.1126354262, -0.1716191769, 0.1830831766, 0.1652213633, 0.0296512991, 0.0466898978, -0.0095825642, -0.0639636666, 0.0170907527, 0.0081479102, -0.2096172273, 0.1619519293, 0.0312604159, 0.0397034287, -0.0002698153, 0.1978329420, -0.0121454597, -0.0094526857, -0.0237273574, -0.0867079943, -0.0049833208, 0.1319896877, -0.1144113541, -0.1337009668, -0.1686180532, 0.1296547651, -0.0601793379, 0.1494078338, 0.0722094178, -0.1717362851, -0.1255957484, -0.1145360470, 0.0237909406, 0.1043739021, -0.1544477940, 0.0790340304, 0.0052815527, 0.2102528811, -0.0860441923, -0.0234307647, 0.1603132486, -0.0272525847, -0.1651003957, 0.1738359630, 0.2106792033, -0.0349970013, -0.0303519666, -0.0339978188, -0.1489456892, 0.2005601525, 0.2035722435, -0.1253810525, 0.1512997746, -0.0325741917, 0.0651094317, 0.0496669710, 0.2097713053, -0.0383381248, 0.0771798193, -0.1760617495, -0.1120572239, 0.1996681392, 0.0647082925, 0.1044281423, -0.0954377651, 0.1633413434, 0.1215559542, 0.0402642190, -0.0182905793, -0.1975707412, -0.0008970201, 0.0971205235, 0.1578942835, 0.2023544014, 0.1381759346, -0.0625620037, 0.1514950693, -0.0718256980, 0.0118870884, 0.1327362955, -0.1062853113, -0.1607363075, 0.0596870482, -0.1901426464, -0.1708513647, 0.1650001109, -0.0033199787, -0.0126292259, -0.0357793868, -0.1835055500, 0.0603061020, 0.1106692255, 0.1907842457, 0.1198039055, 0.1926206648, 0.1565317512, -0.0759528726, -0.1948379129, 0.1923233569, 0.1007493138, -0.1178143397, -0.1323398054, -0.1422309130, 0.0485868156, 0.1440326869, -0.0591032505, -0.1091527343, -0.1529152989, -0.1697878242, 0.0034380555, 0.1017098427, -0.0187026113, 0.1979413629, -0.0882942304, 0.1439684331, 0.1196214259, 0.0762318671, 0.1660355330, 0.1309429705, -0.0918098018, 0.1929387152, -0.1887128353, 0.0244574398, 0.1828245223, -0.1637505293, -0.1873486191, 0.1972919405, 0.1629608572, 0.0894708633, 0.1667929590, -0.1097143143, -0.0912832469, 0.0267206430, 0.1277072132, -0.1347484887, 0.0236548781, -0.0652003288, 0.1869010031, 0.1981157362, -0.1759383380, -0.1731866002, -0.0478647649, -0.1857491732, 0.2028805614, -0.1692140549, -0.0875881314, 0.1166424751, 0.0468351245, 0.1045762599, -0.1714083254, -0.0320059508, -0.1707411706, -0.0123952925, -0.0141666979, -0.2018545270, -0.1669420600, 0.2041317523, 0.0571704507, -0.0365011841, 0.1836222410, 0.1290774643, -0.1669084132, 0.1796984971, -0.0079360455, -0.0760267824, 0.1283863783, -0.2096923590, 0.0941240489, 0.1281087399, 0.0895640850, -0.0796302855, 0.1376777291, 0.1197003126, -0.1719098240, -0.1797896028, 0.0218136162, -0.0866396874, 0.1352225840, 0.0674757659, -0.1355925798, 0.0684938729, 0.1475597322, -0.0109589696, -0.0492037535, -0.1614322811, -0.1336855143, -0.1066660807, -0.0386074781, 0.0495053530, -0.0099364519, -0.1896707416, -0.1004594117, 0.1207754016, 0.0203200579, 0.2052307129, 0.0189252049, 0.0103460997, 0.0420710444, 0.1399002075, 0.1172848344, 0.1661094427, 0.2017557025, 0.0436914265, 0.0643244088, 0.2057434618, -0.0191677213, 0.0682848096, -0.1417491883, -0.0031131506, 0.0148516595, 0.0932514668, 0.2116248608, 0.0039765537, -0.1724414676, -0.1691936702, -0.1404601634, 0.1984391510, -0.0478304625, -0.1642811000, -0.1889132559, -0.1716609597, 0.1156466007, -0.0588394850, -0.1020036116, -0.2036255300, 0.2080315650, -0.1140736863, -0.0345724076, -0.1933063716, 0.1139229834, -0.0723220110, 0.1774840653, 0.1098777950, -0.0612724572, 0.0664094985, 0.1506472230, 0.1241123080, -0.0973965377, -0.1720945984, -0.1503418088, -0.0343479365, 0.0694606900, 0.1561326385, 0.2117401958, 0.0380726457, 0.2029472291, -0.1956074983, -0.0692329109, 0.0057167560, -0.1098129302, -0.1614622772, 0.0239131898, 0.0408787131, -0.0020718277, 0.0050014704, -0.1183702797, -0.0678333789, 0.0211721361, 0.1196450591, 0.0897656381, 0.0394547284, -0.0488569885, -0.0839669853, 0.0309076458, 0.1004701257, 0.0947154164, 0.0654139221, 0.0823945701, 0.1146301925, 0.0400183797, 0.0202626586, -0.1072974056, 0.2105867267, 0.1104008853, -0.0037561506, -0.0927053988, 0.0944980979, 0.1367858946, -0.0674200207, 0.1487843692, -0.0806787759, 0.1989254355, -0.0481174439, -0.1338374913, -0.2081667781, 0.1005316079, -0.1840391755, -0.0350880921, -0.0890243649, -0.0245165527, 0.1492657661, 0.1713838875, 0.0965442955, -0.2071402371, 0.1704485714, 0.1327006221, 0.0831274092, -0.0848695487, 0.1644728780, -0.0411594957, 0.0764342844, 0.1126935780, -0.2038380504, 0.0191847980, -0.0076710582, -0.0816929638, 0.1799655855, -0.0389810801, -0.0568400472, -0.1133250967, 0.0734277964, -0.0255433023, -0.1542529613, 0.1426350176, 0.0768330693, -0.1914806813, -0.1565151960, 0.1419842839, 0.0423746705, 0.1880020499, -0.1642536521, 0.0382031202, -0.0196413547, -0.1266663671, -0.1905800104, 0.0546536446, 0.2114781141}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w12.txt b/model/AE_model/hls4ml_prj/firmware/weights/w12.txt deleted file mode 100644 index cfa53f9..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w12.txt +++ /dev/null @@ -1 +0,0 @@ -0.0299687982, -0.0200913697, -0.1628506184, -0.1068779975, 0.0424054265, 0.0826480091, 0.0613067746, -0.0700136125, -0.0242939144, 0.1030909717, 0.0650041699, -0.0830966085, 0.0960527658, 0.1947352886, -0.2073853463, 0.0206085145, 0.2071990073, 0.0054719150, -0.0430176705, 0.0793472528, 0.0041321069, -0.0060941279, -0.1071751043, 0.0795918703, -0.1221742183, 0.1073543727, 0.1956848502, -0.0784232020, 0.1237751544, 0.2066734433, 0.1868695319, 0.1677424908, 0.0094357580, -0.0799254626, 0.2026934922, -0.0076247603, -0.0580709279, -0.0180531889, -0.1637006700, -0.1638052166, 0.0779233277, -0.1231834143, 0.0149706006, -0.0556826741, -0.1517318487, 0.0896132588, 0.0733369887, -0.0469554067, -0.2075115591, 0.2020627260, -0.1361604631, -0.0397243351, -0.0796420276, -0.0720068067, 0.1404963732, -0.1644846797, -0.1368613839, 0.1972313821, 0.1479609013, 0.1812329292, -0.0925163031, 0.1341431439, 0.0459197760, 0.2102182209, 0.1156741083, -0.1755264401, -0.1409626305, -0.0525652170, -0.1710569263, 0.1657299995, -0.1696748286, -0.1518070698, 0.1033410728, -0.1277162135, -0.1875155568, -0.0796543807, 0.1871464550, 0.0151327997, -0.1990237534, -0.0622079521, 0.0616436303, -0.0678324550, -0.0198629797, -0.0415979624, -0.1598083824, -0.0991619006, -0.0476939231, 0.1539309919, 0.0488269925, -0.0068289489, 0.0577009320, 0.0779598355, 0.0286590308, 0.1280354857, -0.0991276950, -0.1547031701, -0.0801663995, -0.2033021450, -0.0365294069, -0.0199189931, -0.1896166503, -0.1620380282, -0.1860011518, -0.1301473677, -0.1325807571, -0.1151512563, 0.0179842710, -0.0323763490, -0.0208511800, -0.0292268693, 0.0576676726, 0.1994232237, -0.1680585593, 0.1120285392, 0.2034228742, -0.1939662695, 0.1442087591, 0.0624234378, 0.1286650300, 0.2087322176, 0.0912633240, -0.0376317203, 0.0205214471, -0.0496083796, -0.2016787976, -0.1382226348, 0.0664850473, 0.0934087038, 0.0602796376, -0.0408537984, -0.1239186376, 0.1804018617, -0.1277865171, -0.1906520277, 0.0994181335, 0.0932106972, 0.1030148864, 0.1116523147, 0.0058985800, 0.0763316154, 0.0466108620, -0.0782565325, -0.1931094080, -0.1808894277, 0.0781139433, 0.0563023686, -0.0503799319, -0.0703481436, 0.0061757714, -0.0098461658, -0.2114745528, 0.0153114647, -0.1681676507, -0.1633462161, -0.0197864771, -0.1017761901, 0.0926398337, -0.0084916204, 0.1515615582, -0.0639852583, 0.0894241929, -0.1429507434, -0.2018470466, 0.1891367435, -0.1565079689, -0.1863281429, -0.0731568635, 0.1096500158, -0.1922487319, -0.0225030929, -0.0464011431, 0.0343073308, -0.0230456144, -0.0067266226, -0.1473098993, 0.0474331081, 0.1361288130, 0.1835507452, -0.0805701017, 0.1962219775, -0.0072854012, 0.1076261401, 0.1758356094, 0.2032818198, 0.1188454628, -0.0964757353, 0.0214861184, -0.0365467817, 0.1914212108, -0.1486441642, -0.0549377054, -0.1208507791, -0.0835755914, -0.1265096366, -0.2034690231, 0.0648523271, -0.1897552162, -0.0336513519, -0.1699216664, 0.0531323850, -0.1490594000, -0.0797703713, 0.2046851516, -0.1592926085, -0.1386430115, 0.0487061739, 0.0597852468, -0.1644745171, 0.1618199646, 0.0082582086, 0.1800731719, -0.0387442112, -0.0123487860, 0.1716650128, 0.1768315434, 0.0235440135, 0.1460557878, 0.1448304057, 0.1400508285, -0.2036625296, -0.0995768830, 0.1586339772, -0.1803688109, -0.1290575564, 0.1552039683, -0.0657280087, -0.1672912240, 0.0555873215, -0.1085671112, 0.0801717937, 0.0385826826, 0.0135929286, 0.0630749464, 0.0029980689, -0.1597732604, 0.0757490993, -0.0452418327, 0.0770318210, 0.0499458313, -0.0152857453, 0.0045678318, -0.0506545305, 0.0333602875, 0.0823979974, -0.1917371154, -0.1759482026, 0.0670691431, -0.0253701657, 0.2032220960, -0.1656939983, -0.0252533555, -0.2011405975, -0.1797123849, 0.0893137455, -0.1314969361, -0.1712016910, -0.1751994491, -0.1736104190, -0.1309947222, -0.1455578506, -0.0290444344, 0.1079195142, -0.0198743641, -0.1168765575, -0.1956928372, 0.0749217570, 0.1197899282, 0.1492062509, 0.0845648646, 0.1910144687, 0.0714731812, 0.0896423161, 0.0886339843, 0.0424313843, -0.1047299802, 0.1140542328, -0.0675532520, -0.0491651744, 0.1374236345, 0.0591898561, 0.0204799175, -0.2117312998, -0.0115324855, -0.1409758925, -0.1222114265, -0.0760993063, -0.1121596992, 0.0451081991, 0.1246991456, 0.0530746877, -0.1226361692, -0.1766454428, -0.1873668283, 0.0489591658, 0.1323884130, -0.0933586806, 0.0075565875, -0.0572030842, -0.1902633309, -0.1812438220, -0.0443895608, 0.0993377864, 0.1648918986, 0.0184242576, 0.1783342957, -0.1467216909, 0.1525241435, 0.0741368234, 0.1681051254, 0.2015506625, -0.1783226132, 0.0273520201, -0.1540651917, 0.1322736740, 0.1993274987, 0.0856180787, 0.2101798356, 0.1924318671, -0.0558870733, 0.0282167494, -0.1529767513, 0.2130309939, 0.0657108724, 0.0723687112, 0.0556191802, -0.0014367402, 0.1229352653, -0.2076495588, 0.1529274285, -0.0508707613, -0.1626865268, -0.0902138129, -0.1416822970, 0.1324886978, 0.1586819291, 0.0451759696, 0.0123371929, 0.0383366346, 0.1934813261, 0.1374279857, 0.1389309764, -0.1145577505, 0.1496672928, 0.0143344998, -0.1715855300, 0.0703697503, 0.0756785870, 0.0705799758, 0.0685043037, -0.0987578928, -0.1857370734, 0.0366628915, 0.0343631357, 0.1183466315, 0.0785025656, -0.1750455797, 0.1534826159, 0.1441718042, 0.0897021592, 0.0018040389, -0.0981088355, -0.1238731444, 0.1437948942, -0.1384842694, 0.0986107290, 0.0601267219, 0.0760452747, -0.0176557451, -0.2066420913, 0.1434316337, 0.1618829966, 0.1882940829, 0.0081178099, 0.0319456607, -0.0112308115, -0.0579738915, 0.1688969731, -0.0522499532, 0.0275250971, 0.1130464971, -0.1198113412, -0.1739815474, -0.2051894963, -0.0725248307, 0.0653609931, 0.1268644333, 0.0542542338, -0.1434755027, -0.1683304012, -0.0638830960, 0.1737835407, 0.0660760403, -0.0277434587, -0.1337418258, -0.0600245148, 0.1939641833, -0.0056484491, -0.0793008059, -0.1560899913, 0.1696815491, -0.0796096027, 0.1000609398, 0.1038047075, -0.1127653494, 0.0950272083, -0.1602330208, -0.1877627373, -0.1061679423, -0.1238565221, 0.1439324915, 0.1299566925, 0.0472214520, -0.0069753826, -0.1149794459, -0.2021604776, 0.1122357845, -0.1002883688, 0.0194462240, -0.0018406361, -0.0953991339, 0.0182069540, 0.0094234645, -0.0216829777, -0.0452967286, -0.0725801289, 0.0355390161, -0.1340863109, 0.1887212694, -0.1611262858, 0.1702066660, 0.0964568853, -0.1035552248, -0.0042550117, -0.0943432227, 0.1989069283, -0.0933973119, -0.0053331405, 0.0471409857, -0.0212728232, 0.2078837454, 0.2041386068, 0.0111851543, -0.1873343438, 0.1273722947, 0.2028470039, 0.0488651693, 0.1237006783, -0.0178181976, 0.0472271442, -0.0325583816, 0.1946828663, 0.1655352712, 0.2027935684, 0.1411809027, 0.1962138116, 0.1080618501, -0.0607369095, -0.0708165020, 0.1253030300, -0.0159034431, 0.1700783670, -0.0541625768, -0.0760538131, -0.0406669974, -0.0891414285, 0.1450912356, 0.0859740376, 0.2055131793, 0.1083478332, 0.0022055060, -0.0290104300, -0.0267654210, -0.0207869411, -0.1194224805, 0.0018991977, -0.0272793770, -0.1055083573, 0.0597414970, -0.1958667785, 0.0869557858, 0.0951965749, -0.1256363094, -0.0545191616, -0.1926113069, -0.0835183561, 0.0878288150, -0.1846973300, 0.0389287770, 0.0536273718, -0.1922698766, -0.1813737452, -0.0055727065, 0.0913288891, -0.0415549576, 0.0197254270, 0.1108522117, 0.0002185702, 0.0923810899, 0.0573065877, 0.0757805109, 0.1220797300, -0.0833618939, 0.1317946017, -0.0430670381, -0.0967186093, -0.0560624450, 0.0935617089, 0.0121237487, -0.0303220153, 0.0375040770, -0.0382418483, 0.0393078625, 0.0130563527, -0.0055943131, -0.1761269718, -0.0499690771, -0.0106518418, -0.0307799578, 0.0621480346, 0.0695970654, 0.1028584838, 0.0719177127, 0.0005092323, 0.1469067037, 0.1609019041, 0.1450909674, 0.0792758465, -0.0519316047, -0.2121607214, 0.0241434127, -0.0808357447, -0.2041620016, -0.1480538100, 0.1651775241, -0.2083772123, 0.1574057937, -0.1065901965, -0.0385201424, 0.1561101079, -0.1631736457, 0.0538884401, -0.1054305360, -0.2048415542, 0.0021589994, -0.0986903384, -0.0747502595, 0.1790751219, -0.1251314580, 0.1173853278, -0.1656351984, 0.0950775146, -0.1212994158, -0.0788257867, -0.1449895203, -0.1379195750, -0.1993272603, 0.1146961153, -0.0986853093, 0.0152729899, 0.0105710775, 0.1330817044, 0.1422324777, 0.0992231071, 0.1181887984, -0.1909636706, 0.0078451037, -0.1997201741, -0.0151363015, 0.1178297997, -0.1558717191, -0.0950169861, -0.1872103661, 0.2013084590, 0.0404230654, -0.1430938244, -0.0383232236, -0.1629514694, 0.1915737987, 0.0239459276, -0.1554045379, -0.0571268350, -0.0343904793, -0.0432691872, -0.1243529916, 0.0900253952, 0.0138496757, 0.2025043070, 0.0890162289, 0.2063539922, -0.0377029926, 0.0664572418, -0.1869729310, -0.0886757150, -0.1995316446, 0.1380406618, -0.0402527303, -0.0892176777, 0.1503989995, 0.0581840277, -0.1900311857, -0.0375838876, 0.1521078944, 0.0178539306, -0.0032742321, -0.1492450833, -0.1072543487, -0.0301053226, -0.0052204430, 0.1500692666, 0.1414586008, 0.1079036295, 0.0571198165, 0.0485185683, 0.1213852763, -0.1186918393, 0.1275147796, -0.0365253836, -0.1145128161, 0.0286160856, 0.1659997106, -0.2049054056, -0.0777986497, -0.0125737637, 0.0773003101, -0.0892232209, 0.2025945783, 0.0550533831, 0.0385752916, 0.1083570719, 0.1414549351, -0.0111115575, 0.0712562799, -0.1094422191, 0.1511150599, 0.0087268203, 0.0202568769, -0.0386397541, 0.1489885449, -0.1213671267, -0.2128057629, 0.1057298183, 0.0510607064, -0.1561504751, -0.1614055485, 0.1519888341, -0.0476292223, 0.2093452513, 0.0253442973, 0.1837027073, 0.0339175016, -0.0858129710, -0.0682265610, -0.1138197854, -0.1712946147, 0.0106116384, -0.0390239358, -0.1540293545, 0.1809662879, 0.1934553981, -0.0429925621, 0.0340826064, -0.1216562018, 0.1013063490, 0.0999135971, -0.0800538063, 0.0211647600, 0.1619406939, -0.0261410177, -0.0756101608, -0.0725631565, -0.0672484189, -0.1443044245, -0.2104350030, 0.1078053117, -0.1717941314, 0.0366245061, -0.1369144022, 0.0730428398, -0.0014251471, 0.0019932836, -0.0347588062, -0.1416097581, -0.0373671502, 0.1879232824, -0.0678206235, -0.0094726086, -0.1668108106, -0.2068654895, -0.0293164849, 0.1029573083, 0.0726135373, -0.1451911032, -0.0059137344, 0.2113559544, -0.1072068214, 0.2105501294, -0.0070212930, 0.2129808664, -0.1996234953, 0.0191973448, -0.0369255245, -0.0173931569, 0.0040988028, -0.1652255356, 0.0166354179, 0.0675693154, -0.1846835017, -0.0812719762, 0.1431894898, -0.0498331934, -0.0058604628, 0.0493593514, -0.1396758854, -0.1841018498, 0.1082337499, 0.1404029727, -0.0944251642, -0.1443277895, 0.1943573952, -0.0410360843, -0.0552903116, 0.1141994894, -0.2049532384, 0.1282199025, 0.1656420529, 0.1564200521, -0.1017887443, 0.1943162382, -0.1167149171, 0.1902273893, -0.0146615952, 0.0996394455, 0.1081024110, -0.0095883608, 0.0467160344, -0.1426015794, 0.1132473648, -0.0834285319, -0.2006640136, -0.0626687407, 0.1497789025, 0.0997542739, 0.0486185551, -0.1117992550, 0.1593234539, -0.0817669630, -0.1094438434, -0.2040923089, -0.0345581174, -0.1097800955, 0.1097026765, -0.1717210412, -0.1104205102, -0.2118057609, -0.0631954968, 0.1601560116, 0.0353156626, -0.0384458303, 0.0104279816, -0.0868183523, 0.0248557031, -0.0272359103, 0.1344070435, 0.1277020872, -0.0776934773, -0.1456069648, 0.1698482037, -0.0428069234, -0.0244031101, -0.0958980396, -0.1205567792, -0.0047460347, -0.0705674291, 0.1576403379, 0.2007039785, 0.0109769553, 0.1511013210, -0.1129482910, 0.1351296306, -0.2037522495, 0.0605449677, 0.0585310459, -0.1157551780, 0.0295844674, -0.1049444377, 0.1212015152, 0.1379203498, -0.0699597448, 0.0286668092, -0.0065829754, -0.1788249761, -0.1312187314, 0.1286323965, 0.1392367184, 0.1908683181, 0.0242387205, 0.1691608727, -0.2020194232, -0.0678330660, -0.0243738294, -0.0575586557, -0.0077267736, -0.1400625110, 0.1848634481, 0.1182062626, 0.0595957637, 0.1738096774, 0.1422152519, -0.2081463337, 0.0900264084, 0.1681007445, -0.1872164607, 0.0730664432, 0.1905981898, 0.0831505358, -0.0544702560, 0.1223368645, 0.1236465275, 0.1874395013, 0.0316298008, 0.1114262044, 0.0823487937, 0.0209904611, -0.1241559684, -0.1212982461, -0.1685856283, 0.1621521115, -0.0055004209, 0.0879061222, -0.1197008863, 0.0481621325, 0.1770572662, 0.2034153938, 0.0980803668, 0.1807042062, -0.0962149203, 0.0693045855, 0.1404873729, -0.0112236440, -0.1166152358, 0.0854465663, 0.0849801004, 0.1941885948, 0.1874067187, -0.1194612682, -0.0316866338, 0.1586165428, 0.1986514628, -0.0514322966, 0.0083613992, 0.0338022709, -0.0840201527, 0.1076180935, -0.1840358078, -0.0786230713, 0.1650006175, 0.1759569347, -0.0984335914, 0.0937895179, -0.1591776758, -0.0548721850, 0.2099168897, -0.0761839002, -0.1439442784, -0.1180057228, -0.0115567297, 0.2119663954, -0.2084765881, -0.1429431587, 0.1304834485, 0.0253197849, -0.0495870262, -0.1593472958, 0.1906189919, -0.0755666047, 0.0204891115, -0.2027017176, 0.0845215023, -0.0375019461, -0.0741307288, -0.1682538986, -0.0986525714, -0.1323923767, 0.0248608440, 0.1058465838, 0.1753382683, -0.1236304268, 0.1611528993, -0.0788172930, 0.2003071308, 0.0172708482, 0.1628030837, 0.0418015420, -0.0545591116, -0.0956913158, -0.1495652795, -0.1087132543, -0.1375667155, 0.1122941375, -0.1753409654, -0.1203577742, -0.1041368321, 0.1671169102, -0.0055812448, 0.1678700149, 0.0990319848, -0.1881180555, 0.1386297345, -0.0494644642, -0.0536248833, -0.1219948381, 0.0529752672, -0.0706597269, 0.0397333801, -0.1728109568, -0.0324662775, -0.1066334024, 0.0403463542, -0.0274363458, 0.0952627063, -0.1018335298, 0.0583408773, 0.1738654077, 0.1537837386, 0.0972969532, -0.1946167499, 0.0721558928, -0.0901098624, -0.0134937465, 0.2068599164, -0.1080145761, 0.0695914626, 0.1576732397, 0.1439830065, -0.1283816546, -0.0403546393, 0.1978405118, 0.0215785801, 0.1189253926, -0.1251751781, -0.1324729919, -0.0573372245, 0.1317686737, 0.1840246916, -0.0632864386, -0.1593850106, -0.2103401572, -0.0452760458, 0.0562445223, -0.0672827810, -0.1317190230, -0.1057995185, 0.0628919005, 0.1449728310, 0.1558126509, -0.1442781389, 0.1884695888, 0.1673473418, -0.0872376114, 0.1140232086, -0.0252642781, 0.0438523591, 0.1734786332, -0.0142899752, 0.0308145732, -0.1282856315, -0.1500093937, -0.0310410261, -0.0346261412, 0.0138389915, -0.0564204454, 0.1973220706, -0.1628828943, 0.2086023390, -0.0911404118, 0.1388567388, -0.0801965445, 0.1897435784, -0.0078805834, 0.0966969132, -0.1342030764, -0.1829697788, 0.0274105668, 0.0954551399, 0.0424244702, 0.0432503819, -0.1348703206, 0.0819534659, 0.1172466576, -0.1045202017, -0.0274430066, -0.2078236043, 0.1791496873, -0.0249381959, -0.0028370321, -0.1151518151, -0.0351021737, 0.1781578660, 0.1670326293, 0.1231856048, 0.0522374511, -0.0416953564, -0.0919703320, 0.2049568295, 0.0597164333, -0.1264267862, 0.0250963420, -0.1367215514, 0.2062895894, -0.2021236271, -0.0789147466, -0.1009974107, -0.1868142933, 0.1095725596, 0.0458966494, 0.1690641642, -0.0414194912, 0.0501979589, -0.1225041598, -0.0142165720, 0.1769432127, 0.0690946877, -0.0368168950, -0.2125138342, 0.1564998329, 0.1774396300, -0.0208842754, -0.1699668020, 0.1192377508, 0.2057524025, -0.0954460502, 0.0930086076, 0.1147645712, -0.1254046261, 0.1324979365, -0.1101972088, -0.0763699412, 0.0361105055, 0.0514391661, 0.0420373082, -0.0369996876, 0.0854761600, 0.1843793690, -0.1736085415, -0.0634968281, 0.1430990696, 0.1729621291, 0.1585301757, -0.1438342333, 0.0730384588, -0.1971729845, 0.0652405918, 0.0152683109, -0.1353506446, 0.1925430894, 0.0246178210, 0.1677184999, -0.0048195422, -0.1687426418, -0.0789889991, 0.0222119838, 0.1184870303, -0.0578724742, 0.0195703506, 0.1599646807, -0.0953619257, -0.1090037525, 0.0946376324, -0.0791863799, -0.0674538761, 0.1205617189, -0.0457265675, -0.0772978514, 0.0474117100, 0.1960088611, 0.0076489449, -0.1340975463, 0.0089059472, -0.0732634515, -0.0593659431, 0.1910074353, -0.0600316823, 0.1865903735, 0.2039996982, 0.0955586433, 0.0850807428, 0.0748503804, 0.1393448412, 0.1457204521, -0.1769429147, -0.1073040143, -0.1568056345, -0.1769776195, 0.0820996165, -0.0717875659, 0.0552145839, 0.0963548124, -0.1853030771, -0.0829025805, 0.1825232804, -0.0630365610, 0.1861030757, 0.0656674206, -0.0497936457, 0.1127585769, 0.1411151290, -0.1029667556, 0.2078949213, 0.0462093055, 0.0898126066, 0.0131751001, 0.1630607545, 0.0629414618, 0.2107377648, 0.0717314482, -0.0816785246, 0.0140785575, 0.0746624172, 0.1485654712, 0.0411568582, -0.0456013680, 0.1087857783, 0.0439174473, -0.0011476576, -0.1062764674, 0.0663406253, 0.2129457891, 0.0096564740, -0.1795127243, 0.1119864583, -0.0606164932, 0.1801105440, 0.0738519132, -0.0362794101, 0.0169439614, 0.1146946251, -0.0022736192, -0.2109142840, 0.0731431842, -0.2111463845, -0.0210354924, 0.1228208840, 0.1741955280, -0.1463062465, 0.0535667241, 0.0714875758, 0.1088028550, 0.1164041460, 0.2026323378, -0.0252092779, 0.0014938712, -0.1912081689, -0.1331903189, 0.1476591229, -0.1678193510, -0.0322937071, 0.1266770959, -0.0697968751, -0.0139189065, -0.1026626825, -0.0157848597, 0.0318510234, 0.1830307841, -0.0639783591, 0.0032776296, 0.1112110913, 0.1398272812, 0.2115580142, 0.0822045207, 0.1698623598, 0.1983507574, 0.1014650464, 0.0911060572, -0.1313718259, 0.1438991427, -0.0996037722, 0.0321595073, 0.0923565328, -0.0361539572, -0.2123867571, 0.1487106979, -0.0159201771, 0.1643887162, 0.0597353876, -0.1827633679, 0.1444546580, 0.0984890461, 0.0160970092, 0.0142266899, 0.0770986378, -0.0505784303, -0.0323747844, -0.1830642819, 0.0064463913, 0.0076768547, -0.1202597693, -0.2009681910, -0.1707529575, 0.1267985106, -0.0900287405, -0.0438698083, -0.1021372974, 0.0055644661, -0.0194720328, 0.1149333417, -0.0809840262, -0.1144135445, 0.2040384710, -0.0188029557, 0.1048910618, 0.1795919538, -0.1614289731, 0.0341091901, -0.0088966489, 0.0277018845, 0.1153512597, 0.0880717933, -0.1324718297, 0.1717734039, -0.2016137391, -0.1045009866, 0.1157133877, -0.0166334361, -0.0154671073, 0.1994017363, -0.1078871936, 0.1074694693, 0.1580016911, 0.1991653144, 0.1872931123, -0.1518543363, 0.0200148076, -0.1169207320, 0.0856198668, 0.0655365288, 0.1064652503, 0.1896738410, 0.0871496797, 0.2046217620, 0.1393769979, 0.0166612864, -0.0847424716, -0.1429281235, 0.0346267968, 0.1239484847, 0.0759538710, 0.0976523757, 0.0261277556, 0.0197988302, -0.0161558241, 0.0142623633, -0.1662683934, 0.1792075336, 0.0535419285, -0.1046166271, 0.0217982680, 0.1907408237, -0.0097986907, -0.0788309723, -0.1983426064, 0.1801694930, 0.1988052130, 0.1525231898, -0.0462639928, -0.1794506609, -0.1983816922, -0.0863542110, 0.1962837577, 0.0113638788, -0.1423419416, 0.2009785175, 0.0230496824, -0.0825804174, 0.0670066476, 0.0893870592, 0.1693057418, -0.0931251049, 0.0395222306, -0.0908814818, -0.0015156865, -0.1482891142, -0.1197384968, 0.0808253288, 0.1706576049, 0.1219940186, -0.0090284497, -0.1708687544, -0.0672705173, 0.1744294167, -0.0471183211, 0.1627449393, 0.0505898595, 0.1289803386, 0.1933867931, -0.0364499092, 0.2092516422, -0.0879659653, -0.1325432360, -0.1883024126, 0.1935233176, 0.0722268522, -0.0351103544, -0.1282860935, -0.1669809967, 0.0634535849, 0.1463640928, 0.1115628481, 0.1915774643, -0.1330951154, -0.0498410761, 0.1824287474, -0.1198925152, -0.1558498144, 0.0115216672, -0.0575571805, 0.1512074769, -0.0792186111, -0.1005453169, 0.1918959022, 0.1577787995, -0.0474315286, 0.1767385006, 0.1532249153, 0.0381480753, -0.0994352177, -0.1345816553, -0.0714825839, 0.1817150712, -0.0423345566, 0.0728407800, 0.0606569946, 0.1074360311, -0.1082013845, -0.1286506951, -0.1654386818, 0.0755141973, 0.1346943080, 0.0741473436, 0.0272509605, -0.1022430733, -0.1535176337, -0.1437671334, 0.0033517927, 0.0385562479, -0.2093280107, -0.1801258922, 0.1942785680, 0.1442832649, 0.0647675097, 0.0466073155, -0.0312325507, 0.1904779971, -0.0702055097, 0.1841617227, 0.0860672593, -0.0434789211, -0.1418571472, -0.0536649376, 0.0984870791, -0.1137775481, 0.0694874823, 0.0945133567, -0.1912234277, 0.1735962331, -0.0742257386, 0.1887037754, -0.1645788699, 0.0214261860, 0.1316542625, -0.1871816963, 0.0810263753, 0.1041027904, -0.1497622430, -0.0212554485, -0.1823785156, 0.1808028221, 0.1183961034, 0.1672869921, 0.1207077503, 0.0926214755, 0.1032781005, 0.0705330670, -0.0409869701, -0.1389550120, 0.0041922331, -0.0760333836, -0.0342211723, -0.0022919774, 0.0694222152, -0.1467096359, 0.0167407840, 0.2002843916, -0.2026804835, 0.0219483674, 0.1510784626, -0.2011389732, 0.1555231214, -0.0785504282, -0.0242179781, 0.0736868083, 0.0837689936, -0.2070930153, 0.1436602771, -0.1341157854, -0.0420701355, -0.1833635718, 0.0336981118, -0.1235698834, 0.0389548540, 0.0881867111, 0.0741657019, -0.1485468149, -0.1753440648, 0.0552891493, 0.1398189962, 0.0925252438, -0.0714594126, 0.1528547406, 0.0452864170, 0.1368271112, -0.1442251801, -0.1871099770, 0.1367825866, 0.0078157187, 0.0879496336, -0.1634112298, -0.1578331888, -0.1039924771, 0.1737509668, -0.2009857148, 0.0084375441, -0.0871703029, 0.1638271213, -0.1012258977, 0.0226652473, 0.2094560564, -0.2052043378, -0.1554896235, 0.1281714737, 0.1526623070, 0.0711450577, -0.1538139880, 0.1103184819, -0.1276670098, -0.1715557873, -0.0104382038, -0.1191718876, 0.1682462394, 0.1613282859, 0.0988994539, 0.0623968840, 0.0341099948, 0.1983372867, -0.1309966445, 0.1504108608, 0.0166955441, 0.1539048254, 0.0171548128, -0.1117881685, 0.1348723173, -0.0929081589, 0.0306994468, -0.0673389435, 0.1843204200, -0.0494693965, 0.0026714802, 0.1970034242, 0.1465358436, -0.2089259773, -0.0306969434, -0.0623424053, 0.1178109348, -0.1690531224, -0.1106899157, -0.0879889876, -0.0418089181, 0.0957140326, 0.1265924871, -0.0413431525, -0.1948350221, 0.0549199581, -0.1067268252, 0.1657143831, -0.0590002686, -0.1327666938, 0.1300134361, -0.0232419223, 0.2081829906, -0.0133474618, -0.1192633808, 0.0818081498, 0.0748744309, 0.1030098200, 0.1931266487, -0.1345575154, 0.1282161474, 0.0507016480, -0.0075940490, 0.1418971121, 0.2076115310, 0.0331827849, -0.0025079995, -0.0684792399, -0.2117804438, 0.0889830291, -0.0081021041, 0.0968770087, -0.0448308140, -0.2018771470, 0.1256079674, -0.1889444590, -0.1807408929, -0.1891945004, 0.1386094987, 0.1040057838, 0.2109294832, -0.1347030997, -0.0752518028, -0.1905307919, -0.0660125017, -0.1359195858, 0.0700816810, -0.1311333477, 0.1863650084, 0.0182687193, -0.1991056353, -0.1986645758, 0.0332740843, 0.1223597527, 0.1440291107, -0.1991315633, -0.1418480575, -0.1046753898, 0.1215175390, -0.1528828144, -0.0192871094, -0.0392865241, 0.1554636955, 0.1521648169, -0.0530413985, 0.1745767593, 0.1329261065, 0.1173268855, -0.0834161788, 0.1669941545, -0.1135928258, -0.0104432255, 0.2093745172, -0.1487203538, -0.0243670642, 0.0781385601, -0.0863867402, -0.1772288829, 0.0374935269, 0.0326699018, -0.1416948438, 0.1712468863, -0.2092596889, -0.0162612945, 0.1995322108, -0.0407852232, 0.1391594112, 0.1703530252, -0.1247310713, 0.0101923794, -0.1614331901, -0.1967547536, 0.1085800827, 0.0099474788, -0.1713281572, -0.0349265933, -0.1580587327, -0.0134223402, -0.1268889010, -0.0272006392, 0.0517058074, 0.0707002580, -0.0472020358, -0.0683047771, 0.0666269660, 0.0012337267, 0.1978390217, 0.1685774326, 0.0937682688, 0.1021435857, -0.1766422987, 0.1285056174, 0.0278677493, 0.2131409347, -0.0197218806, -0.0183848143, 0.1801211238, -0.2011249512, -0.1342885196, -0.1063225642, -0.1096163169, -0.0815093517, 0.1041289568, 0.1356954575, 0.0624127984, -0.1830896437, -0.1202615499, 0.0235555023, 0.1180990338, 0.0151791573, -0.1735906005, -0.0099890083, 0.1042123735, -0.1211249679, -0.0183042437, 0.0646506846, -0.1295357645, -0.2120593637, -0.0708652437, 0.1243365109, -0.0544359982, -0.0681137592, -0.0318974257, -0.0399938375, -0.2073388398, 0.1302348375, 0.1618840694, 0.0332589298, 0.1849151850, 0.1767701805, -0.1539921910, 0.0606725514, -0.2084412575, -0.1359802783, -0.1610464752, -0.0460764319, -0.0974373594, -0.0677113235, 0.0968209207, 0.1616028249, 0.0057454854, 0.1070614457, -0.1252095997, 0.1165149510, 0.1797955036, 0.0990042090, -0.0438649803, -0.2108273208, -0.1882810742, 0.0832380652, 0.1381633580, -0.1082440838, -0.2057079226, 0.1687243879, 0.0165371001, -0.0090067983, 0.0030519515, -0.1095453575, 0.0558823049, 0.0032670647, 0.0653376877, -0.0037532598, 0.0686316192, -0.0914803669, 0.1204346418, 0.0681389868, 0.0972673297, 0.1868832707, -0.1156612411, 0.0290973932, 0.1910237670, 0.0628211200, 0.0652168095, -0.1818069816, 0.0808030069, -0.2054787725, 0.1728060246, 0.1067647040, -0.0791605115, -0.1227906942, 0.2060981393, 0.0920174122, 0.0442633331, -0.0913680345, 0.0774338245, -0.1595715582, 0.0464090705, 0.0904039145, 0.0160845071, -0.0072901845, 0.1936618984, 0.1889795959, -0.0602845103, 0.1024118364, -0.0906693637, 0.0332486182, 0.1135805845, -0.0269023627, 0.1737165153, 0.0655167997, 0.2131136060, -0.0408491194, 0.1877136528, 0.1271311045, 0.0442544520, 0.1611259580, 0.1131458282, 0.0869052708, 0.0794386566, -0.1972284913, -0.1239228025, 0.0040045232, -0.0112203807, 0.0104427189, 0.0851106346, 0.1309471428, -0.1934918612, -0.0773466080, 0.1444209814, 0.0258134604, 0.0405142605, -0.2011807114, -0.0524137318, -0.0633147508, 0.0562126935, 0.0138960779, 0.0027410090, -0.0553597510, 0.1429971457, -0.0844705701, -0.1139667407, 0.1930039823, 0.1534200013, 0.0817907155, -0.0481107384, 0.1761950254, -0.0427481681, -0.0800165981, 0.1292200089, -0.0713572800, -0.1633257270, -0.1784992516, 0.2117676437, 0.0497537553, -0.1343480349, 0.1995138526, 0.1230620742, 0.1978739500, 0.0688371956, -0.1255532205, 0.0393286645, 0.1028071940, -0.0379785895, 0.1169190407, -0.1697795391, 0.0002817065, -0.0651353747, -0.0321286619, -0.0973549113, -0.0383515954, -0.0690279007, 0.0932333767, -0.0843957514, 0.1068355143, -0.1142790467, 0.1139979362, -0.2103314102, -0.1968776584, -0.0599546731, 0.0578142405, -0.1474400312, -0.0340850949, -0.1431041956, -0.1225979477, 0.0317832083, 0.2002293169, 0.1547575593, -0.0025028139, 0.0855506361, 0.2077602744, 0.1482928097, 0.1962883770, -0.0263144523, 0.0999545455, -0.1755501330, 0.0907763541, 0.2108449042, 0.1564360857, -0.1490325630, -0.2122148573, 0.1328415275, -0.0560300648, 0.0927752256, -0.1412148029, 0.1037666798, -0.0936286896, 0.1331335306, 0.1564979255, 0.0636173487, 0.1403563321, -0.1232199147, 0.2115045786, 0.1556344926, 0.1365908086, -0.1735243648, 0.0514004230, 0.0813339949, -0.0397134125, 0.0008128434, 0.1764344871, 0.0534341335, -0.0965536609, -0.0563279837, -0.0701866448, 0.1678231657, -0.1305635720, -0.1049790010, 0.1803027987, -0.1480420679, -0.0221689790, 0.0227394551, -0.0514955819, 0.0391811430, -0.0903801844, 0.0161486119, -0.1661705375, 0.0148486495, -0.1189615428, -0.2023089528, 0.1500414014, 0.1575564146, 0.2006876469, -0.1427052170, 0.1038216352, 0.1328781247, -0.0355130285, -0.0493305773, 0.1476909816, -0.1162002012, 0.0018752515, 0.1564856172, 0.1089758575, 0.1843735874, -0.1625342369, 0.2025069296, 0.0816542208, -0.2002037317, 0.1977411807, 0.1830754280, 0.1948248446, 0.0473127961, 0.0856705010, -0.1472903192, 0.0240328014, -0.1473911256, 0.1059477031, -0.1635962129, 0.0690924525, 0.1293298900, 0.0291915834, 0.1522969902, 0.1869597137, 0.0537905991, -0.1628608406, -0.0562254041, -0.0952598080, -0.0580354929, 0.0834422708, -0.0904143378, -0.0870322436, 0.0731475651, 0.1328050792, 0.0595055819, -0.1284235865, 0.0775947571, 0.1282472014, -0.0781846493, -0.1768473983, -0.1059038192, 0.0783807635, 0.0185207874, 0.1210107505, -0.0355900973, -0.1083190590, 0.0551561117, -0.0146243870, -0.1358241141, 0.0594488978, -0.1208960190, 0.1518229246, -0.1121866331, -0.1449517012, -0.1512638927, -0.2059335560, -0.0745748878, 0.1951863468, 0.1911711693, -0.1959552318, 0.0085752457, 0.1613205969, -0.1183672324, -0.1731554866, -0.0484661460, 0.0297663808, 0.0933525264, -0.0036646575, -0.1410296857, 0.2080911398, -0.0710754842, -0.1831357479, -0.1716746837, 0.1974130571, -0.0352466851, 0.1570383608, -0.1903720498, -0.1753707528, -0.1628082246, -0.1246879175, -0.0627532750, 0.1821535826, -0.1860825270, 0.1057403088, 0.1573023498, -0.1415687501, -0.1320505738, 0.1899049580, -0.0032659471, 0.1987372637, -0.0291750133, -0.0125812888, 0.1250814497, 0.1543976665, 0.1588623226, -0.0772247612, 0.1269832850, 0.0809114277, -0.2079120576, -0.2060230672, 0.1824369133, -0.0100146681, 0.2086891532, 0.1752610207, 0.1876649559, -0.0246680826, -0.0451197475, 0.0043716729, -0.1415401697, -0.1758477986, -0.0596223921, 0.1316759586, -0.0559997708, -0.0688156337, 0.0573354363, 0.0119467080, -0.1301584542, 0.1751771867, 0.1697615385, 0.1741175056, 0.1899056733, -0.1500841081, -0.1966127753, -0.1269682944, 0.0956632495, -0.0649770349, 0.0084272772, 0.2049444020, -0.1740206331, 0.1296412945, 0.1302121878, 0.0303550661, 0.1835718751, -0.0123747587, -0.0687476248, -0.0049850494, 0.1179048121, 0.1232193112, 0.1716808677, 0.1933630109, 0.0383467674, 0.1538934708, 0.0399881005, -0.0753969848, 0.1629869342, 0.1576235592, -0.2061833888, -0.1943323910, -0.1071545705, -0.1535230726, -0.1996119171, 0.1132124662, 0.2103752792, -0.1986448467, -0.1092130244, -0.0629687458, 0.0168035626, -0.0435729027, 0.0788228810, 0.1089095175, 0.0574910045, -0.0307945460, -0.0557697564, -0.1573819667, 0.0387057960, -0.1841708720, 0.0259755105, 0.1528935432, 0.0440687537, -0.1419970393, -0.0956466347, -0.1713100672, -0.1513942778, -0.1747036427, -0.0862678587, -0.1714905649, -0.0699100792, 0.1882464886, 0.1420514286, -0.0752908885, 0.1676419377, 0.1588957012, -0.1760142744, -0.1110270768, 0.1897342205, -0.2016245723, 0.1889849305, 0.0963345766, 0.1372450590, -0.0214768201, -0.0735859275, 0.0885555148, 0.1388621330, -0.0230655819, 0.1722593904, 0.2026747465, -0.1153706908, 0.0849388838, 0.1582046151, -0.1976340264, 0.0836519301, 0.1209901571, -0.1021070480, -0.1253621280, 0.0024885833, -0.1998213828, 0.1640697122, -0.0472567230, -0.2121480554, -0.0621883422, 0.0732249320, -0.1825171858, -0.1615246385, -0.0747048706, -0.0765175521, 0.1380745769, 0.1035941541, 0.0566515625, -0.1656499356, -0.0494195819, 0.0154630542, -0.0155421346, 0.0999943018, -0.0983497724, -0.0023596287, -0.0089180022, 0.0952349901, 0.2121636569, 0.1911831498, -0.1771416515, 0.1345708370, 0.0569574237, 0.0976062715, 0.0373338163, 0.1374650598, 0.1132061481, 0.0398771465, -0.1904560328, -0.0199830383, 0.1737166047, 0.0579673350, -0.1397959590, 0.0845487416, 0.0635729134, -0.1875258237, 0.0082111955, -0.0156118274, -0.0246786624, 0.0612721145, -0.1228818372, -0.0824263990, 0.0642475486, -0.0011276305, -0.1635920405, 0.0701577365, -0.1154046953, 0.0584930182, 0.2104386091, 0.1489616632, -0.1016275138, -0.1633670628, 0.0255742520, 0.1254868209, -0.0513779521, -0.1428818554, -0.1509671360, 0.0329130292, -0.1813355684, 0.0400531590, 0.0307151526, 0.1701872051, 0.1005813181, 0.1923497319, -0.0850675851, 0.1909916401, 0.1995913386, -0.2029951215, 0.1294534206, 0.1793923080, 0.1737214327, -0.1812362373, -0.0247590691, -0.1586031765, -0.1100956500, -0.1073428467, -0.1396663934, 0.1241170764, 0.1778326631, -0.1573841572, -0.2054813653, -0.0386196226, -0.0788801759, -0.1261099130, 0.0681798458, -0.1681665778, -0.1431814581, -0.0348086655, 0.1602859497, -0.0285475105, -0.0923261940, -0.0164624304, -0.0991970226, -0.0123434514, 0.0399152040, -0.1202259138, -0.0785073340, 0.1368511617, -0.1663074791, 0.1028437316, 0.0936442316, 0.1018613279, -0.0085767657, -0.1116045192, 0.1987394094, 0.0133036524, -0.0635730773, 0.0212164521, 0.1224555671, -0.2004901171, 0.0609331131, -0.0939833373, -0.1074724123, -0.0456439555, -0.1393577456, 0.2108364701, -0.1564366072, 0.1102900207, -0.1210132912, 0.2025828958, -0.0019102842, -0.1822917014, 0.0851008594, 0.1891973019, -0.0883233026, 0.0805514455, -0.1029163301, -0.0362101346, -0.1989262998, 0.1424619555, 0.1177086234, -0.0348578691, 0.0526777506, 0.0025217235, -0.1254328489, -0.2027739584, 0.1317826509, -0.2042178661, -0.1840894967, 0.0762514472, 0.2096597254, -0.1821867377, -0.1721322089, 0.1988409162, -0.0269709826, -0.0497884154, 0.1787462831, 0.0205632746, -0.0181038231, -0.0163949877, 0.0733549595, 0.0962017179, 0.0804091096, 0.1289397180, -0.1992752105, -0.0732874870, -0.1382424533, -0.1074526906, 0.0234863609, -0.1498726010, 0.1014916301, -0.1051092297, 0.0120407492, -0.0532581955, -0.1761582792, -0.1231599301, 0.1514270604, -0.0693330914, -0.0399371088, -0.1808742732, 0.0967165828, 0.0503450036, 0.0447240770, -0.0834280699, -0.1418748945, 0.1757943928, -0.0100928098, -0.1883556843, -0.1606097370, -0.0556207746, 0.0232119858, -0.0959400758, -0.0751698166, 0.0568815768, 0.1121352017, -0.1729973555, -0.2019679844, -0.0289052129, -0.0151661485, -0.1674913317, 0.1589995623, 0.0899834037, 0.1433444321, -0.0225699395, 0.1180243194, 0.2110497952, 0.0646307766, 0.1859165132, -0.0485507846, 0.1991371512, 0.0911098719, 0.2106680572, -0.1714508235, -0.1939509660, 0.0791778266, -0.0754837543, -0.0327089429, 0.1121619940, 0.2039345801, -0.1273471415, -0.2015063763, -0.0674412698, -0.0352532864, 0.0634191632, 0.0450389683, 0.0261033475, 0.0950153172, -0.1664189100, 0.1172609031, -0.1009978130, 0.1553344429, 0.0687726438, -0.0394574255, -0.1875092536, 0.1070518792, 0.1996398270, -0.0200542510, -0.0682562441, -0.0071145147, -0.1617317200, -0.0876040459, -0.1677239388, 0.1637404561, -0.1399584115, 0.1566878259, -0.1262205243, -0.2000394017, -0.0376290232, 0.1243444383, 0.1360243857, 0.1490159035, -0.1438673735, -0.1607309133, -0.0636731088, -0.0899126381, 0.0921191573, -0.0427442491, 0.0562658012, 0.0478655696, 0.0427762866, 0.0448572934, 0.0992826223, 0.1593501866, 0.0214248151, -0.0314345062, 0.0521414280, -0.0732607543, -0.1107577235, -0.0309938043, 0.1126447618, -0.1880721003, -0.1696287394, -0.0810296685, 0.1370448172, 0.0319990814, 0.0231824517, -0.0773761868, 0.1445294023, -0.0761980265, -0.1314511299, 0.1056902707, 0.0578934848, 0.0492510796, 0.2056159675, 0.1874613762, 0.1695712507, -0.1180968583, -0.1972379982, -0.0108184218, -0.0791732669, 0.1048881114, 0.1979803443, 0.2024841607, 0.1388750672, 0.1141068339, 0.1264521480, -0.1981775612, -0.0573552251, 0.0723751187, -0.1998384148, -0.1825031638, 0.1997896731, 0.0256707221, 0.1526589394, -0.0417924523, -0.1898938417, -0.2010440826, 0.1861183643, -0.1606833935, -0.2109050304, -0.0684543848, -0.1897711307, -0.0417264700, -0.0888886005, -0.1028481126, 0.1220721900, 0.0838447511, -0.1525900662, 0.0044677407, -0.1151472405, 0.0706208050, -0.1393886507, -0.1777141094, -0.1873037368, -0.1871229857, 0.0860051513, 0.1032820046, 0.0603369176, 0.0606627464, -0.0815231800, 0.1486389339, -0.1946210712, -0.0372415483, 0.0269194990, -0.1937365085, 0.0906293988, 0.0503427684, 0.0503278971, 0.2001654506, -0.1801522225, 0.0419180095, 0.1578094661, -0.0037205815, -0.0345633030, -0.0801014453, -0.0104420632, 0.1217197776, 0.1103863418, -0.1894428581, 0.0520878136, -0.1004308462, 0.0276933908, 0.0552809536, -0.1131219789, 0.1236320138, 0.0618739426, 0.1961426437, 0.1427689195, -0.0817000270, 0.0674391389, 0.0967779160, -0.0040636808, -0.1892023832, 0.1024222970, 0.1905990243, 0.0761097372, 0.1403602958, 0.2085951269, -0.1978327781, -0.1386842430, 0.0716426373, -0.1514661461, 0.1604115963, 0.1293117702, 0.0809597671, 0.1760691106, -0.1881445944, -0.2093095034, 0.0757643282, 0.0491489172, 0.0915529430, -0.1682676375, 0.0580054522, 0.0966015458, 0.1935326159, 0.2076593339, 0.1939801872, 0.1266939640, 0.0558563173, -0.1001905203, -0.2072352469, 0.0404997170, -0.0043535680, -0.0369075388, 0.0924699605, 0.1955164075, 0.0661515296, -0.1610964835, 0.1529740095, -0.0638748109, -0.0208785385, -0.0419577509, 0.1858939528, -0.1960482001, -0.0744788647, 0.0906780958, -0.0887935981, 0.0468099117, -0.0935182869, 0.0357558578, 0.1774282455, 0.1700491011, -0.0210153759, -0.1612454206, 0.1797387004, -0.1056237966, 0.0738513470, 0.1883957982, -0.0871931314, 0.1078689396, -0.0225079209, 0.1023400724, 0.0868689418, -0.1747629195, -0.0368673801, 0.0986522734, 0.2037334442, -0.1426269412, -0.0711795837, 0.1987050474, 0.1878060997, 0.1339875460, -0.0994506180, 0.0646777451, 0.1630476415, 0.2040054798, -0.1387091875, -0.0780089796, 0.1923853159, -0.0326879025, -0.0326911509, 0.0727188587, 0.1397978961, -0.0133277923, -0.0764702260, 0.2108619809, -0.0837472975, -0.0571934283, -0.1908024848, -0.0166734308, 0.2078124285, -0.1086236387, 0.2005369365, 0.1395209134, 0.1248455942, 0.0990054011, -0.1519040614, 0.2061503530, 0.1659146547, -0.1723120511, 0.1742579043, 0.0923238099, -0.2108805329, 0.1853901148, -0.1210635602, -0.1610381305, 0.2092482150, 0.1099981070, -0.1123044118, 0.1142407656, 0.0639456213, -0.1164770797, -0.1839908361, -0.0080247372, -0.1194459125, 0.0586822033, 0.1616915762, -0.0002340227, 0.0028121769, -0.1835221648, 0.1208060980, -0.2078100890, 0.0155630857, 0.2087851763, -0.0807315856, -0.1970693469, -0.0661643893, 0.0090000927, 0.1261626780, -0.1204295978, 0.0437651873, -0.1915783733, -0.1516554952, 0.0651507080, 0.1397578418, -0.1196567118, -0.0727079660, -0.1299479604, 0.0757280290, -0.0095487535, -0.1183249354, -0.0271632820, 0.1173901558, 0.1588713527, 0.0924242437, -0.2049111426, -0.1289208233, 0.1828841865, -0.0855947435, -0.0643326938, -0.0527134836, 0.1769357920, 0.0774650872, 0.1172084808, -0.0975405425, 0.0255076140, 0.1517721117, 0.1112448871, -0.0195154548, 0.0205666870, -0.0908947960, 0.0713352263, 0.0169820338, -0.0227927715, 0.0229648352, 0.1850242615, 0.0407651067, 0.1555531621, -0.0662065744, -0.1438441426, -0.1127760187, -0.1377274990, 0.2091112137, -0.0072878450, -0.1981091946, -0.0098019540, -0.1877576113, 0.1508529782, -0.0234492570, 0.0491071939, 0.0448753834, -0.0734052658, -0.0165965855, 0.1248821020, 0.0734958947, 0.1669113934, -0.0577529222, 0.2000485361, -0.1228384748, -0.1255454868, -0.1971827000, -0.1230085567, 0.1180750430, -0.0093547851, -0.0230401754, -0.0049679726, 0.2042787969, -0.1283455640, -0.1552554518, -0.0012578666, -0.1631354690, -0.1329830885, 0.0765587687, -0.0761249810, 0.1577172577, 0.0429348648, 0.1620784402, 0.0867160857, 0.1138004661, 0.0462742150, -0.1812913418, -0.0250388533, -0.0280440748, 0.0066502243, -0.1858594716, -0.0276051015, 0.1421964169, 0.0813965499, 0.1068108976, 0.0059656799, -0.1877613217, 0.0368406475, -0.0483537614, 0.1361891031, -0.1244090050, 0.0797127783, -0.1442604959, 0.1093797982, 0.1205075085, 0.0501118004, -0.0564092100, -0.1988244951, 0.2009366155, -0.1583352536, -0.0167462230, 0.0865212083, -0.2071752548, -0.1965620518, -0.1771773398, -0.1335911155, 0.0192012042, 0.1224520504, -0.1708127856, 0.0516567528, 0.1172842681, 0.1654311419, 0.1693318784, 0.1837634742, -0.0850449055, 0.0907040834, 0.0058849603, -0.0235214978, 0.0194096118, -0.1881018877, 0.2034058869, -0.1333278120, -0.1030089483, -0.1997814327, 0.0269460827, -0.0611050725, 0.0560825169, 0.1283653378, -0.1056428030, 0.1983804405, 0.0421571434, -0.0861751437, 0.0508041084, -0.2116856426, -0.0863313377, 0.0239236653, 0.0539779663, 0.0233431309, 0.1606138051, -0.0920646712, 0.1922321022, -0.0452404171, -0.1105760559, 0.2106334865, -0.1054409519, -0.0556141138, -0.1781117618, 0.1360196769, 0.1802893281, -0.0936985314, 0.1165351272, 0.0552333295, -0.0636999011, 0.1994484961, 0.0636085570, -0.0902845711, -0.0198717266, 0.1379822493, -0.0663420409, 0.1304030120, 0.1364517808, -0.1937849969, -0.1414416730, -0.0128650218, 0.1679543555, 0.0158417374, -0.1752573997, 0.0270776749, 0.1726594865, 0.0408231914, 0.2081383169, -0.1346630901, 0.0387143195, -0.1806079745, 0.1326352954, -0.0630900264, -0.0658071935, -0.1518288255, 0.1277736127, -0.0592663139, -0.0034587383, -0.1979734749, 0.1719286740, 0.0123056769, -0.1612582803, 0.2065779865, -0.0637299865, -0.1479045153, -0.0260363519, -0.2057416737, -0.0346208513, 0.2064574659, -0.0264683217, -0.0883198008, 0.1408757567, 0.1289643645, 0.1855285168, -0.1804073453, -0.0537951142, 0.0668195486, -0.1226902008, 0.0524666011, -0.1067594588, 0.1907449961, -0.0393671393, 0.1491917074, -0.1861257851, 0.1008849740, 0.2036682665, 0.1965058446, 0.0960520506, -0.0340944976, -0.0966986790, 0.0040719211, 0.0189812630, -0.1239445582, 0.1392132342, 0.2128939629, -0.2059993297, 0.0990686119, 0.0473121703, 0.0808303058, 0.2105965018, -0.1099056453, -0.1748321503, 0.0744347870, -0.1461552233, 0.1689332724, 0.0095289350, -0.1977693886, 0.0245501548, -0.1985494345, 0.0792918503, -0.0335043967, -0.0181492567, 0.0773982406, -0.1040530652, 0.0992784202, 0.0055586696, 0.1237892807, -0.1484608054, 0.0555051267, -0.1437306851, -0.0632395744, -0.1463977993, 0.1064682007, -0.0560435802, 0.0960682333, 0.0719676018, 0.0245992690, -0.0462644100, -0.0785900801, -0.0558394939, 0.1865259707, -0.0731129944, 0.1052559912, -0.0146709979, -0.1061939150, 0.0801361501, 0.0586482584, 0.1610437334, 0.1619606316, 0.0940272212, -0.0385499299, -0.0123391300, 0.1672401428, 0.1551659405, 0.0083943903, -0.1835677177, -0.0897399187, 0.1685397923, -0.1080016717, -0.0534483045, 0.1901096106, 0.1756649613, 0.0774500966, -0.1757703424, -0.1224443838, 0.0554220080, -0.0717803538, -0.0245188475, -0.0113737881, -0.0852353275, 0.0548189580, -0.0362652838, 0.0551236272, 0.1079287827, -0.0623466223, -0.0302456766, 0.0536195636, 0.1808533370, -0.0254818946, -0.1045151204, -0.0699811429, 0.2028083801, 0.1999809444, -0.0528029501, 0.1118593216, -0.1497626901, -0.1521579623, -0.1569841057, -0.0230683386, 0.1878478229, 0.0261472762, -0.1194706187, 0.0159520358, -0.0970126167, -0.1212493479, 0.0610946119, -0.0846420228, 0.1101294160, 0.1159366071, 0.0047756732, 0.1573970020, -0.1000526622, 0.2035552263, -0.1226661578, 0.0103985518, -0.0672702640, -0.1391693056, -0.2008733302, -0.1600718349, 0.1714603305, 0.0079642981, 0.1395266652, 0.1262914836, 0.1683962941, 0.0637745559, -0.1979252845, 0.0519728661, 0.1328639686, 0.1291106045, -0.0457876623, 0.2084420621, -0.1958028972, 0.1884651780, 0.0992593467, -0.1925799996, -0.1031548306, -0.1922521442, 0.0982190967, 0.1479490399, 0.1115373671, 0.0264677554, -0.0409521610, 0.0600257218, -0.1780522466, -0.1126354262, -0.1716191769, 0.1830831766, 0.1652213633, 0.0296512991, 0.0466898978, -0.0095825642, -0.0639636666, 0.0170907527, 0.0081479102, -0.2096172273, 0.1619519293, 0.0312604159, 0.0397034287, -0.0002698153, 0.1978329420, -0.0121454597, -0.0094526857, -0.0237273574, -0.0867079943, -0.0049833208, 0.1319896877, -0.1144113541, -0.1337009668, -0.1686180532, 0.1296547651, -0.0601793379, 0.1494078338, 0.0722094178, -0.1717362851, -0.1255957484, -0.1145360470, 0.0237909406, 0.1043739021, -0.1544477940, 0.0790340304, 0.0052815527, 0.2102528811, -0.0860441923, -0.0234307647, 0.1603132486, -0.0272525847, -0.1651003957, 0.1738359630, 0.2106792033, -0.0349970013, -0.0303519666, -0.0339978188, -0.1489456892, 0.2005601525, 0.2035722435, -0.1253810525, 0.1512997746, -0.0325741917, 0.0651094317, 0.0496669710, 0.2097713053, -0.0383381248, 0.0771798193, -0.1760617495, -0.1120572239, 0.1996681392, 0.0647082925, 0.1044281423, -0.0954377651, 0.1633413434, 0.1215559542, 0.0402642190, -0.0182905793, -0.1975707412, -0.0008970201, 0.0971205235, 0.1578942835, 0.2023544014, 0.1381759346, -0.0625620037, 0.1514950693, -0.0718256980, 0.0118870884, 0.1327362955, -0.1062853113, -0.1607363075, 0.0596870482, -0.1901426464, -0.1708513647, 0.1650001109, -0.0033199787, -0.0126292259, -0.0357793868, -0.1835055500, 0.0603061020, 0.1106692255, 0.1907842457, 0.1198039055, 0.1926206648, 0.1565317512, -0.0759528726, -0.1948379129, 0.1923233569, 0.1007493138, -0.1178143397, -0.1323398054, -0.1422309130, 0.0485868156, 0.1440326869, -0.0591032505, -0.1091527343, -0.1529152989, -0.1697878242, 0.0034380555, 0.1017098427, -0.0187026113, 0.1979413629, -0.0882942304, 0.1439684331, 0.1196214259, 0.0762318671, 0.1660355330, 0.1309429705, -0.0918098018, 0.1929387152, -0.1887128353, 0.0244574398, 0.1828245223, -0.1637505293, -0.1873486191, 0.1972919405, 0.1629608572, 0.0894708633, 0.1667929590, -0.1097143143, -0.0912832469, 0.0267206430, 0.1277072132, -0.1347484887, 0.0236548781, -0.0652003288, 0.1869010031, 0.1981157362, -0.1759383380, -0.1731866002, -0.0478647649, -0.1857491732, 0.2028805614, -0.1692140549, -0.0875881314, 0.1166424751, 0.0468351245, 0.1045762599, -0.1714083254, -0.0320059508, -0.1707411706, -0.0123952925, -0.0141666979, -0.2018545270, -0.1669420600, 0.2041317523, 0.0571704507, -0.0365011841, 0.1836222410, 0.1290774643, -0.1669084132, 0.1796984971, -0.0079360455, -0.0760267824, 0.1283863783, -0.2096923590, 0.0941240489, 0.1281087399, 0.0895640850, -0.0796302855, 0.1376777291, 0.1197003126, -0.1719098240, -0.1797896028, 0.0218136162, -0.0866396874, 0.1352225840, 0.0674757659, -0.1355925798, 0.0684938729, 0.1475597322, -0.0109589696, -0.0492037535, -0.1614322811, -0.1336855143, -0.1066660807, -0.0386074781, 0.0495053530, -0.0099364519, -0.1896707416, -0.1004594117, 0.1207754016, 0.0203200579, 0.2052307129, 0.0189252049, 0.0103460997, 0.0420710444, 0.1399002075, 0.1172848344, 0.1661094427, 0.2017557025, 0.0436914265, 0.0643244088, 0.2057434618, -0.0191677213, 0.0682848096, -0.1417491883, -0.0031131506, 0.0148516595, 0.0932514668, 0.2116248608, 0.0039765537, -0.1724414676, -0.1691936702, -0.1404601634, 0.1984391510, -0.0478304625, -0.1642811000, -0.1889132559, -0.1716609597, 0.1156466007, -0.0588394850, -0.1020036116, -0.2036255300, 0.2080315650, -0.1140736863, -0.0345724076, -0.1933063716, 0.1139229834, -0.0723220110, 0.1774840653, 0.1098777950, -0.0612724572, 0.0664094985, 0.1506472230, 0.1241123080, -0.0973965377, -0.1720945984, -0.1503418088, -0.0343479365, 0.0694606900, 0.1561326385, 0.2117401958, 0.0380726457, 0.2029472291, -0.1956074983, -0.0692329109, 0.0057167560, -0.1098129302, -0.1614622772, 0.0239131898, 0.0408787131, -0.0020718277, 0.0050014704, -0.1183702797, -0.0678333789, 0.0211721361, 0.1196450591, 0.0897656381, 0.0394547284, -0.0488569885, -0.0839669853, 0.0309076458, 0.1004701257, 0.0947154164, 0.0654139221, 0.0823945701, 0.1146301925, 0.0400183797, 0.0202626586, -0.1072974056, 0.2105867267, 0.1104008853, -0.0037561506, -0.0927053988, 0.0944980979, 0.1367858946, -0.0674200207, 0.1487843692, -0.0806787759, 0.1989254355, -0.0481174439, -0.1338374913, -0.2081667781, 0.1005316079, -0.1840391755, -0.0350880921, -0.0890243649, -0.0245165527, 0.1492657661, 0.1713838875, 0.0965442955, -0.2071402371, 0.1704485714, 0.1327006221, 0.0831274092, -0.0848695487, 0.1644728780, -0.0411594957, 0.0764342844, 0.1126935780, -0.2038380504, 0.0191847980, -0.0076710582, -0.0816929638, 0.1799655855, -0.0389810801, -0.0568400472, -0.1133250967, 0.0734277964, -0.0255433023, -0.1542529613, 0.1426350176, 0.0768330693, -0.1914806813, -0.1565151960, 0.1419842839, 0.0423746705, 0.1880020499, -0.1642536521, 0.0382031202, -0.0196413547, -0.1266663671, -0.1905800104, 0.0546536446, 0.2114781141 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w14.h b/model/AE_model/hls4ml_prj/firmware/weights/w14.h deleted file mode 100644 index bf54b3a..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w14.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [16, 32] -//Min -0.352969318628 -//Max 0.353386133909 -//Number of zeros 0 - -#ifndef W14_H_ -#define W14_H_ - -#ifndef __SYNTHESIS__ -model_default_t w14[512]; -#else -model_default_t w14[512] = {-0.2104128301, -0.0651161969, 0.0637888312, 0.2786956728, -0.1577507555, 0.2137601078, -0.1620317847, 0.2961234152, 0.3063785136, -0.3292697072, -0.2376041114, -0.1946339756, -0.1384265125, -0.2214472145, -0.2890057564, -0.1488772482, -0.0602627397, 0.0887363851, -0.0511747003, -0.2741987109, -0.2830548584, -0.1904991120, 0.3381526768, 0.0912524760, -0.1021313369, -0.0372625291, -0.0692368150, 0.1225488782, 0.1884752810, 0.0585415363, -0.3364412487, 0.0374448597, -0.1625506133, -0.2650209665, -0.0975113809, -0.2090594023, -0.3058266342, 0.1961886585, 0.0348712802, 0.0131646395, 0.1438148320, -0.3158846498, -0.2929155231, 0.1902697384, -0.0414126515, 0.1801969707, 0.2977441251, -0.2324579060, -0.2515633106, -0.2370102704, 0.0488639474, -0.2443211377, -0.0191687942, -0.3409484327, 0.2143162191, -0.0362817049, -0.2819245458, 0.3000384271, 0.0070981085, -0.0664525032, 0.1834050715, 0.1544108093, -0.1102373600, 0.1815340817, -0.1195008904, -0.2228412628, -0.3404814601, 0.2941864431, -0.2016991377, -0.0422915816, -0.3281959891, 0.1580484211, -0.2733638585, -0.2432881296, 0.0024492443, 0.0064841211, -0.0915660560, 0.2151068151, 0.1173196137, -0.2608975768, -0.3128213286, -0.0211062133, 0.0965364277, -0.2963927388, 0.3050226271, 0.0184180737, 0.1623338163, -0.2272293419, 0.2585650980, -0.2859437764, 0.0905432999, 0.0427523255, -0.3521257937, -0.1284755617, 0.1940052211, 0.3120084107, 0.1907337606, 0.0072628260, 0.0480974019, 0.3418790400, -0.1587992907, -0.2558910549, -0.3003242016, 0.2436918914, -0.1416399628, 0.0812042356, 0.1182833612, -0.3304276466, 0.2678700984, -0.3175876141, 0.1185255349, 0.2548620999, -0.0256580710, -0.2923592031, 0.3453312814, 0.0428219438, 0.2159025967, -0.2799137235, 0.0405740142, -0.2981891930, 0.2908079326, -0.1066367477, 0.2274124920, 0.1955782473, -0.2599209547, -0.3464727998, 0.2024867833, 0.1812884510, -0.2744805813, 0.1761512458, 0.2947615683, -0.0317451656, 0.2345430553, -0.2116046548, 0.2522437274, 0.1361580789, -0.2265832275, -0.1393159032, -0.0140093565, 0.1704966724, -0.2779214382, 0.2154225409, 0.1383433044, -0.2272161841, -0.0349671245, 0.1483313739, 0.1073454916, 0.1128142178, 0.2009421885, 0.1553560793, -0.2621973157, 0.0594667494, -0.3323782980, -0.1570560187, -0.2330069095, -0.0685856640, 0.1583690345, -0.1288231015, 0.0896657407, -0.2080138326, 0.0674297214, -0.3116129637, -0.2365963012, 0.0020760000, -0.2806189358, -0.1921744496, 0.1028302908, -0.0052621067, 0.3431119025, 0.0280777216, -0.3352828920, 0.1318499148, 0.0909807086, -0.2589854598, -0.0070649981, -0.1543257385, -0.3529693186, -0.0454064012, 0.3131664097, 0.0083570480, -0.2517983317, 0.0087630153, 0.2905826271, 0.3106434047, 0.3310423195, -0.2283099741, 0.2485543787, -0.1175040603, -0.1530541778, -0.3356561363, 0.1856422126, -0.0478076041, 0.2561735213, -0.2144515067, -0.1326334327, -0.0244426429, -0.2210899740, -0.1684414744, 0.1584191024, -0.1257058382, 0.1377820075, 0.1070937812, -0.2873014808, 0.2112663090, 0.1689752042, 0.3072234690, 0.1249450147, -0.2892347574, -0.1141919941, 0.1780271232, -0.2346712053, -0.1282201558, -0.1951668859, 0.0572723448, 0.3476817310, 0.3097430766, -0.0694688857, 0.0179810226, -0.0397894979, -0.2886975706, 0.0050763488, 0.0525809824, -0.0938493907, -0.2285660654, -0.3025331199, 0.2077526748, -0.3139280081, -0.1002203226, 0.2784654200, -0.1472466737, -0.2984074354, 0.2066662014, 0.2571214736, 0.3446792066, -0.2432067841, -0.1658468395, -0.2415178716, -0.2357595265, -0.1331879199, -0.1722324193, -0.3324182630, 0.1871741712, -0.2136915922, 0.2770191729, 0.2024173439, 0.2692929208, -0.1448243260, -0.3238295615, 0.0351980031, 0.3277530372, -0.2493458986, -0.0552849472, -0.3398516178, 0.3440208733, 0.0895716548, -0.0330175757, -0.3025259376, 0.2602374852, -0.1126659364, 0.1770308316, -0.1137306541, 0.2098836601, -0.0419318974, -0.2305967808, 0.3219900429, -0.3251759112, 0.1820591986, 0.2099358141, -0.3287070692, -0.0244790614, -0.1218364239, 0.2137781084, 0.0747151375, -0.0965917110, -0.0754750669, 0.0436042845, -0.3011885285, -0.0093117654, 0.1950882375, 0.0913399756, 0.0519896448, 0.2688082159, 0.2429775894, -0.2701424956, 0.0264282525, 0.1636182964, -0.0139211118, -0.1955984682, 0.1484878957, 0.0011553168, 0.1560303271, -0.3003760278, -0.2225619107, 0.3303847611, -0.1360888779, -0.1802078635, -0.2838710845, 0.3089537323, 0.3230552375, 0.2999368608, -0.3490749598, 0.2893798649, 0.0208529830, 0.0615670085, 0.2200969160, -0.1092539877, 0.2084079683, 0.2328234613, 0.3199514449, 0.1520860493, 0.2544805706, -0.2269093543, -0.3421576321, -0.2911312878, 0.2402988970, 0.1755721271, -0.1839977950, -0.1467418373, -0.1424182504, 0.1230173707, 0.1158834398, 0.0796020031, 0.2520294487, -0.2189599574, -0.0870942771, -0.2369038165, 0.2381949127, 0.2816577852, -0.2113579214, 0.3193245828, 0.2749432027, 0.3299224675, -0.0534442961, 0.0122364163, 0.1898978651, -0.0593554974, -0.1911506206, 0.1835816205, -0.0038102567, 0.2936836779, -0.2445285916, -0.1096910536, 0.2181036174, 0.2075175345, -0.2078140527, -0.0940753818, -0.3132092357, -0.1816757619, 0.3346010149, 0.0598202944, 0.0135555267, -0.3043526709, -0.3494090140, -0.2980049253, 0.0120356977, 0.2904994190, 0.1463614106, 0.1164741516, 0.1303087771, -0.1467744559, -0.2867579460, 0.3170651495, 0.2569256723, -0.0465157032, -0.1336412430, 0.1728937328, -0.2108898461, 0.2332225144, -0.2436333001, 0.3013693392, -0.2708851099, -0.3374443650, -0.3292576671, -0.1877246797, 0.0813086033, -0.2047800720, -0.2521688938, -0.3251110911, -0.1006260216, 0.2320288718, 0.2053699791, 0.1018685102, -0.0409417152, -0.0566135049, 0.3341082036, -0.2872641385, 0.3338668644, 0.0789492130, 0.1308437884, 0.0956031382, 0.2508752048, 0.1955392659, -0.0521635413, -0.2860295773, -0.1108724177, 0.2519609630, -0.1436319947, -0.2077299207, -0.1839043200, -0.2982684374, -0.0150337815, 0.0390550494, -0.2709376216, 0.2195751965, 0.2839834392, 0.2652252018, -0.3387462795, -0.0878296494, -0.1017440856, 0.2872445881, 0.2500836551, -0.0338531137, -0.1318827122, -0.3202596605, -0.3413102329, 0.2992563546, -0.3473968208, -0.1178490818, 0.0630039871, 0.1755520999, 0.3064512312, 0.2571113408, -0.0414123833, -0.0650598109, 0.1810841858, 0.0617624819, -0.1075441688, -0.1585885584, -0.1942676306, 0.3175873458, 0.1413180530, 0.0413216054, 0.1954012811, 0.0365999043, -0.1842115670, -0.1695735455, -0.2689238787, 0.0369788110, 0.1677915752, 0.0816374421, -0.1139687002, -0.1124617010, 0.2852846086, -0.1495224386, 0.1629674733, 0.2631935775, -0.1420605034, -0.2802310288, -0.1741423458, -0.3004750013, -0.3230425119, 0.1735974848, 0.2661114037, 0.3268138468, -0.2339599431, -0.0585399568, 0.0214767754, 0.1543150246, 0.0247350633, -0.1771892309, -0.0944663286, 0.1441922188, 0.2435393035, 0.1764782965, -0.3400511444, -0.1025463045, -0.0939780176, -0.1839746088, -0.0237399638, 0.0697292686, 0.2523711026, -0.1273541152, -0.2600442767, 0.0438865721, 0.0211515725, -0.1267851293, 0.3533861339, 0.2169689238, 0.3349179924, -0.2936881781, 0.1087199748, -0.2176765054, 0.1939828098, 0.2006958425, -0.0649384260, -0.0166963041, -0.1023434103, -0.2891024947, 0.1397484839, 0.0826405287, 0.2130860388, 0.0943424404, 0.0540462434, -0.2508959770, 0.2585811913, 0.1950165927, 0.0376732945, 0.1355844736, -0.2284357399, 0.1544227898, -0.0771847963, 0.0831505954, -0.2533823848, -0.0581488311, 0.2140286863, 0.3206844032, 0.2698189914, -0.2680549622, -0.2651958168, -0.1382180601, -0.1838939488, -0.0721508563}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w14.txt b/model/AE_model/hls4ml_prj/firmware/weights/w14.txt deleted file mode 100644 index f39cbd3..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w14.txt +++ /dev/null @@ -1 +0,0 @@ --0.2104128301, -0.0651161969, 0.0637888312, 0.2786956728, -0.1577507555, 0.2137601078, -0.1620317847, 0.2961234152, 0.3063785136, -0.3292697072, -0.2376041114, -0.1946339756, -0.1384265125, -0.2214472145, -0.2890057564, -0.1488772482, -0.0602627397, 0.0887363851, -0.0511747003, -0.2741987109, -0.2830548584, -0.1904991120, 0.3381526768, 0.0912524760, -0.1021313369, -0.0372625291, -0.0692368150, 0.1225488782, 0.1884752810, 0.0585415363, -0.3364412487, 0.0374448597, -0.1625506133, -0.2650209665, -0.0975113809, -0.2090594023, -0.3058266342, 0.1961886585, 0.0348712802, 0.0131646395, 0.1438148320, -0.3158846498, -0.2929155231, 0.1902697384, -0.0414126515, 0.1801969707, 0.2977441251, -0.2324579060, -0.2515633106, -0.2370102704, 0.0488639474, -0.2443211377, -0.0191687942, -0.3409484327, 0.2143162191, -0.0362817049, -0.2819245458, 0.3000384271, 0.0070981085, -0.0664525032, 0.1834050715, 0.1544108093, -0.1102373600, 0.1815340817, -0.1195008904, -0.2228412628, -0.3404814601, 0.2941864431, -0.2016991377, -0.0422915816, -0.3281959891, 0.1580484211, -0.2733638585, -0.2432881296, 0.0024492443, 0.0064841211, -0.0915660560, 0.2151068151, 0.1173196137, -0.2608975768, -0.3128213286, -0.0211062133, 0.0965364277, -0.2963927388, 0.3050226271, 0.0184180737, 0.1623338163, -0.2272293419, 0.2585650980, -0.2859437764, 0.0905432999, 0.0427523255, -0.3521257937, -0.1284755617, 0.1940052211, 0.3120084107, 0.1907337606, 0.0072628260, 0.0480974019, 0.3418790400, -0.1587992907, -0.2558910549, -0.3003242016, 0.2436918914, -0.1416399628, 0.0812042356, 0.1182833612, -0.3304276466, 0.2678700984, -0.3175876141, 0.1185255349, 0.2548620999, -0.0256580710, -0.2923592031, 0.3453312814, 0.0428219438, 0.2159025967, -0.2799137235, 0.0405740142, -0.2981891930, 0.2908079326, -0.1066367477, 0.2274124920, 0.1955782473, -0.2599209547, -0.3464727998, 0.2024867833, 0.1812884510, -0.2744805813, 0.1761512458, 0.2947615683, -0.0317451656, 0.2345430553, -0.2116046548, 0.2522437274, 0.1361580789, -0.2265832275, -0.1393159032, -0.0140093565, 0.1704966724, -0.2779214382, 0.2154225409, 0.1383433044, -0.2272161841, -0.0349671245, 0.1483313739, 0.1073454916, 0.1128142178, 0.2009421885, 0.1553560793, -0.2621973157, 0.0594667494, -0.3323782980, -0.1570560187, -0.2330069095, -0.0685856640, 0.1583690345, -0.1288231015, 0.0896657407, -0.2080138326, 0.0674297214, -0.3116129637, -0.2365963012, 0.0020760000, -0.2806189358, -0.1921744496, 0.1028302908, -0.0052621067, 0.3431119025, 0.0280777216, -0.3352828920, 0.1318499148, 0.0909807086, -0.2589854598, -0.0070649981, -0.1543257385, -0.3529693186, -0.0454064012, 0.3131664097, 0.0083570480, -0.2517983317, 0.0087630153, 0.2905826271, 0.3106434047, 0.3310423195, -0.2283099741, 0.2485543787, -0.1175040603, -0.1530541778, -0.3356561363, 0.1856422126, -0.0478076041, 0.2561735213, -0.2144515067, -0.1326334327, -0.0244426429, -0.2210899740, -0.1684414744, 0.1584191024, -0.1257058382, 0.1377820075, 0.1070937812, -0.2873014808, 0.2112663090, 0.1689752042, 0.3072234690, 0.1249450147, -0.2892347574, -0.1141919941, 0.1780271232, -0.2346712053, -0.1282201558, -0.1951668859, 0.0572723448, 0.3476817310, 0.3097430766, -0.0694688857, 0.0179810226, -0.0397894979, -0.2886975706, 0.0050763488, 0.0525809824, -0.0938493907, -0.2285660654, -0.3025331199, 0.2077526748, -0.3139280081, -0.1002203226, 0.2784654200, -0.1472466737, -0.2984074354, 0.2066662014, 0.2571214736, 0.3446792066, -0.2432067841, -0.1658468395, -0.2415178716, -0.2357595265, -0.1331879199, -0.1722324193, -0.3324182630, 0.1871741712, -0.2136915922, 0.2770191729, 0.2024173439, 0.2692929208, -0.1448243260, -0.3238295615, 0.0351980031, 0.3277530372, -0.2493458986, -0.0552849472, -0.3398516178, 0.3440208733, 0.0895716548, -0.0330175757, -0.3025259376, 0.2602374852, -0.1126659364, 0.1770308316, -0.1137306541, 0.2098836601, -0.0419318974, -0.2305967808, 0.3219900429, -0.3251759112, 0.1820591986, 0.2099358141, -0.3287070692, -0.0244790614, -0.1218364239, 0.2137781084, 0.0747151375, -0.0965917110, -0.0754750669, 0.0436042845, -0.3011885285, -0.0093117654, 0.1950882375, 0.0913399756, 0.0519896448, 0.2688082159, 0.2429775894, -0.2701424956, 0.0264282525, 0.1636182964, -0.0139211118, -0.1955984682, 0.1484878957, 0.0011553168, 0.1560303271, -0.3003760278, -0.2225619107, 0.3303847611, -0.1360888779, -0.1802078635, -0.2838710845, 0.3089537323, 0.3230552375, 0.2999368608, -0.3490749598, 0.2893798649, 0.0208529830, 0.0615670085, 0.2200969160, -0.1092539877, 0.2084079683, 0.2328234613, 0.3199514449, 0.1520860493, 0.2544805706, -0.2269093543, -0.3421576321, -0.2911312878, 0.2402988970, 0.1755721271, -0.1839977950, -0.1467418373, -0.1424182504, 0.1230173707, 0.1158834398, 0.0796020031, 0.2520294487, -0.2189599574, -0.0870942771, -0.2369038165, 0.2381949127, 0.2816577852, -0.2113579214, 0.3193245828, 0.2749432027, 0.3299224675, -0.0534442961, 0.0122364163, 0.1898978651, -0.0593554974, -0.1911506206, 0.1835816205, -0.0038102567, 0.2936836779, -0.2445285916, -0.1096910536, 0.2181036174, 0.2075175345, -0.2078140527, -0.0940753818, -0.3132092357, -0.1816757619, 0.3346010149, 0.0598202944, 0.0135555267, -0.3043526709, -0.3494090140, -0.2980049253, 0.0120356977, 0.2904994190, 0.1463614106, 0.1164741516, 0.1303087771, -0.1467744559, -0.2867579460, 0.3170651495, 0.2569256723, -0.0465157032, -0.1336412430, 0.1728937328, -0.2108898461, 0.2332225144, -0.2436333001, 0.3013693392, -0.2708851099, -0.3374443650, -0.3292576671, -0.1877246797, 0.0813086033, -0.2047800720, -0.2521688938, -0.3251110911, -0.1006260216, 0.2320288718, 0.2053699791, 0.1018685102, -0.0409417152, -0.0566135049, 0.3341082036, -0.2872641385, 0.3338668644, 0.0789492130, 0.1308437884, 0.0956031382, 0.2508752048, 0.1955392659, -0.0521635413, -0.2860295773, -0.1108724177, 0.2519609630, -0.1436319947, -0.2077299207, -0.1839043200, -0.2982684374, -0.0150337815, 0.0390550494, -0.2709376216, 0.2195751965, 0.2839834392, 0.2652252018, -0.3387462795, -0.0878296494, -0.1017440856, 0.2872445881, 0.2500836551, -0.0338531137, -0.1318827122, -0.3202596605, -0.3413102329, 0.2992563546, -0.3473968208, -0.1178490818, 0.0630039871, 0.1755520999, 0.3064512312, 0.2571113408, -0.0414123833, -0.0650598109, 0.1810841858, 0.0617624819, -0.1075441688, -0.1585885584, -0.1942676306, 0.3175873458, 0.1413180530, 0.0413216054, 0.1954012811, 0.0365999043, -0.1842115670, -0.1695735455, -0.2689238787, 0.0369788110, 0.1677915752, 0.0816374421, -0.1139687002, -0.1124617010, 0.2852846086, -0.1495224386, 0.1629674733, 0.2631935775, -0.1420605034, -0.2802310288, -0.1741423458, -0.3004750013, -0.3230425119, 0.1735974848, 0.2661114037, 0.3268138468, -0.2339599431, -0.0585399568, 0.0214767754, 0.1543150246, 0.0247350633, -0.1771892309, -0.0944663286, 0.1441922188, 0.2435393035, 0.1764782965, -0.3400511444, -0.1025463045, -0.0939780176, -0.1839746088, -0.0237399638, 0.0697292686, 0.2523711026, -0.1273541152, -0.2600442767, 0.0438865721, 0.0211515725, -0.1267851293, 0.3533861339, 0.2169689238, 0.3349179924, -0.2936881781, 0.1087199748, -0.2176765054, 0.1939828098, 0.2006958425, -0.0649384260, -0.0166963041, -0.1023434103, -0.2891024947, 0.1397484839, 0.0826405287, 0.2130860388, 0.0943424404, 0.0540462434, -0.2508959770, 0.2585811913, 0.1950165927, 0.0376732945, 0.1355844736, -0.2284357399, 0.1544227898, -0.0771847963, 0.0831505954, -0.2533823848, -0.0581488311, 0.2140286863, 0.3206844032, 0.2698189914, -0.2680549622, -0.2651958168, -0.1382180601, -0.1838939488, -0.0721508563 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w16.h b/model/AE_model/hls4ml_prj/firmware/weights/w16.h deleted file mode 100644 index be946ae..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w16.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [32, 100] -//Min -0.213191926479 -//Max 0.213063180447 -//Number of zeros 0 - -#ifndef W16_H_ -#define W16_H_ - -#ifndef __SYNTHESIS__ -model_default_t w16[3200]; -#else -model_default_t w16[3200] = {-0.0130273253, -0.1259363294, 0.0945610702, -0.0644461960, 0.1832793951, -0.0208553076, -0.1577622890, 0.0114846081, 0.0462474227, -0.1888662875, 0.1281007528, 0.1329291463, -0.1587361991, -0.1352097839, 0.0944213569, 0.0784721076, -0.1558004022, 0.1288587451, -0.2122411281, 0.0272939205, 0.0659274757, -0.2089752853, -0.1386389434, -0.0837319940, -0.1696569324, 0.0262442082, 0.1631107330, -0.1182218567, 0.1800297797, -0.1726104319, -0.0111823082, -0.0128869861, -0.1045312807, -0.2043615580, -0.0798180550, 0.0643519163, -0.1027161554, -0.0397471637, 0.0978991687, -0.1402687877, 0.1218408048, -0.1134288982, -0.1261436641, 0.0335370302, 0.1479334533, -0.0108215213, 0.1092103422, 0.2026947737, -0.0346155167, -0.1371692121, 0.1905909181, -0.1643185169, 0.0096005499, 0.0794419646, 0.1910420954, -0.1008122340, -0.0858196318, -0.0960322395, -0.0611624718, -0.1540560871, -0.0846777558, 0.0128069818, -0.0647849888, -0.1241305545, 0.0749971569, -0.1083801538, -0.0463754684, 0.0780991018, -0.0549549758, 0.0051411539, 0.2104826868, 0.0234862119, 0.0375915766, -0.0367360860, -0.1087446660, 0.2111480236, -0.1739501804, 0.0233765692, 0.1652782559, 0.1255599260, -0.1299285442, -0.1814702153, 0.1860595942, -0.0244893581, -0.1234823540, 0.1627963185, 0.1788330972, 0.1180432737, 0.0764050186, -0.2097494900, -0.0992160887, 0.1479691863, -0.1603781432, 0.0174055099, 0.1682570577, -0.0068627894, 0.0234803259, -0.1371489763, -0.1290633380, 0.2020197213, 0.1064198017, -0.1345657110, 0.1129842699, 0.2006976604, 0.1649823785, 0.1847754717, -0.0348276794, 0.1845819056, -0.0747617930, 0.0267496705, -0.0231935233, -0.1705366671, 0.0892340541, -0.1630261838, -0.0064330697, -0.0180535465, 0.1774684489, -0.0118700117, 0.1112754345, -0.1261567175, -0.1455314755, 0.1447922885, 0.0541168749, -0.0653234869, -0.0965587944, 0.0156036466, 0.0802645087, 0.0841549635, 0.0812481344, -0.1411535442, 0.1254012883, -0.0455906391, -0.0306715816, -0.0808172971, 0.1147423089, 0.0619878173, -0.1582829952, 0.1947368681, 0.0744240284, 0.2098235190, 0.0004032403, 0.0944982171, -0.0592246801, 0.0990560055, -0.1866515279, -0.0556830317, 0.1125717759, 0.0700600147, -0.1412425637, 0.0156001896, 0.0776591599, -0.0046227276, -0.1678069979, 0.0324525982, 0.1702670753, -0.2018597126, 0.1013407707, 0.0099410713, 0.0017249435, -0.0457270741, -0.0991436541, -0.2034626603, -0.0888631791, 0.0707303286, 0.2062967122, 0.1711236238, -0.1963857710, -0.1301012635, 0.0640211105, -0.0077804029, 0.0104616880, -0.0048618913, 0.2108360231, -0.1978262216, 0.0269224495, 0.0039434731, 0.0548866689, -0.0827367753, 0.1085537970, 0.1956063807, -0.1081783026, 0.1494415104, 0.1101001203, -0.1612143219, 0.1067217290, -0.0207707137, -0.1488733590, -0.0303766131, -0.0802035034, -0.1339956224, -0.1519602239, 0.0016708672, -0.1595647037, 0.1969965398, 0.2075348794, 0.1518881917, 0.0671034455, -0.1564162225, -0.1543469429, -0.1770093888, 0.0682467222, -0.1632902026, -0.1717197597, 0.0498220026, 0.1095688343, -0.0015616864, -0.1720746160, 0.1646409333, -0.1605213434, 0.1961368918, 0.0093684644, -0.0201760978, 0.2055852711, 0.1918219030, -0.0060595125, -0.1528907865, 0.1307045221, 0.1481581628, 0.1970739663, 0.1757183969, -0.1381469071, 0.1237665117, 0.0018544197, 0.0833833516, -0.1581424922, -0.1709466279, -0.0158225298, 0.0906814039, 0.0412386954, 0.1893225014, 0.1991872787, -0.1016348824, -0.2098781019, -0.1076380759, 0.2011736035, 0.1551723778, 0.0359183550, 0.0616644621, -0.2027701885, 0.2111682296, -0.1193955913, -0.0354953408, -0.0443158448, 0.0606944561, 0.1446566880, 0.0543707907, 0.1525784731, -0.1012778431, -0.0449997336, -0.0272941738, 0.0104666650, -0.2114956975, -0.1726112962, 0.0984360874, 0.0880922377, 0.0589379370, -0.1279652417, 0.0765250623, 0.1821038425, 0.1174420118, -0.0163721591, 0.1228275001, -0.1220860258, -0.1425816417, -0.0332352966, 0.0324501693, 0.1842880249, -0.1939656585, 0.1910464168, -0.1111146137, 0.0026402175, 0.1187394559, -0.0988348573, -0.1217542514, -0.0492030978, 0.0797930956, -0.0714403391, -0.1571806669, 0.0695837438, 0.1016166210, -0.0704020709, -0.0949677825, -0.0479588509, -0.1081922874, 0.0105456114, -0.0054046065, -0.0465161651, -0.1691238731, 0.2052527666, 0.1894890070, 0.0782389343, 0.0852125585, -0.1593517214, 0.1442769170, 0.1072202325, 0.0686706603, -0.0415009856, -0.1497082710, 0.0498762131, -0.2106196284, 0.0765061677, -0.1385392547, 0.1746212542, -0.0992993489, 0.1934341788, 0.0618958473, 0.1375975311, -0.0717558563, 0.2000515461, -0.0323338062, -0.1225704998, -0.0116799474, -0.0371402949, -0.1208240986, 0.1519456506, -0.0316224843, 0.1335759759, -0.2024369538, -0.1641412675, -0.1927401721, 0.0306266546, 0.0828153193, 0.1659827828, 0.0384555459, 0.1457235515, -0.0497836322, 0.1769310236, -0.2116001546, -0.0031991005, -0.0807842463, 0.0081038922, -0.0225998759, -0.1627896130, 0.0764707923, 0.1039808393, -0.0406423360, -0.0554921627, 0.1342954934, 0.0338096321, 0.1133666337, 0.0632500947, 0.1918676496, 0.1823641956, -0.1334682703, -0.1244893149, 0.1369327009, 0.0636276603, 0.1408673227, -0.0425146967, -0.2027536780, -0.0305647403, 0.1510687470, -0.0805604905, 0.0702908039, -0.1553621888, -0.0088961422, 0.0790726840, -0.0023701489, 0.1248674989, -0.1758075953, 0.0428200960, 0.0787388682, 0.0355882198, 0.0636335611, -0.1202259660, 0.0270224810, 0.1517257392, -0.1454291940, -0.0783185363, -0.0340940356, -0.2012153268, -0.1551640034, 0.0292676836, -0.1072629914, -0.0488430113, 0.0402400792, -0.1803735942, -0.1590253264, -0.1700740159, -0.0305492282, 0.1598092020, -0.1394096911, -0.1372441947, 0.0859484375, 0.1609318554, -0.1009811461, -0.0802806169, -0.1897195280, -0.0607282221, -0.1316629350, -0.1219133064, -0.2082910538, -0.1972658038, -0.1844384521, 0.1265234351, -0.1628829986, -0.2030221075, 0.1910839975, -0.0368629098, -0.0243633538, 0.0063986033, -0.1167256460, 0.0628578961, -0.1803720146, -0.0783854425, 0.0121531934, -0.1639599055, -0.1593689471, 0.1314008236, -0.0459068567, -0.0907423571, 0.1804122329, 0.2122233510, 0.1151688397, 0.0911640525, 0.0348865390, 0.1300783455, -0.0236830264, 0.0023433119, 0.1851803660, 0.1672433913, 0.0325655490, 0.0911865532, -0.1637508869, -0.1168597341, 0.2057717144, 0.0455974638, 0.0204673558, -0.1965441108, 0.0855367482, -0.0623529255, 0.1629964113, -0.0489413142, 0.0882367492, 0.0340018868, -0.1326198429, -0.1001866534, -0.1245983988, 0.1413900256, 0.1874953806, -0.0106244385, 0.2050077319, -0.1698612273, -0.1506629139, -0.1031069979, -0.0526490808, 0.0260028094, 0.1677609980, 0.0581763983, -0.1462530196, -0.1360576898, -0.1503466368, 0.1414406896, 0.1622020006, -0.0680478364, 0.1303669214, -0.1221360937, 0.1745809913, 0.0342087150, -0.1642162502, 0.0834338665, -0.1282218397, 0.1373473406, -0.0401223451, 0.0739849508, 0.1701364219, 0.1990130246, -0.1143041030, -0.0163943768, 0.2096578479, -0.1905419827, -0.1134785041, 0.0192365348, 0.0860688388, -0.1228942946, 0.1085300148, -0.0134354979, -0.1682397127, 0.1570128798, 0.1703217030, -0.1215950996, 0.1636342406, -0.0334042609, -0.0700438619, -0.0970657319, -0.0906256959, 0.1340383887, -0.1851412952, -0.0015206039, 0.0290814936, -0.0646947622, 0.0061229467, 0.0407950282, -0.0902684033, 0.1242007911, -0.0269559473, -0.0076397955, -0.2071086168, 0.1732262969, -0.0320551991, -0.0571409166, 0.0321718603, 0.1998512745, 0.0916839540, -0.0651914328, 0.1697616577, -0.0198900700, -0.0171448886, -0.1235098019, -0.1281911433, -0.1592148840, 0.0836006999, -0.1731902510, 0.0908051729, -0.0268761814, -0.1512360871, -0.2000906318, -0.1091002822, 0.0626733303, -0.1795879006, 0.1988547742, 0.0267653167, -0.0725796670, -0.2008852810, -0.1168303564, 0.1781799793, 0.1904968023, 0.1290690303, -0.0236298144, -0.0400479287, -0.1034653038, 0.1879202127, -0.0822001994, 0.0808651149, -0.1721311361, 0.1181168854, 0.1653339565, 0.0717893541, 0.0279274285, -0.1693844795, 0.1900699735, 0.0000168830, 0.1852777302, 0.1035282314, 0.1743865013, -0.1719912589, -0.1293298006, 0.1979320943, 0.0311407000, 0.0762527585, -0.1054227054, -0.1804566532, -0.1717367470, -0.0783862472, -0.0735121667, 0.1575010717, 0.1610148549, -0.1397852898, -0.0534511954, -0.1419837177, -0.1520278305, -0.0357308537, 0.1778426766, 0.2022635639, 0.1641831994, -0.1320675611, 0.1779336035, -0.0851632953, -0.1922511756, 0.1587883532, 0.0165648609, -0.0097687542, 0.1468048990, -0.1659059674, 0.1205895543, -0.0662048459, -0.1921826005, 0.0132936239, -0.1969076991, 0.1992416680, 0.1337226033, -0.1967195719, -0.2016975135, -0.1981110722, 0.1564672589, 0.0506201088, -0.2086362988, -0.1201700047, 0.0168281645, -0.1158882529, -0.1751039326, -0.1424258947, 0.0607258379, 0.0809723735, -0.1056843325, -0.1978037506, -0.0771079063, -0.0868115872, -0.0388507992, 0.1239619553, 0.1218158007, -0.1637382209, 0.0826045573, -0.0083401054, 0.0766014159, 0.0513367951, 0.0186986476, -0.1079499200, 0.0341885388, -0.1341587454, 0.0070068985, -0.0510378480, 0.1157514751, 0.0924983621, 0.1735253334, 0.1024294198, -0.2024069577, 0.1459152102, -0.1794299632, 0.1391270757, -0.0433251560, -0.1144386530, -0.1725994051, 0.0651500523, -0.0469828993, 0.1333318949, -0.0614170730, -0.1486979425, 0.1749379337, -0.0312749445, -0.1020108759, -0.1791891754, 0.1619752049, 0.1529638469, 0.0497876108, -0.0993031636, -0.0895941854, 0.0647700429, 0.0605212450, -0.1583527923, 0.0356428623, 0.1551423371, 0.0297968388, 0.0220008790, 0.1167052090, -0.0531750321, -0.0138240457, 0.1592967808, 0.0496267378, 0.2091331780, -0.1480971277, -0.1682489216, 0.1384595037, 0.0888846815, -0.0842253119, -0.1167098358, 0.1488567889, 0.2066698968, -0.0304312110, -0.1703116000, 0.0639329553, 0.0541225374, -0.1226595566, -0.0579297096, -0.1718170643, -0.1047814190, 0.1794770956, -0.1659982800, 0.0023263842, -0.0723258704, 0.1574643552, -0.0623307228, 0.0114367753, 0.1690727770, -0.2131630033, 0.0294306427, -0.1702712774, -0.1688735783, -0.1018458307, -0.1143009514, -0.0047163516, 0.0957580507, -0.0802835226, 0.0648097396, -0.0078999996, -0.1538537294, -0.2005685568, 0.1738888323, 0.0263175517, 0.1479609907, -0.0688941628, 0.1260773838, 0.0928246081, -0.1632209718, 0.1544763148, 0.1699717343, -0.0160051137, -0.1773654222, -0.0445157737, -0.1644815356, -0.1299230456, -0.0888913423, -0.0018408000, 0.0861804187, -0.1999694109, 0.1855406761, -0.1262204200, -0.1767251939, -0.2082639039, -0.0643157661, 0.1059206426, 0.0088308752, 0.0215080827, -0.0907995403, 0.1237658262, 0.0732398033, 0.2101181149, -0.0685326010, 0.0550488234, -0.1716340184, 0.1942046583, 0.0304473639, 0.2130631804, 0.1521381438, -0.0104703307, 0.0254605860, -0.0609222949, -0.0393703431, -0.0966759622, 0.0641950965, -0.0440582931, 0.1723761857, -0.1971201748, 0.0044940263, -0.0772200376, -0.1752294451, 0.2021924853, 0.0265952498, 0.0746521652, -0.0911174864, -0.1643462777, 0.1444889903, -0.1840594560, 0.0733265281, -0.1415145099, 0.1180490255, -0.1164425164, 0.0999458730, -0.0610869825, -0.0340544432, 0.1973402798, -0.1915016174, 0.2029054165, -0.0103540272, -0.1594736576, -0.1525272429, -0.0188208371, -0.0790094435, 0.1923677325, -0.0339856148, -0.0228689164, -0.0859591067, 0.0814860761, 0.0550598502, 0.1838219166, -0.0192521960, 0.1407603621, -0.0096959174, -0.0932167545, 0.1781721115, -0.0855361372, 0.1891888678, -0.0069375187, 0.1952764690, 0.1129395366, -0.1079180986, -0.1885606945, -0.0205569714, 0.1095406711, -0.1541737169, 0.0263331085, -0.1461997032, 0.1600303650, -0.1034623086, 0.0812811852, 0.0963799059, 0.0490098298, -0.0512192100, 0.0336747766, -0.0803432912, -0.1928579956, 0.0009355396, -0.1906580329, 0.1890609264, 0.0538485348, 0.0304931104, -0.1823762357, 0.0240671188, -0.1079957187, -0.0150481611, -0.0227957815, 0.0470040441, 0.0693390965, -0.0566840470, -0.0704285055, -0.1234320328, 0.0321579278, 0.1299918294, -0.0880828798, 0.0265530050, 0.0247528702, 0.1927776337, -0.1681027412, 0.0949314535, -0.0540727675, -0.2020932734, 0.1341821849, 0.2118407488, -0.2032287419, -0.1367629170, -0.0947465152, 0.1430233717, -0.2115065157, -0.0912154391, 0.1946260035, 0.1944942474, -0.0088078976, 0.1785105765, 0.1199140549, 0.1413906813, -0.1986526847, 0.1076044738, -0.0413151979, -0.0772407800, 0.1983164847, -0.1040216982, 0.1793057323, 0.1895011663, -0.0773698837, 0.0715141594, 0.1469281614, -0.1726556122, -0.1201167330, 0.0367779583, -0.1818589270, 0.0927172005, -0.0280686319, -0.0086932778, 0.0841871798, 0.0758739412, -0.1718271673, 0.0194304138, -0.2104951292, -0.0464355499, 0.0466483235, -0.1867761612, -0.0607739687, -0.0055530816, 0.2062681317, -0.0899071023, -0.1466156542, -0.1700449288, -0.0352381468, -0.1439867318, 0.0279891789, 0.0052996427, -0.1774032861, -0.0753418207, -0.0649657398, 0.0333490521, 0.1913325191, 0.1162198186, -0.1369870305, 0.1173079014, 0.1992448568, -0.0396678150, -0.0303589255, -0.0619280785, -0.0192707032, -0.0790151358, -0.1448483169, -0.0779868662, 0.0969208181, 0.1015408039, -0.0625919849, -0.1346160173, 0.1641981602, 0.0319124758, 0.0982068777, 0.1008815169, -0.0978270769, -0.0016372651, -0.0054634660, 0.1999173164, -0.2003428638, -0.1025240645, -0.0592647344, -0.1252372414, -0.0870438963, 0.1773294210, 0.0137821138, -0.0117748529, 0.1342442334, 0.1442306638, -0.0628429949, -0.0721761286, 0.0534745157, 0.0238779634, 0.1552363932, 0.1699821651, -0.0442073196, 0.1695192456, 0.0530515015, 0.0595406592, -0.1705650389, -0.0639193952, -0.1489825994, 0.0764563382, 0.1519193053, -0.1043368578, -0.0463358760, -0.0165051371, -0.1310031563, 0.2021290660, -0.0560600460, 0.1796547771, 0.1029445529, -0.1228640974, -0.1941508800, -0.0907981694, -0.0546313375, 0.0337099135, -0.0008449703, -0.1432957351, 0.0558494031, -0.0492122471, 0.1636962295, -0.1825852990, 0.1001596153, 0.1829636991, 0.0331404507, -0.1169753745, -0.1455797553, 0.0733731389, 0.0429403484, -0.1705754548, 0.0322585851, 0.1478659511, -0.0472624153, -0.0188592225, 0.1383612156, 0.0260158777, 0.0440246463, 0.1482222080, -0.0436652154, 0.1809160113, 0.1424434483, -0.0133117288, 0.1041171253, -0.0775254816, 0.0607286096, -0.0155260712, 0.1529510319, -0.2055692524, 0.0051077604, -0.1450271308, 0.0847360492, -0.1129557639, -0.0156958997, 0.0518609583, 0.0307663828, 0.1660754383, -0.1019806340, 0.1176193058, 0.1917870939, 0.1363770664, 0.0379193127, -0.0729095191, -0.0966173038, -0.1248160079, 0.2000123560, 0.0094743967, -0.0882367939, 0.1015456319, -0.0674209893, -0.1662264615, -0.1839380711, -0.1320059597, 0.1887626946, 0.2035280466, -0.0533521324, 0.0082952678, -0.1028251871, 0.1246227026, 0.0488411188, 0.1782095134, 0.0781773329, -0.1430292130, 0.1122246981, -0.1704412699, -0.1757664233, -0.1247237027, 0.0092140883, -0.1822572351, -0.0997265354, -0.1050046682, 0.0886016190, -0.0296980143, 0.1983782947, 0.1298699975, 0.0795823932, -0.1162241474, 0.1733252108, 0.0104044974, 0.2047517002, 0.0917622745, -0.0174271017, -0.0020326823, -0.1344762444, -0.0506389737, -0.2100296766, 0.1877582073, -0.0410911739, -0.0063932687, -0.0494657904, 0.1441004872, -0.1969064772, 0.0923915207, -0.1293616295, -0.0393955559, -0.0578577369, 0.1438804269, 0.0814321339, 0.0784842372, -0.1527344286, -0.0276184231, 0.1820350587, 0.0567962825, -0.1889699250, 0.0160314888, -0.1600189805, -0.1148333549, -0.1550061703, 0.0448240042, 0.1842555702, -0.1586228460, 0.0745503008, 0.0607309639, -0.1876632124, 0.1188407838, -0.0673445314, 0.0973199308, -0.0874732137, -0.0405899882, 0.1194924712, 0.1050751805, -0.0377250016, -0.0332672745, -0.1674756259, -0.1423026919, -0.0350551009, -0.0985023156, -0.0951841697, 0.0006961823, 0.0258001387, -0.0484638661, -0.2063206434, 0.1210769415, 0.1295931041, -0.0792551488, -0.1073084325, 0.0022826195, -0.0591862053, 0.1678128541, 0.2003252804, 0.0493347645, 0.0721547604, 0.0598349571, -0.0255390257, 0.0196670294, -0.0521317273, -0.1928784251, 0.0355230570, 0.0934202969, -0.0761632621, -0.1314253211, -0.1957649738, 0.0752701163, 0.0782026350, -0.0987959206, 0.2125548720, 0.1511770189, -0.0734881759, 0.0920494199, 0.1625028849, -0.0768847018, 0.1584999859, -0.1727127433, -0.1644728929, -0.1382983327, -0.1660568416, -0.1793116778, 0.0099412203, -0.0791091621, -0.0846506059, 0.0790362656, -0.0133007020, -0.1654711068, 0.0573849678, -0.1701870561, 0.1805684268, 0.0581678450, 0.0920302570, -0.1281255633, -0.0639522821, -0.1546281874, 0.1244523227, 0.0743416250, 0.0706484020, 0.1799728274, 0.1064555347, 0.2091509700, 0.1711511612, -0.0555743128, -0.1664301902, -0.0028101355, 0.0690938830, -0.1037319154, -0.0864460170, -0.0368000269, 0.0399753749, -0.1528497636, -0.1097660661, 0.1010111272, 0.0987169147, 0.0314895064, -0.0543241203, -0.0520908535, -0.0086442679, 0.0969336629, -0.0699095726, -0.1331691146, -0.2069860697, 0.1236446500, -0.1357996762, -0.1200416535, -0.0506703854, -0.1990199387, -0.1748924255, 0.1290726364, 0.0294344574, 0.1476340592, 0.1509452462, -0.0244340599, -0.1539846659, 0.1124024093, 0.0214278102, 0.1704240441, -0.0724699795, -0.1785931885, -0.1700597256, 0.1837204993, -0.0194244087, -0.1878972501, 0.2055566907, -0.1611421853, 0.1714851260, -0.2007489949, 0.1520946324, -0.1191827133, 0.1413890123, -0.1775853038, -0.0248494446, 0.0703947544, 0.0560485721, -0.1586514711, 0.0541211367, 0.0367946327, -0.0246199518, -0.1869306862, 0.0217935890, -0.0829221010, 0.0873340368, -0.1758350432, 0.1454812586, -0.0828677118, -0.1690293252, -0.2004337013, 0.1523751616, 0.0680314004, -0.0973403752, -0.0847362131, -0.0708044469, 0.0425238609, -0.0822722763, -0.1330907941, -0.0131355971, 0.0557457209, -0.1308217943, 0.0857084095, -0.0758208036, -0.1346733123, -0.1555400491, -0.0969168991, 0.0320490599, -0.1431545615, 0.1276002228, -0.0794734806, 0.2112722397, -0.2054769397, 0.1153905094, 0.0442796946, 0.1386967003, -0.2096072733, 0.1811663508, 0.1794033349, -0.0582896024, -0.0159388334, -0.1149303913, -0.0124904066, -0.0947031081, 0.1242024899, 0.0512652695, 0.0718409419, -0.1800667346, -0.1936214268, 0.1672570705, -0.1238474771, 0.2030343115, -0.0088793188, 0.0576428175, 0.1919571757, 0.1780738533, 0.0743105710, 0.0483388305, -0.1933601499, 0.0573388040, 0.0927100182, 0.0190719962, 0.1921852827, -0.1414444596, -0.0606168956, 0.0225313604, 0.0726953149, -0.0708997101, -0.1291381121, 0.0971594155, -0.0985634699, 0.1121488810, -0.0717573315, -0.0415566415, -0.0751338750, 0.0083053857, 0.1715459824, 0.2018745542, -0.0923625901, -0.0133760273, 0.1272982359, -0.0956774876, -0.1240583733, -0.2114854306, 0.0965881348, -0.0672399253, -0.1880328655, 0.1312022507, -0.1394779086, 0.1825407147, 0.0174094737, 0.1769882441, -0.0735728145, 0.1314514875, -0.0022834241, -0.0012988895, -0.1842794418, -0.1392400265, 0.0068610162, -0.0002130866, 0.1254684627, -0.1400572360, -0.0490175188, -0.1366832256, -0.0835879445, 0.0948438644, -0.1165343672, 0.1079588830, -0.1742309630, 0.0942076147, -0.2069736123, 0.1206722558, -0.1774893850, 0.0393536687, 0.0133828372, 0.0662358105, -0.1072077379, 0.0789229870, 0.0019953251, -0.0018918812, 0.1487488747, 0.0653204024, 0.0895190537, -0.1732241511, -0.1341161430, 0.1755096316, -0.1138452515, -0.0368136466, -0.0363892615, 0.0309521258, -0.0052079856, 0.0354398340, -0.1062960327, 0.1332124174, -0.1448436379, -0.2075458765, -0.1759052426, -0.1594075263, -0.0318089277, -0.1131876037, 0.1570088565, -0.1197258383, 0.0138314217, -0.1105028093, -0.0295597017, 0.1378022134, -0.1440986097, 0.0703257322, 0.0650744140, -0.0353616029, -0.0718922764, 0.1725155115, 0.0594631732, 0.1383387446, 0.1432417035, -0.1360167265, -0.1198626310, 0.1673899889, -0.1245760322, 0.1036848426, 0.0674479604, -0.1988779157, -0.0741225481, 0.1518616080, 0.1727854311, 0.2025708854, -0.1955710053, 0.1098783612, 0.1568675935, -0.1278287619, -0.0991523936, -0.1556450725, 0.1036491096, 0.0829957724, 0.1966727078, -0.0123555511, 0.1867456138, 0.1836900115, 0.1205491126, 0.1161455512, 0.1055618823, 0.0448076427, -0.2055694014, 0.1347579062, 0.0496198237, 0.0014238805, -0.1270311177, -0.1212837622, -0.1498177499, 0.0584974885, 0.2008564472, -0.1326838881, -0.1859655082, -0.0276795775, 0.0559844673, -0.1822595298, -0.0514723510, -0.1829582453, 0.1997265816, 0.0494521260, -0.0760574341, 0.1203515232, 0.0950507522, 0.0931355357, -0.1741347015, 0.1319496334, -0.0033025891, 0.1753038168, -0.1310523152, -0.0321434438, 0.0919113159, -0.1145440266, 0.1372021139, -0.1949167550, -0.1191260889, -0.1971220076, -0.1756067574, -0.1678233147, -0.2006524801, 0.1193429232, 0.2098030150, -0.0447238684, -0.2036878467, -0.0867692530, -0.1309165955, 0.0847793221, -0.1098388508, 0.1825619638, -0.1476746202, 0.2038953006, -0.1721340865, 0.0535374582, -0.1794906557, 0.0754552782, 0.1397316456, 0.1095485091, 0.1933746934, -0.1138690412, 0.1855984032, 0.0389611721, 0.0381172001, -0.0462874323, -0.1968904734, 0.1458078921, -0.0722205937, 0.2060584426, -0.1714447141, 0.0223436356, 0.1825688779, 0.0452565849, 0.1058931053, -0.2038344443, 0.1905703843, -0.1854292452, 0.1800690591, -0.0769351721, 0.1531750858, 0.0848983228, -0.1336221695, 0.1280547082, 0.1484613121, -0.0277594775, -0.1551034600, 0.0823943317, 0.0643174350, -0.0788183063, 0.0762106776, 0.0242073983, 0.0263604075, 0.1125132143, -0.1060078219, -0.1991036981, 0.1918284595, 0.0840535462, -0.1217572540, 0.0472959578, -0.0989014953, 0.2087621093, -0.1823205203, -0.0105943531, 0.0384185910, -0.1028940678, 0.1185675561, 0.0462585092, -0.0512450784, 0.0990857184, 0.2116090953, -0.0509551466, -0.1323211491, 0.1672795713, 0.2000471354, 0.0863650441, 0.0256348997, 0.1485285163, 0.0510468483, -0.0337763876, -0.0341346562, 0.1407789886, -0.0521683246, 0.1687902808, -0.0672319382, 0.1154437959, -0.0787539631, -0.1798828244, 0.1729774177, 0.0052112937, 0.0594650805, 0.0338179171, 0.0396455526, 0.0651315451, 0.0241717249, 0.0589820743, -0.1591632813, 0.1442280114, -0.2010892630, 0.0796580911, -0.1434063315, -0.1692698151, 0.2002624571, 0.1403183043, 0.0042257905, 0.0713099539, 0.0852792859, 0.2020341158, 0.0972422063, 0.1421691179, -0.1759033650, -0.1923001707, -0.1595743597, -0.1895710528, 0.2113615572, 0.1198105216, 0.1897158623, 0.1519897580, 0.1169688702, 0.0630189180, 0.0186039954, 0.0013304949, 0.1581035554, 0.1829706430, 0.1218507886, -0.0516599715, -0.1732880026, 0.1261597276, 0.0492627323, -0.0481002182, 0.0445055366, 0.1528100669, -0.0859618038, 0.1968157589, -0.1851369143, 0.2037501633, 0.1451233029, -0.1401752084, 0.0779571831, 0.0972661674, -0.0483306795, -0.0958286598, -0.1751645356, 0.0244353861, 0.1761728227, 0.0009850562, -0.0998479649, 0.0216421187, 0.1283885539, -0.1615431905, 0.1778119206, -0.2018036395, 0.0518199205, 0.1242860556, 0.0953228772, -0.0126432031, 0.1637348831, -0.0028868914, 0.1344926059, 0.0586344898, 0.1754533648, -0.2111395746, -0.0661977828, -0.1522785276, 0.0873704851, -0.0004187524, 0.1675336361, 0.1108632386, 0.0430812538, -0.1502431035, 0.1938326657, -0.1104866415, -0.0683636963, -0.0831161290, 0.0355570614, -0.2026015371, 0.0559004545, 0.0382340848, 0.0799589157, -0.0211348683, -0.1368488669, -0.1282242835, 0.0260183066, 0.1688709855, -0.0368644297, -0.1862521470, 0.0476023853, -0.0792344213, -0.1053574905, 0.1902099550, 0.1507623792, 0.1542567611, 0.1710912287, -0.0019168407, 0.2112519443, 0.1955697238, -0.1300433576, 0.0924468338, -0.1891560704, -0.0391472429, -0.1859188527, -0.2114342898, -0.1893524379, 0.1264006793, -0.0839566737, -0.1194514036, -0.0930093676, -0.1221729517, 0.0454541147, -0.1912920475, 0.1893217266, -0.1293410361, 0.1383384168, 0.1342498362, 0.1058112085, 0.0181810260, -0.1570251286, 0.1479201913, 0.0062170327, 0.0490781963, -0.2000998408, -0.0083201230, -0.0939723626, 0.1157927513, 0.0630370677, -0.0091766268, -0.0765612125, -0.0905905217, 0.0746472776, -0.0515676588, -0.0877936929, -0.1437296271, -0.2062004805, 0.0459145308, 0.0518745780, -0.0567450970, 0.2010192573, -0.0243847072, -0.0786848813, 0.1182677150, -0.0290865153, -0.0413807184, -0.1611226648, -0.0477492362, 0.0337571353, -0.0053299367, 0.1461633444, -0.1096765473, -0.0238418728, 0.0018897504, -0.1042069793, 0.1136350632, 0.1388032734, -0.0648652017, 0.0302183181, 0.1621866226, -0.1386421025, -0.0704583973, 0.0239891857, -0.1453436017, -0.0245934725, 0.1979980171, -0.0843390226, 0.0007893592, 0.0350620151, 0.2009984255, 0.1280063689, 0.0126281083, 0.0310563296, -0.1027310491, 0.0386101604, 0.0696326494, -0.2083996236, 0.1151551306, 0.0441848934, 0.1600982249, -0.1232326254, -0.0260440856, -0.1348734796, -0.0952562988, 0.1961986721, 0.1452758908, -0.1939922422, 0.0091093183, 0.0370045602, -0.0122943968, 0.1697953939, 0.1073029041, 0.1232846677, 0.1302166581, 0.0340778232, 0.0419728458, 0.1299465299, 0.0913463235, -0.0027413219, -0.1219573766, 0.0513713360, -0.1140092835, 0.2118974030, -0.1113556996, -0.2100419700, -0.0568319708, -0.0482634902, -0.0355322957, 0.1515703499, 0.1702822149, -0.1693487465, 0.2012262940, 0.1006334126, 0.0732228756, 0.1557646692, -0.1909618974, -0.1565110236, 0.0937556624, 0.0888049304, -0.0952448621, -0.0188108236, -0.1042839885, 0.0419894755, -0.1621105671, -0.0983826593, -0.0272268206, -0.1381223500, 0.0549430847, -0.0194458663, 0.0039207488, -0.1663725376, 0.1870987415, -0.1859398931, 0.1687123477, 0.0482874215, -0.1615109742, 0.0982285440, 0.1731853783, 0.1082703173, 0.1116540730, 0.2082655728, -0.0078319907, 0.2052211761, -0.0949357599, 0.1129602194, 0.1065994501, 0.0399096012, 0.0829414725, 0.1299278736, -0.2051162422, 0.0627848506, 0.1472616196, -0.1903744340, 0.1651630700, -0.1418522298, -0.0410842746, 0.0962750018, 0.0493612885, 0.1878988147, -0.0499424338, -0.0915017724, 0.0851533711, -0.0916376412, -0.1698620021, -0.1871181130, -0.0783956498, 0.1575850844, -0.1168074310, -0.1657191664, -0.0658403933, 0.1936830878, 0.0523431897, 0.1185898781, -0.0176909715, -0.0143125355, 0.0721827745, -0.0973571986, 0.0904549956, 0.1836954057, -0.0886407495, 0.0323009789, 0.1663124263, 0.0151741803, 0.0074783564, -0.0942574739, 0.1947118938, -0.0421919227, -0.1184858158, 0.2109894753, -0.0226028264, -0.1724603176, -0.2043152004, -0.0026250184, -0.0081331134, -0.1256359667, 0.0432811379, 0.0452671051, 0.0373051465, -0.1479172260, -0.1526697725, -0.0647729933, 0.1266577542, 0.1120478809, 0.1817023754, -0.2120599747, 0.0862949491, 0.0168930739, -0.2018598616, -0.1736362427, -0.0817916691, -0.0788579136, 0.0714763403, 0.0890515149, -0.2124472558, 0.1023100317, -0.0289710313, 0.1125129759, 0.0315441042, -0.0292290002, 0.0617497563, 0.0402621329, 0.0301108211, 0.2063018680, 0.1398603022, -0.1295326203, -0.0214233398, 0.1308341920, 0.0003687292, -0.1712298542, 0.1937851012, 0.0021202117, -0.0376309156, -0.0598136187, 0.1916348040, 0.1275726259, 0.1723597646, 0.1401208639, -0.0029467195, -0.1655184329, -0.1739171445, 0.2098056674, 0.0084194988, 0.0375558734, -0.1408582330, 0.0006600469, -0.1534451544, 0.1627846956, -0.1271483898, -0.1370807290, 0.1105353534, -0.0278621614, -0.0206038952, 0.1613380015, 0.1314874887, -0.0099503249, -0.0465818495, -0.0490111560, -0.1488530338, -0.0213380009, 0.1212062538, 0.0407195985, -0.1816841662, -0.0523589998, -0.1792617738, 0.1531568468, 0.0089685768, 0.0235614926, -0.0178877860, 0.1825806797, -0.1412900835, 0.1882363856, 0.0958912671, -0.1089919060, -0.0834980160, -0.0736042261, 0.0398091674, -0.1313294470, -0.0783142149, 0.0504100323, 0.0822021961, -0.0462735593, -0.1051808000, 0.0246717483, -0.0896309838, -0.0401306301, -0.0251594186, 0.0796609521, -0.1438814104, -0.0223538578, -0.0244199783, 0.1629701853, 0.1265147924, 0.0364100039, -0.0175888985, -0.1557615250, 0.0770325661, -0.1606579125, -0.0355778933, 0.1474189758, 0.0702895820, -0.2091641724, 0.1953218877, 0.0043252558, 0.0129832029, -0.1255178303, 0.0872347653, -0.0282660574, 0.1322372854, 0.0334073156, 0.0594078302, 0.1398628652, -0.0369449407, 0.1382974684, 0.0596849620, 0.0111430287, 0.1559647024, 0.1321473718, 0.1628567278, 0.0509160459, 0.1169908643, 0.1601838768, -0.1885716617, -0.1836548895, 0.1762075722, -0.0656511039, -0.1660412848, 0.1848152578, -0.2090318203, -0.1517060250, 0.1312254369, -0.1492921561, 0.0980155170, 0.1366658807, 0.1977568865, 0.1404947937, 0.1480135918, 0.1731882691, 0.0772440135, 0.0025944114, -0.1132899225, 0.0496724248, 0.1860830486, -0.1336355954, -0.0278831422, -0.0055948198, 0.1560053527, -0.0739876330, -0.0067940801, -0.1273649335, 0.0620990396, 0.1703686118, 0.1816574931, 0.1523585916, -0.1919798404, -0.0987751260, 0.1137881577, 0.1714571118, -0.0949567556, -0.0509785265, -0.0433674455, 0.0025682300, -0.1018572673, 0.2032278180, 0.1624566317, -0.1094431356, 0.1545654237, -0.0564386845, -0.0159603804, 0.0222223550, -0.1085324958, 0.0756898224, 0.0739400983, -0.0236016512, -0.1739635020, -0.0718785524, 0.1224631369, 0.0379896164, -0.2022826672, 0.0342850089, 0.1086674035, -0.0425202996, -0.0250317305, -0.0254981518, 0.1734285057, -0.0076459050, 0.1249652505, 0.1001253128, -0.0738305748, 0.1741576195, 0.1829492152, -0.0310747325, 0.0060606301, 0.0945225060, 0.1241886616, -0.0296901464, 0.0009692907, 0.0344382077, -0.0205199718, -0.1175931245, -0.0696323812, -0.1005026698, 0.0062219203, -0.1890629530, -0.1190022081, -0.1363080889, -0.1013581082, 0.2035762072, 0.1073179841, 0.1970246136, -0.0273063630, -0.1769396067, 0.0624212325, -0.1262149811, -0.0768698156, -0.0423385203, -0.1450702250, -0.1801055074, -0.0268956572, 0.0560451150, -0.1114352494, 0.1087172627, -0.2066947520, -0.0380227119, 0.0018448085, 0.1122630239, 0.0720984936, 0.0490970612, 0.0986473858, -0.0048467368, 0.0085182041, 0.1405288875, 0.1927247047, -0.1678233147, 0.0235735923, -0.0336104333, 0.1021865904, -0.0218194127, 0.0798167288, -0.0714006424, 0.0763245523, -0.2099650204, 0.1664243340, 0.0584085882, 0.2119176984, 0.1464650333, 0.2063736618, -0.1791144609, 0.1117559969, 0.1103233099, 0.1025905907, 0.0931468010, -0.2046590745, -0.0736854970, -0.0054731816, -0.0823983401, -0.0584122092, 0.1528870165, 0.1687346697, 0.0803000331, -0.0039590746, 0.0534914136, 0.0935313106, -0.0145738572, 0.1680481434, 0.1247592270, -0.1519022733, 0.0225370526, 0.2074175775, 0.0663752258, -0.0572958589, 0.1314680576, -0.0081505477, 0.1502386928, 0.0843608379, -0.0505757928, 0.0318961591, -0.1350189149, 0.2059093714, -0.1096357852, -0.0237801224, -0.0912672877, -0.0329676718, -0.0144457668, 0.1773395538, 0.0272649378, -0.0634466112, -0.1111930907, 0.1688987911, 0.0674479306, 0.1422763169, 0.1402884126, 0.1684876680, -0.0936151668, -0.0196692646, -0.1291329861, 0.1792899370, -0.1618148834, 0.1808791459, 0.1992952228, -0.1180936098, 0.0815925598, 0.1380904317, -0.1840451658, 0.1549934149, 0.0875937343, -0.0849592090, 0.0974246562, -0.0104719996, -0.1704319566, -0.1461453140, 0.1322407424, -0.0554242581, 0.0936799943, -0.0386036634, 0.1452425122, 0.0899178684, -0.0412901789, 0.0560518205, -0.1611335427, 0.1422611177, 0.1953564882, 0.0727872550, 0.0488506258, -0.1748843044, -0.1653818488, 0.1663266420, -0.1325635165, -0.0699115545, 0.1830326617, -0.0022758096, 0.0998718441, 0.1550491154, 0.0415105820, -0.1932657659, -0.0377684534, 0.1460716128, 0.2040894628, -0.1827876568, 0.2034503520, 0.0465519428, 0.1580714285, 0.0621053874, 0.1651513875, 0.1507709920, 0.1027133167, 0.1883013546, -0.1740298271, 0.1747498512, -0.0905787274, 0.1860815585, -0.0746505708, 0.0537184179, -0.0758107007, -0.0454756021, -0.1685490757, -0.1549349576, -0.1699792594, -0.2082224786, 0.1378434300, -0.1509437114, -0.0446635783, -0.1351365447, 0.0446104705, -0.1861547530, 0.0029438734, 0.1290639639, -0.1048939601, -0.0368072987, -0.1131323949, -0.2130697817, 0.0702968538, -0.1823674440, -0.1840161979, -0.0068235993, 0.1415870786, 0.1259913146, 0.0572944880, -0.1511217207, -0.1518146992, -0.0302279294, 0.0081147105, -0.0265112668, 0.0647821426, 0.1110815108, -0.1381454766, 0.1686417460, 0.1248066425, 0.1109326482, -0.1001610830, 0.2065006196, -0.1484271139, 0.2000478804, 0.0129306018, 0.1010906696, 0.0494739711, 0.1341028810, -0.0126507729, -0.0906337276, -0.0796923041, -0.1187514141, 0.0626639128, 0.1592695117, -0.0600781441, -0.1760297269, 0.1624909341, 0.2064928412, -0.0690795928, 0.1862381101, 0.0610037744, -0.0018520802, -0.0035834312, -0.0278175771, -0.1491471827, 0.1348098814, -0.0514868349, -0.1080121920, -0.1104326621, 0.2023530304, -0.0406453907, 0.0713945329, 0.1608239710, -0.1471444964, -0.2112867832, -0.0019274056, -0.1672579646, 0.1421840489, 0.1175822914, -0.0851505399, 0.1390727758, -0.0979966521, -0.1673496217, 0.0396300852, 0.1642152369, 0.1630523801, 0.1590069234, -0.1655886769, -0.0681497008, 0.0405101776, 0.1699393094, -0.0245542228, -0.1818218231, -0.0424215794, 0.0926091373, -0.1783550382, 0.1543887854, 0.0718891919, -0.1927368641, 0.1659371257, 0.1914150417, 0.1347251534, 0.0423839688, -0.0580154210, -0.0447445065, -0.1811912656, -0.1356982589, 0.0058128387, 0.0032359511, 0.1545306444, -0.0575654060, -0.1548760533, -0.1092362031, -0.1805575043, -0.1575052738, -0.0652302206, -0.0790501535, 0.1490799487, 0.0498728454, 0.1736911535, 0.0337035507, 0.0347825885, 0.1907315850, 0.0940455198, -0.1271450371, -0.1469286680, 0.0499047041, -0.1211973503, 0.1857516170, -0.1012217775, 0.1606440544, 0.1949877143, 0.0010551512, 0.1897149086, 0.0091839880, -0.0053898692, 0.0590130389, -0.0634863079, 0.0069778711, -0.0761531889, 0.1508392990, -0.0640203953, -0.1421354562, 0.1939566135, 0.1684629321, -0.0360288620, -0.1836050153, 0.0923433304, 0.0136799514, -0.2008460909, -0.1974148452, 0.0965938270, 0.1779162288, 0.1597458720, -0.0529540777, -0.1671065390, -0.1075444445, 0.1343218088, 0.1139514744, 0.0594527125, -0.1444732845, 0.0543672740, 0.1798780859, -0.0765798688, 0.1536311805, 0.0859356225, 0.1940051615, 0.1727126539, 0.0379105210, 0.0009198934, -0.1782970428, 0.0198643059, 0.0361964107, 0.2025280297, -0.1845655739, -0.0162867159, 0.1495032609, 0.0997734070, 0.0528253615, -0.2013835311, 0.0945262611, -0.1260560751, -0.2058556378, 0.0438373685, -0.1610147059, 0.1749124229, -0.1420629621, -0.1523222476, 0.0423185527, 0.0682304204, -0.1083713099, 0.1326313913, -0.1834546626, -0.0828554183, -0.1987082362, 0.1442075372, 0.0832913816, -0.0681697726, -0.0933425650, -0.1998527944, -0.2001420259, -0.0934497640, -0.1489324868, 0.1759579480, -0.1881609559, 0.1892626584, 0.1499628127, -0.2007803619, 0.1305122972, 0.0622969568, 0.1794747412, 0.0820458233, -0.0254466087, 0.0773642957, -0.0267990828, 0.0644598305, -0.1568169296, 0.1258660853, -0.1860484630, 0.1883485615, 0.1727247536, 0.1197294891, -0.1694395840, 0.1129588187, 0.0532492101, 0.1438889802, 0.0986272693, -0.0438405275, -0.0657222122, -0.0719935447, 0.0421020687, -0.0541504771, 0.1208387911, -0.2131919265, 0.0039448440, -0.0854387432, -0.1607017815, 0.0815662742, 0.1249569058, 0.0407440066, -0.1564131677, -0.1577273607, -0.1736676693, 0.0977464616, 0.0630435646, 0.0068023056, 0.0708548129, 0.1436045170, 0.0072188228, -0.1178695410, 0.1501477957, 0.0042518079, 0.1290286183, 0.1199949980, -0.0904974490, -0.2128094137, 0.0700814426, -0.1686827689, 0.1664354205, 0.1718768477, -0.1842298806, 0.0531402528, -0.0238433480, -0.2039491236, -0.0819852352, 0.1844753027, 0.0296037793, -0.0350253582, 0.1872778535, -0.1650556624, -0.0567166358, 0.1191662848, -0.1457097828, -0.0642208606, 0.0548260212, 0.1760723889, -0.0513615906, 0.0929824710, 0.1938198209, -0.0034515262, 0.1158276498, -0.0828904361, 0.0234277099, 0.0763218999, 0.1054467559, 0.1146610975, -0.0648252517, 0.0624802113, 0.2022757232, -0.1753597260, 0.1490517855, -0.1511972994, 0.1661396027, -0.1716566384, -0.0434365273, -0.1507773399, 0.0630852878, -0.0973015353, -0.1589654088, -0.1886912286, 0.2025721669, 0.1810853183, -0.0706967413, 0.0383313596, 0.1245371401, 0.1146691144, -0.0449625701, 0.0436422825, 0.1395887136, -0.1616845131, 0.1066615582, 0.1780829430, -0.0645134449, 0.1557524800, -0.0882606283, -0.1103699356, -0.1888148487, 0.1427669227, -0.0163445026, -0.1656727493, -0.0337721258, 0.2112357020, 0.0161519647, 0.0182989091, -0.1249348521, 0.1998015642, -0.2016466260, 0.0259066820, 0.1043611467, -0.0022014976, 0.1776066720, 0.1349163353, 0.1535488367, 0.1053943336, -0.0207833797, -0.0530792624, 0.0430369377, 0.1755416393, 0.0766601861, -0.0773406029, 0.0147576630, 0.0559092760, 0.0843859911, -0.1002954841, 0.0615185797, -0.1131670624, 0.0017252117, -0.1220274195, -0.1376246065, -0.1835173368, -0.1174220815, -0.1680146903, -0.1507832408, 0.1809541285, 0.1313103437, -0.1905061454, -0.0216181725, -0.1844664514, -0.0534408838, -0.2044046670, 0.0049962848, -0.1204927266, 0.1276222467, 0.0318249911, -0.1870529354, 0.1569690108, 0.0279721469, 0.2019387484, 0.1913354099, -0.0546239167, -0.1964109242, -0.1925244331, 0.0739316642, -0.1145623252, 0.1245226264, -0.1919418126, -0.0579973161, -0.0511387438, 0.0103970766, 0.1590977013, 0.1299258471, 0.0437954962, 0.1557581723, 0.1993747354, 0.0341538638, 0.0599365234, -0.1906317025, -0.1545984149, -0.1063477322, -0.1067869589, -0.1613583267, 0.1209427416, -0.0941306502, 0.0978935659, 0.1584370136, -0.0206309855, -0.2008893490, 0.0891769528, 0.1714769900, -0.1579600126, 0.0751194954, -0.0583976209, -0.1104251891, 0.0307909846, 0.1872331798, -0.1938214451, -0.2099076360, -0.0078707188, -0.1876039505, -0.1131740287, 0.1190108061, 0.1344430447, -0.1948728263, -0.0047534555, 0.1290161610, -0.1333805770, -0.0967373103, -0.1476974785, -0.1990575939, -0.1990798116, 0.1665185988, 0.0363839716, -0.1362581700, -0.1713395417, -0.0987100676, -0.0854968429, -0.1141184196, -0.0776877850, 0.0548579991, 0.1284639835, 0.0501741171, -0.1944070756, 0.1335031390, -0.0683825612, -0.0699648261, -0.0992463827, 0.0448395014, 0.0899653435, -0.0744938701, -0.0096022338, 0.1873570085, 0.0732779801, -0.1916254908, -0.0531954616, -0.0220243633, -0.1768929362, 0.1347981393, -0.0774987340, -0.1386564374, -0.1722143590, 0.1197276711, -0.0297907889, 0.0230280310, 0.1581282616, 0.0137360692, 0.0143634677, 0.0532052815, 0.0497603118, 0.0923163891, -0.0899877176, -0.0450925976, -0.1556188911, -0.0994720757, -0.1373393983, -0.0370617509, -0.1319033206, -0.0236480683, 0.0797799826, -0.1062793136, 0.0500923395, 0.0054854304, -0.0232686102, 0.0268861502, 0.1068070829, 0.1481148601, -0.0765626878, -0.2049585134, -0.2074185312, 0.1376159191, 0.1162165105, 0.1596168578, 0.2111602724, -0.1718850732, -0.1022058651, 0.0040615499, 0.0975148380, -0.1960753500, 0.0795379877, 0.1664321125, -0.1130281910, 0.1508635581, -0.1652863920, 0.0242457390, 0.0055758506, -0.0306469351, -0.1158140376, -0.0395158827, -0.0917486027, 0.0528489947, -0.1595364809, 0.0755034685, 0.0998315513, -0.0077430904, -0.0779739022, 0.1347191036, 0.0529284477, -0.1888697445, 0.2032252252, 0.1789621711, 0.0117135048, -0.0093316138, 0.0515504181, -0.0069679618, 0.0242062807, 0.0760845244, 0.1489381790, -0.2005273253, 0.1012580693, 0.1794412434, -0.0231635869, 0.1566728652, -0.0870216787, 0.1510018110, -0.0404780507, -0.0720026940, -0.0239696652, -0.1116491482, 0.1134687364, -0.0718342364, 0.0246311873, 0.0601386726, -0.0144272596, -0.0647571385, -0.0739642531, -0.0646997988, 0.1861934364, -0.1823046654, 0.1959239542, -0.2009767294, -0.0160039365, -0.0794434398, 0.1750234663, 0.0874374807, 0.1707782745, 0.1825541854, -0.0467963964, -0.0234479457, -0.1295272261, -0.0882118866, 0.1365664005, 0.1647350192, 0.1123317480, -0.1775737703, -0.0438817590, 0.1012901366, -0.0697916448, 0.0002094805, -0.1149990633, -0.0234351307, -0.1668582857, 0.1332397759, -0.0910778865, -0.0948271379, 0.1515246630, 0.0342892855, 0.0003544390, -0.0739539862, 0.1579813659, -0.1103885919, -0.1934318841, 0.1029623449, -0.1023991257, -0.1770507097, 0.1144099236, -0.1180014014, -0.1217893288, -0.0216405988, -0.2123173326, 0.1234333515, -0.0110137612, -0.0702448487, -0.1057308912, 0.0890272558, 0.1160265207, 0.1072906852, -0.1487851739, -0.0729204863, 0.0325599611, -0.1984154582, 0.1357439160, 0.1908751130, -0.1651226133, -0.0818393081, -0.0859399438, -0.1118555740, 0.1012180746, -0.1372910589, 0.1543109715, -0.0700101107, -0.1153733879, 0.1927016973, -0.1514202058, -0.0399074256, -0.1110946834, 0.1895937324, 0.1058147252, 0.0465854406, 0.0037314594, 0.0336747766, -0.0988306329, 0.1484581232, -0.0304508209, -0.0265737921, -0.1864701658, -0.0615098476, -0.2006002665, -0.0114497393, -0.2109055966, 0.1424169540, 0.1540012062, -0.0719988793, 0.0591722727, 0.2031416595, -0.0165841281, 0.1612119377, -0.0742466301, -0.1312684417, 0.0608208776, -0.0316384435, -0.0817120224, 0.0872193575, 0.1956618726, -0.0404774398, 0.1140631735, -0.0501891673, -0.1804451048, 0.0997518897, -0.1699244082, -0.1335892379, 0.1278506219, 0.0197480470, -0.0585744530, 0.0234824568, -0.1051296145, 0.0362330079, -0.1587586254, 0.0151935965, 0.0355547667, 0.0052086562, -0.1169655174, -0.1713310182, -0.0385859758, -0.0837848634, 0.1440131068, -0.0401693135, -0.0738870949, -0.0715562850, 0.0477899909, -0.0151329041, -0.0192564577, -0.1984879375, 0.1764692068, -0.0540780425, 0.1339556873, 0.1013427079, 0.1356646121, 0.0366824567, -0.2079485506, 0.0675307810, 0.0513723493, -0.0202654600, 0.0328555405, -0.1610383391, 0.0330421478, -0.0760183930, 0.0774135888, 0.1138041914, 0.0724302232, 0.0473278463, 0.0798558295, 0.1625003517, 0.1401090324, -0.0781959444, 0.0051681399, -0.0166549385, -0.1576520801, 0.0759117901, -0.1660232395, 0.0300527215, -0.0842814296, -0.1780070066, -0.0144460648, -0.1311115324, -0.0554333478, -0.0296566933, -0.0202657580, -0.1877194941, 0.0399649739, 0.2036542892, -0.0825829059, -0.1474654377, 0.1191262007, 0.0360662788, 0.1118718386, 0.1384701431, -0.0842552930, 0.1759040654, -0.1586447060, -0.1873539686, 0.0091989934, -0.0039460659, 0.0245167613, 0.1099811196, -0.1016512513, 0.1695171595, -0.1549521983, -0.0917722955, -0.0526238680, 0.1569677293, 0.0747935176, 0.1457156241, -0.0392616242, 0.0045026094, 0.0586986244, 0.1585946977, 0.0240565389, 0.0721940100, -0.0179607868, -0.0745855123, 0.1442858577, 0.0884040296, 0.1972596943, 0.1373186111, 0.1396714151, 0.1481304765, 0.2042340338, -0.1433375180, 0.1879104972, 0.1883034706, -0.0375428647, 0.0876332223, -0.1979481578, 0.1876739562, -0.0831981152, 0.1516041160, -0.1019506454, -0.0926410481, -0.2048652470, -0.1704465002, 0.0091331154, -0.0848201811, -0.0127605647, -0.0296472460, 0.2019983232, 0.1860531569, 0.1715733707, -0.1858924627, 0.1668051183, -0.1521826088, 0.1237525642, -0.0924146920, 0.1166935265, 0.1696141362, 0.0671969652, -0.0248258710, 0.0338087231, -0.1298024356, -0.1412873417, -0.0938943326, 0.0255146325, -0.0767071545, -0.1595285088, -0.0689493716, -0.1350239515, -0.0762471259, -0.1737507731, -0.0865042210, 0.1237120032, 0.1740107238, 0.1906027198, 0.1435766220, -0.0496110618, 0.2051031291, -0.1019685343, 0.1054754555, -0.1568296850, 0.0534400046, 0.1224918664, -0.0571731478, -0.1844448447, -0.1931433082, 0.1145355999, 0.1861183643, 0.2112169862, -0.2071847171, -0.1183616370, 0.0267622173, -0.0111140013, -0.0748765171, -0.0343641043, 0.1867268980, 0.0073581487, -0.1785207093, 0.0156961530, -0.0324758887, 0.1932121813, 0.1859124005, 0.1032010913, -0.0417507589, -0.0692599416, -0.0419545919, -0.1674657762, 0.0691252351, -0.0761830360, -0.0556465387, 0.0874100626, 0.0407373905, 0.1677820981, -0.1047263220, -0.0004046112, -0.1613337100, 0.0772895217, 0.1394611299, -0.1292207241, 0.1378256083, 0.1551188529, 0.0093925595, -0.1140830368, 0.0083839595, -0.1780405492, -0.1162949502, -0.0319907516, -0.2126251012, -0.0337369442, 0.0166796893, -0.0834767222, 0.1906233728, -0.0643443912, -0.1505066603, -0.2028512210, 0.1418441832, 0.0258653611, 0.2078367770, 0.1635337472, -0.0844045877, 0.1793107092, 0.1728874147, -0.1903070360, 0.1823727190, 0.0281185955, 0.1103662848, 0.1913473010, 0.1985392869, 0.1925708055, -0.2113988549, -0.1326120645, -0.0053517967, 0.1622230113, -0.0963383913, 0.0758258998, -0.1000966355, 0.2115381956, 0.1619590819, 0.0606486797, -0.2107422203, 0.0434962511, 0.0496878326, -0.0737221986, -0.1311294138, 0.0231507868, 0.0533021986, 0.2003799677, -0.2059152126, -0.1476105750, 0.1615459025, -0.0945557505, -0.1844131798, 0.0907543898, -0.0892151371, -0.0803146809, -0.1402549595, 0.1689867973, 0.1396781802, -0.0881352276, -0.0759515911, 0.0551408827, 0.1586233675, -0.0432564318, 0.0208853930, -0.0288933069, -0.1734358221, 0.0157984346, -0.2012790740, 0.0118523687, 0.0947940350, -0.0750545859, 0.0994751751, 0.0760326087, -0.0599491745, -0.1075237021, -0.0623507500, 0.0252066404, -0.1730477214, 0.0188627839, 0.0291252583, 0.0546479225, -0.2006445974, -0.1803621650, -0.1530943662, -0.2109929770, 0.0681557357, 0.1000976861, -0.0689093620, 0.0986846983, -0.1617750823, 0.1346070766, -0.1434522867, 0.1873315871, -0.0810629129, 0.0585987568, -0.2078234553, 0.0861922204, -0.1149285138, 0.1015041471, 0.0587496758, -0.0816388279, 0.0329773873, -0.1751419157, 0.0617503226, -0.0125437230, -0.0608698875, -0.1515468657, 0.0312709361, 0.0630266964, 0.0740807056, -0.0399111360, -0.0375293493, -0.0139126033, 0.0200311840, -0.0200245231, -0.1484813988, 0.2052195966, 0.0477811992, 0.0990149975, -0.1714024246, -0.2094894946, -0.1313878894, -0.1148661450, 0.0304362923, 0.0647411346, 0.0184717923, 0.1958904266, 0.0704886317, -0.2035749555, 0.1110543609, -0.0554997325, 0.1144627333, -0.1712825596, -0.0720108747, 0.1296592355, 0.1444630623, -0.1581989676, 0.1138352454, -0.1145668477, -0.0837427229, -0.0041969121, 0.1294562817, 0.0548149943, -0.2026207447, -0.0274128020, 0.0741438866, 0.2122734189, 0.1474706233, -0.1592406482, 0.1181590259, 0.0398111939, -0.0797617882, -0.0818977058, -0.0535846353, -0.0138099790, 0.0738448501, -0.0227702558, 0.0595405102, 0.0758373141, 0.1493564546, 0.1753648520, 0.2115623355, 0.0326047838, 0.0795084834, -0.1598423868, -0.0082726479, -0.0116433501, -0.0979276747, -0.0745778382, 0.0494920313, 0.1692018509, -0.1930025518, -0.1778339744, -0.1058364213, -0.2035454214, 0.1553150117, -0.1060210392, 0.1822800636, 0.1885613501, 0.1408819556, -0.1401152760, -0.0881394446, -0.0391691625, 0.1795762181, -0.1603543609, 0.1908683181, 0.0162536800, -0.2088878602, -0.0978953987, -0.1938916445, 0.0695549250, 0.1291896701, -0.0831993371, -0.2024009079, 0.1975736916, 0.0419121087, -0.1825169325, -0.0131265521, -0.0304873288, 0.1385656893, -0.1155586168, -0.0952081606, 0.1655867398, 0.1476935148, -0.1647372097, 0.1462611556, 0.0466453433, 0.0614350736, 0.1485420465, 0.1639919877, 0.0604065061, 0.2065810859, -0.1950193793, -0.0875226706, -0.1095805839, -0.0771680325, 0.1688233614, 0.1457514167, 0.0789042711, 0.0510345995, -0.0439327359, 0.1476272345, 0.0209182799, -0.1571552157, -0.1447319984, 0.1360955238, 0.1790454686, -0.0366974473, -0.0223669112, -0.2093652189, 0.0970938802, 0.0873357058, -0.1303490102, 0.1705565453, -0.0405270606, 0.0477897823, -0.1483874172, 0.1627970040}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w16.txt b/model/AE_model/hls4ml_prj/firmware/weights/w16.txt deleted file mode 100644 index 5dc8f99..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w16.txt +++ /dev/null @@ -1 +0,0 @@ --0.0130273253, -0.1259363294, 0.0945610702, -0.0644461960, 0.1832793951, -0.0208553076, -0.1577622890, 0.0114846081, 0.0462474227, -0.1888662875, 0.1281007528, 0.1329291463, -0.1587361991, -0.1352097839, 0.0944213569, 0.0784721076, -0.1558004022, 0.1288587451, -0.2122411281, 0.0272939205, 0.0659274757, -0.2089752853, -0.1386389434, -0.0837319940, -0.1696569324, 0.0262442082, 0.1631107330, -0.1182218567, 0.1800297797, -0.1726104319, -0.0111823082, -0.0128869861, -0.1045312807, -0.2043615580, -0.0798180550, 0.0643519163, -0.1027161554, -0.0397471637, 0.0978991687, -0.1402687877, 0.1218408048, -0.1134288982, -0.1261436641, 0.0335370302, 0.1479334533, -0.0108215213, 0.1092103422, 0.2026947737, -0.0346155167, -0.1371692121, 0.1905909181, -0.1643185169, 0.0096005499, 0.0794419646, 0.1910420954, -0.1008122340, -0.0858196318, -0.0960322395, -0.0611624718, -0.1540560871, -0.0846777558, 0.0128069818, -0.0647849888, -0.1241305545, 0.0749971569, -0.1083801538, -0.0463754684, 0.0780991018, -0.0549549758, 0.0051411539, 0.2104826868, 0.0234862119, 0.0375915766, -0.0367360860, -0.1087446660, 0.2111480236, -0.1739501804, 0.0233765692, 0.1652782559, 0.1255599260, -0.1299285442, -0.1814702153, 0.1860595942, -0.0244893581, -0.1234823540, 0.1627963185, 0.1788330972, 0.1180432737, 0.0764050186, -0.2097494900, -0.0992160887, 0.1479691863, -0.1603781432, 0.0174055099, 0.1682570577, -0.0068627894, 0.0234803259, -0.1371489763, -0.1290633380, 0.2020197213, 0.1064198017, -0.1345657110, 0.1129842699, 0.2006976604, 0.1649823785, 0.1847754717, -0.0348276794, 0.1845819056, -0.0747617930, 0.0267496705, -0.0231935233, -0.1705366671, 0.0892340541, -0.1630261838, -0.0064330697, -0.0180535465, 0.1774684489, -0.0118700117, 0.1112754345, -0.1261567175, -0.1455314755, 0.1447922885, 0.0541168749, -0.0653234869, -0.0965587944, 0.0156036466, 0.0802645087, 0.0841549635, 0.0812481344, -0.1411535442, 0.1254012883, -0.0455906391, -0.0306715816, -0.0808172971, 0.1147423089, 0.0619878173, -0.1582829952, 0.1947368681, 0.0744240284, 0.2098235190, 0.0004032403, 0.0944982171, -0.0592246801, 0.0990560055, -0.1866515279, -0.0556830317, 0.1125717759, 0.0700600147, -0.1412425637, 0.0156001896, 0.0776591599, -0.0046227276, -0.1678069979, 0.0324525982, 0.1702670753, -0.2018597126, 0.1013407707, 0.0099410713, 0.0017249435, -0.0457270741, -0.0991436541, -0.2034626603, -0.0888631791, 0.0707303286, 0.2062967122, 0.1711236238, -0.1963857710, -0.1301012635, 0.0640211105, -0.0077804029, 0.0104616880, -0.0048618913, 0.2108360231, -0.1978262216, 0.0269224495, 0.0039434731, 0.0548866689, -0.0827367753, 0.1085537970, 0.1956063807, -0.1081783026, 0.1494415104, 0.1101001203, -0.1612143219, 0.1067217290, -0.0207707137, -0.1488733590, -0.0303766131, -0.0802035034, -0.1339956224, -0.1519602239, 0.0016708672, -0.1595647037, 0.1969965398, 0.2075348794, 0.1518881917, 0.0671034455, -0.1564162225, -0.1543469429, -0.1770093888, 0.0682467222, -0.1632902026, -0.1717197597, 0.0498220026, 0.1095688343, -0.0015616864, -0.1720746160, 0.1646409333, -0.1605213434, 0.1961368918, 0.0093684644, -0.0201760978, 0.2055852711, 0.1918219030, -0.0060595125, -0.1528907865, 0.1307045221, 0.1481581628, 0.1970739663, 0.1757183969, -0.1381469071, 0.1237665117, 0.0018544197, 0.0833833516, -0.1581424922, -0.1709466279, -0.0158225298, 0.0906814039, 0.0412386954, 0.1893225014, 0.1991872787, -0.1016348824, -0.2098781019, -0.1076380759, 0.2011736035, 0.1551723778, 0.0359183550, 0.0616644621, -0.2027701885, 0.2111682296, -0.1193955913, -0.0354953408, -0.0443158448, 0.0606944561, 0.1446566880, 0.0543707907, 0.1525784731, -0.1012778431, -0.0449997336, -0.0272941738, 0.0104666650, -0.2114956975, -0.1726112962, 0.0984360874, 0.0880922377, 0.0589379370, -0.1279652417, 0.0765250623, 0.1821038425, 0.1174420118, -0.0163721591, 0.1228275001, -0.1220860258, -0.1425816417, -0.0332352966, 0.0324501693, 0.1842880249, -0.1939656585, 0.1910464168, -0.1111146137, 0.0026402175, 0.1187394559, -0.0988348573, -0.1217542514, -0.0492030978, 0.0797930956, -0.0714403391, -0.1571806669, 0.0695837438, 0.1016166210, -0.0704020709, -0.0949677825, -0.0479588509, -0.1081922874, 0.0105456114, -0.0054046065, -0.0465161651, -0.1691238731, 0.2052527666, 0.1894890070, 0.0782389343, 0.0852125585, -0.1593517214, 0.1442769170, 0.1072202325, 0.0686706603, -0.0415009856, -0.1497082710, 0.0498762131, -0.2106196284, 0.0765061677, -0.1385392547, 0.1746212542, -0.0992993489, 0.1934341788, 0.0618958473, 0.1375975311, -0.0717558563, 0.2000515461, -0.0323338062, -0.1225704998, -0.0116799474, -0.0371402949, -0.1208240986, 0.1519456506, -0.0316224843, 0.1335759759, -0.2024369538, -0.1641412675, -0.1927401721, 0.0306266546, 0.0828153193, 0.1659827828, 0.0384555459, 0.1457235515, -0.0497836322, 0.1769310236, -0.2116001546, -0.0031991005, -0.0807842463, 0.0081038922, -0.0225998759, -0.1627896130, 0.0764707923, 0.1039808393, -0.0406423360, -0.0554921627, 0.1342954934, 0.0338096321, 0.1133666337, 0.0632500947, 0.1918676496, 0.1823641956, -0.1334682703, -0.1244893149, 0.1369327009, 0.0636276603, 0.1408673227, -0.0425146967, -0.2027536780, -0.0305647403, 0.1510687470, -0.0805604905, 0.0702908039, -0.1553621888, -0.0088961422, 0.0790726840, -0.0023701489, 0.1248674989, -0.1758075953, 0.0428200960, 0.0787388682, 0.0355882198, 0.0636335611, -0.1202259660, 0.0270224810, 0.1517257392, -0.1454291940, -0.0783185363, -0.0340940356, -0.2012153268, -0.1551640034, 0.0292676836, -0.1072629914, -0.0488430113, 0.0402400792, -0.1803735942, -0.1590253264, -0.1700740159, -0.0305492282, 0.1598092020, -0.1394096911, -0.1372441947, 0.0859484375, 0.1609318554, -0.1009811461, -0.0802806169, -0.1897195280, -0.0607282221, -0.1316629350, -0.1219133064, -0.2082910538, -0.1972658038, -0.1844384521, 0.1265234351, -0.1628829986, -0.2030221075, 0.1910839975, -0.0368629098, -0.0243633538, 0.0063986033, -0.1167256460, 0.0628578961, -0.1803720146, -0.0783854425, 0.0121531934, -0.1639599055, -0.1593689471, 0.1314008236, -0.0459068567, -0.0907423571, 0.1804122329, 0.2122233510, 0.1151688397, 0.0911640525, 0.0348865390, 0.1300783455, -0.0236830264, 0.0023433119, 0.1851803660, 0.1672433913, 0.0325655490, 0.0911865532, -0.1637508869, -0.1168597341, 0.2057717144, 0.0455974638, 0.0204673558, -0.1965441108, 0.0855367482, -0.0623529255, 0.1629964113, -0.0489413142, 0.0882367492, 0.0340018868, -0.1326198429, -0.1001866534, -0.1245983988, 0.1413900256, 0.1874953806, -0.0106244385, 0.2050077319, -0.1698612273, -0.1506629139, -0.1031069979, -0.0526490808, 0.0260028094, 0.1677609980, 0.0581763983, -0.1462530196, -0.1360576898, -0.1503466368, 0.1414406896, 0.1622020006, -0.0680478364, 0.1303669214, -0.1221360937, 0.1745809913, 0.0342087150, -0.1642162502, 0.0834338665, -0.1282218397, 0.1373473406, -0.0401223451, 0.0739849508, 0.1701364219, 0.1990130246, -0.1143041030, -0.0163943768, 0.2096578479, -0.1905419827, -0.1134785041, 0.0192365348, 0.0860688388, -0.1228942946, 0.1085300148, -0.0134354979, -0.1682397127, 0.1570128798, 0.1703217030, -0.1215950996, 0.1636342406, -0.0334042609, -0.0700438619, -0.0970657319, -0.0906256959, 0.1340383887, -0.1851412952, -0.0015206039, 0.0290814936, -0.0646947622, 0.0061229467, 0.0407950282, -0.0902684033, 0.1242007911, -0.0269559473, -0.0076397955, -0.2071086168, 0.1732262969, -0.0320551991, -0.0571409166, 0.0321718603, 0.1998512745, 0.0916839540, -0.0651914328, 0.1697616577, -0.0198900700, -0.0171448886, -0.1235098019, -0.1281911433, -0.1592148840, 0.0836006999, -0.1731902510, 0.0908051729, -0.0268761814, -0.1512360871, -0.2000906318, -0.1091002822, 0.0626733303, -0.1795879006, 0.1988547742, 0.0267653167, -0.0725796670, -0.2008852810, -0.1168303564, 0.1781799793, 0.1904968023, 0.1290690303, -0.0236298144, -0.0400479287, -0.1034653038, 0.1879202127, -0.0822001994, 0.0808651149, -0.1721311361, 0.1181168854, 0.1653339565, 0.0717893541, 0.0279274285, -0.1693844795, 0.1900699735, 0.0000168830, 0.1852777302, 0.1035282314, 0.1743865013, -0.1719912589, -0.1293298006, 0.1979320943, 0.0311407000, 0.0762527585, -0.1054227054, -0.1804566532, -0.1717367470, -0.0783862472, -0.0735121667, 0.1575010717, 0.1610148549, -0.1397852898, -0.0534511954, -0.1419837177, -0.1520278305, -0.0357308537, 0.1778426766, 0.2022635639, 0.1641831994, -0.1320675611, 0.1779336035, -0.0851632953, -0.1922511756, 0.1587883532, 0.0165648609, -0.0097687542, 0.1468048990, -0.1659059674, 0.1205895543, -0.0662048459, -0.1921826005, 0.0132936239, -0.1969076991, 0.1992416680, 0.1337226033, -0.1967195719, -0.2016975135, -0.1981110722, 0.1564672589, 0.0506201088, -0.2086362988, -0.1201700047, 0.0168281645, -0.1158882529, -0.1751039326, -0.1424258947, 0.0607258379, 0.0809723735, -0.1056843325, -0.1978037506, -0.0771079063, -0.0868115872, -0.0388507992, 0.1239619553, 0.1218158007, -0.1637382209, 0.0826045573, -0.0083401054, 0.0766014159, 0.0513367951, 0.0186986476, -0.1079499200, 0.0341885388, -0.1341587454, 0.0070068985, -0.0510378480, 0.1157514751, 0.0924983621, 0.1735253334, 0.1024294198, -0.2024069577, 0.1459152102, -0.1794299632, 0.1391270757, -0.0433251560, -0.1144386530, -0.1725994051, 0.0651500523, -0.0469828993, 0.1333318949, -0.0614170730, -0.1486979425, 0.1749379337, -0.0312749445, -0.1020108759, -0.1791891754, 0.1619752049, 0.1529638469, 0.0497876108, -0.0993031636, -0.0895941854, 0.0647700429, 0.0605212450, -0.1583527923, 0.0356428623, 0.1551423371, 0.0297968388, 0.0220008790, 0.1167052090, -0.0531750321, -0.0138240457, 0.1592967808, 0.0496267378, 0.2091331780, -0.1480971277, -0.1682489216, 0.1384595037, 0.0888846815, -0.0842253119, -0.1167098358, 0.1488567889, 0.2066698968, -0.0304312110, -0.1703116000, 0.0639329553, 0.0541225374, -0.1226595566, -0.0579297096, -0.1718170643, -0.1047814190, 0.1794770956, -0.1659982800, 0.0023263842, -0.0723258704, 0.1574643552, -0.0623307228, 0.0114367753, 0.1690727770, -0.2131630033, 0.0294306427, -0.1702712774, -0.1688735783, -0.1018458307, -0.1143009514, -0.0047163516, 0.0957580507, -0.0802835226, 0.0648097396, -0.0078999996, -0.1538537294, -0.2005685568, 0.1738888323, 0.0263175517, 0.1479609907, -0.0688941628, 0.1260773838, 0.0928246081, -0.1632209718, 0.1544763148, 0.1699717343, -0.0160051137, -0.1773654222, -0.0445157737, -0.1644815356, -0.1299230456, -0.0888913423, -0.0018408000, 0.0861804187, -0.1999694109, 0.1855406761, -0.1262204200, -0.1767251939, -0.2082639039, -0.0643157661, 0.1059206426, 0.0088308752, 0.0215080827, -0.0907995403, 0.1237658262, 0.0732398033, 0.2101181149, -0.0685326010, 0.0550488234, -0.1716340184, 0.1942046583, 0.0304473639, 0.2130631804, 0.1521381438, -0.0104703307, 0.0254605860, -0.0609222949, -0.0393703431, -0.0966759622, 0.0641950965, -0.0440582931, 0.1723761857, -0.1971201748, 0.0044940263, -0.0772200376, -0.1752294451, 0.2021924853, 0.0265952498, 0.0746521652, -0.0911174864, -0.1643462777, 0.1444889903, -0.1840594560, 0.0733265281, -0.1415145099, 0.1180490255, -0.1164425164, 0.0999458730, -0.0610869825, -0.0340544432, 0.1973402798, -0.1915016174, 0.2029054165, -0.0103540272, -0.1594736576, -0.1525272429, -0.0188208371, -0.0790094435, 0.1923677325, -0.0339856148, -0.0228689164, -0.0859591067, 0.0814860761, 0.0550598502, 0.1838219166, -0.0192521960, 0.1407603621, -0.0096959174, -0.0932167545, 0.1781721115, -0.0855361372, 0.1891888678, -0.0069375187, 0.1952764690, 0.1129395366, -0.1079180986, -0.1885606945, -0.0205569714, 0.1095406711, -0.1541737169, 0.0263331085, -0.1461997032, 0.1600303650, -0.1034623086, 0.0812811852, 0.0963799059, 0.0490098298, -0.0512192100, 0.0336747766, -0.0803432912, -0.1928579956, 0.0009355396, -0.1906580329, 0.1890609264, 0.0538485348, 0.0304931104, -0.1823762357, 0.0240671188, -0.1079957187, -0.0150481611, -0.0227957815, 0.0470040441, 0.0693390965, -0.0566840470, -0.0704285055, -0.1234320328, 0.0321579278, 0.1299918294, -0.0880828798, 0.0265530050, 0.0247528702, 0.1927776337, -0.1681027412, 0.0949314535, -0.0540727675, -0.2020932734, 0.1341821849, 0.2118407488, -0.2032287419, -0.1367629170, -0.0947465152, 0.1430233717, -0.2115065157, -0.0912154391, 0.1946260035, 0.1944942474, -0.0088078976, 0.1785105765, 0.1199140549, 0.1413906813, -0.1986526847, 0.1076044738, -0.0413151979, -0.0772407800, 0.1983164847, -0.1040216982, 0.1793057323, 0.1895011663, -0.0773698837, 0.0715141594, 0.1469281614, -0.1726556122, -0.1201167330, 0.0367779583, -0.1818589270, 0.0927172005, -0.0280686319, -0.0086932778, 0.0841871798, 0.0758739412, -0.1718271673, 0.0194304138, -0.2104951292, -0.0464355499, 0.0466483235, -0.1867761612, -0.0607739687, -0.0055530816, 0.2062681317, -0.0899071023, -0.1466156542, -0.1700449288, -0.0352381468, -0.1439867318, 0.0279891789, 0.0052996427, -0.1774032861, -0.0753418207, -0.0649657398, 0.0333490521, 0.1913325191, 0.1162198186, -0.1369870305, 0.1173079014, 0.1992448568, -0.0396678150, -0.0303589255, -0.0619280785, -0.0192707032, -0.0790151358, -0.1448483169, -0.0779868662, 0.0969208181, 0.1015408039, -0.0625919849, -0.1346160173, 0.1641981602, 0.0319124758, 0.0982068777, 0.1008815169, -0.0978270769, -0.0016372651, -0.0054634660, 0.1999173164, -0.2003428638, -0.1025240645, -0.0592647344, -0.1252372414, -0.0870438963, 0.1773294210, 0.0137821138, -0.0117748529, 0.1342442334, 0.1442306638, -0.0628429949, -0.0721761286, 0.0534745157, 0.0238779634, 0.1552363932, 0.1699821651, -0.0442073196, 0.1695192456, 0.0530515015, 0.0595406592, -0.1705650389, -0.0639193952, -0.1489825994, 0.0764563382, 0.1519193053, -0.1043368578, -0.0463358760, -0.0165051371, -0.1310031563, 0.2021290660, -0.0560600460, 0.1796547771, 0.1029445529, -0.1228640974, -0.1941508800, -0.0907981694, -0.0546313375, 0.0337099135, -0.0008449703, -0.1432957351, 0.0558494031, -0.0492122471, 0.1636962295, -0.1825852990, 0.1001596153, 0.1829636991, 0.0331404507, -0.1169753745, -0.1455797553, 0.0733731389, 0.0429403484, -0.1705754548, 0.0322585851, 0.1478659511, -0.0472624153, -0.0188592225, 0.1383612156, 0.0260158777, 0.0440246463, 0.1482222080, -0.0436652154, 0.1809160113, 0.1424434483, -0.0133117288, 0.1041171253, -0.0775254816, 0.0607286096, -0.0155260712, 0.1529510319, -0.2055692524, 0.0051077604, -0.1450271308, 0.0847360492, -0.1129557639, -0.0156958997, 0.0518609583, 0.0307663828, 0.1660754383, -0.1019806340, 0.1176193058, 0.1917870939, 0.1363770664, 0.0379193127, -0.0729095191, -0.0966173038, -0.1248160079, 0.2000123560, 0.0094743967, -0.0882367939, 0.1015456319, -0.0674209893, -0.1662264615, -0.1839380711, -0.1320059597, 0.1887626946, 0.2035280466, -0.0533521324, 0.0082952678, -0.1028251871, 0.1246227026, 0.0488411188, 0.1782095134, 0.0781773329, -0.1430292130, 0.1122246981, -0.1704412699, -0.1757664233, -0.1247237027, 0.0092140883, -0.1822572351, -0.0997265354, -0.1050046682, 0.0886016190, -0.0296980143, 0.1983782947, 0.1298699975, 0.0795823932, -0.1162241474, 0.1733252108, 0.0104044974, 0.2047517002, 0.0917622745, -0.0174271017, -0.0020326823, -0.1344762444, -0.0506389737, -0.2100296766, 0.1877582073, -0.0410911739, -0.0063932687, -0.0494657904, 0.1441004872, -0.1969064772, 0.0923915207, -0.1293616295, -0.0393955559, -0.0578577369, 0.1438804269, 0.0814321339, 0.0784842372, -0.1527344286, -0.0276184231, 0.1820350587, 0.0567962825, -0.1889699250, 0.0160314888, -0.1600189805, -0.1148333549, -0.1550061703, 0.0448240042, 0.1842555702, -0.1586228460, 0.0745503008, 0.0607309639, -0.1876632124, 0.1188407838, -0.0673445314, 0.0973199308, -0.0874732137, -0.0405899882, 0.1194924712, 0.1050751805, -0.0377250016, -0.0332672745, -0.1674756259, -0.1423026919, -0.0350551009, -0.0985023156, -0.0951841697, 0.0006961823, 0.0258001387, -0.0484638661, -0.2063206434, 0.1210769415, 0.1295931041, -0.0792551488, -0.1073084325, 0.0022826195, -0.0591862053, 0.1678128541, 0.2003252804, 0.0493347645, 0.0721547604, 0.0598349571, -0.0255390257, 0.0196670294, -0.0521317273, -0.1928784251, 0.0355230570, 0.0934202969, -0.0761632621, -0.1314253211, -0.1957649738, 0.0752701163, 0.0782026350, -0.0987959206, 0.2125548720, 0.1511770189, -0.0734881759, 0.0920494199, 0.1625028849, -0.0768847018, 0.1584999859, -0.1727127433, -0.1644728929, -0.1382983327, -0.1660568416, -0.1793116778, 0.0099412203, -0.0791091621, -0.0846506059, 0.0790362656, -0.0133007020, -0.1654711068, 0.0573849678, -0.1701870561, 0.1805684268, 0.0581678450, 0.0920302570, -0.1281255633, -0.0639522821, -0.1546281874, 0.1244523227, 0.0743416250, 0.0706484020, 0.1799728274, 0.1064555347, 0.2091509700, 0.1711511612, -0.0555743128, -0.1664301902, -0.0028101355, 0.0690938830, -0.1037319154, -0.0864460170, -0.0368000269, 0.0399753749, -0.1528497636, -0.1097660661, 0.1010111272, 0.0987169147, 0.0314895064, -0.0543241203, -0.0520908535, -0.0086442679, 0.0969336629, -0.0699095726, -0.1331691146, -0.2069860697, 0.1236446500, -0.1357996762, -0.1200416535, -0.0506703854, -0.1990199387, -0.1748924255, 0.1290726364, 0.0294344574, 0.1476340592, 0.1509452462, -0.0244340599, -0.1539846659, 0.1124024093, 0.0214278102, 0.1704240441, -0.0724699795, -0.1785931885, -0.1700597256, 0.1837204993, -0.0194244087, -0.1878972501, 0.2055566907, -0.1611421853, 0.1714851260, -0.2007489949, 0.1520946324, -0.1191827133, 0.1413890123, -0.1775853038, -0.0248494446, 0.0703947544, 0.0560485721, -0.1586514711, 0.0541211367, 0.0367946327, -0.0246199518, -0.1869306862, 0.0217935890, -0.0829221010, 0.0873340368, -0.1758350432, 0.1454812586, -0.0828677118, -0.1690293252, -0.2004337013, 0.1523751616, 0.0680314004, -0.0973403752, -0.0847362131, -0.0708044469, 0.0425238609, -0.0822722763, -0.1330907941, -0.0131355971, 0.0557457209, -0.1308217943, 0.0857084095, -0.0758208036, -0.1346733123, -0.1555400491, -0.0969168991, 0.0320490599, -0.1431545615, 0.1276002228, -0.0794734806, 0.2112722397, -0.2054769397, 0.1153905094, 0.0442796946, 0.1386967003, -0.2096072733, 0.1811663508, 0.1794033349, -0.0582896024, -0.0159388334, -0.1149303913, -0.0124904066, -0.0947031081, 0.1242024899, 0.0512652695, 0.0718409419, -0.1800667346, -0.1936214268, 0.1672570705, -0.1238474771, 0.2030343115, -0.0088793188, 0.0576428175, 0.1919571757, 0.1780738533, 0.0743105710, 0.0483388305, -0.1933601499, 0.0573388040, 0.0927100182, 0.0190719962, 0.1921852827, -0.1414444596, -0.0606168956, 0.0225313604, 0.0726953149, -0.0708997101, -0.1291381121, 0.0971594155, -0.0985634699, 0.1121488810, -0.0717573315, -0.0415566415, -0.0751338750, 0.0083053857, 0.1715459824, 0.2018745542, -0.0923625901, -0.0133760273, 0.1272982359, -0.0956774876, -0.1240583733, -0.2114854306, 0.0965881348, -0.0672399253, -0.1880328655, 0.1312022507, -0.1394779086, 0.1825407147, 0.0174094737, 0.1769882441, -0.0735728145, 0.1314514875, -0.0022834241, -0.0012988895, -0.1842794418, -0.1392400265, 0.0068610162, -0.0002130866, 0.1254684627, -0.1400572360, -0.0490175188, -0.1366832256, -0.0835879445, 0.0948438644, -0.1165343672, 0.1079588830, -0.1742309630, 0.0942076147, -0.2069736123, 0.1206722558, -0.1774893850, 0.0393536687, 0.0133828372, 0.0662358105, -0.1072077379, 0.0789229870, 0.0019953251, -0.0018918812, 0.1487488747, 0.0653204024, 0.0895190537, -0.1732241511, -0.1341161430, 0.1755096316, -0.1138452515, -0.0368136466, -0.0363892615, 0.0309521258, -0.0052079856, 0.0354398340, -0.1062960327, 0.1332124174, -0.1448436379, -0.2075458765, -0.1759052426, -0.1594075263, -0.0318089277, -0.1131876037, 0.1570088565, -0.1197258383, 0.0138314217, -0.1105028093, -0.0295597017, 0.1378022134, -0.1440986097, 0.0703257322, 0.0650744140, -0.0353616029, -0.0718922764, 0.1725155115, 0.0594631732, 0.1383387446, 0.1432417035, -0.1360167265, -0.1198626310, 0.1673899889, -0.1245760322, 0.1036848426, 0.0674479604, -0.1988779157, -0.0741225481, 0.1518616080, 0.1727854311, 0.2025708854, -0.1955710053, 0.1098783612, 0.1568675935, -0.1278287619, -0.0991523936, -0.1556450725, 0.1036491096, 0.0829957724, 0.1966727078, -0.0123555511, 0.1867456138, 0.1836900115, 0.1205491126, 0.1161455512, 0.1055618823, 0.0448076427, -0.2055694014, 0.1347579062, 0.0496198237, 0.0014238805, -0.1270311177, -0.1212837622, -0.1498177499, 0.0584974885, 0.2008564472, -0.1326838881, -0.1859655082, -0.0276795775, 0.0559844673, -0.1822595298, -0.0514723510, -0.1829582453, 0.1997265816, 0.0494521260, -0.0760574341, 0.1203515232, 0.0950507522, 0.0931355357, -0.1741347015, 0.1319496334, -0.0033025891, 0.1753038168, -0.1310523152, -0.0321434438, 0.0919113159, -0.1145440266, 0.1372021139, -0.1949167550, -0.1191260889, -0.1971220076, -0.1756067574, -0.1678233147, -0.2006524801, 0.1193429232, 0.2098030150, -0.0447238684, -0.2036878467, -0.0867692530, -0.1309165955, 0.0847793221, -0.1098388508, 0.1825619638, -0.1476746202, 0.2038953006, -0.1721340865, 0.0535374582, -0.1794906557, 0.0754552782, 0.1397316456, 0.1095485091, 0.1933746934, -0.1138690412, 0.1855984032, 0.0389611721, 0.0381172001, -0.0462874323, -0.1968904734, 0.1458078921, -0.0722205937, 0.2060584426, -0.1714447141, 0.0223436356, 0.1825688779, 0.0452565849, 0.1058931053, -0.2038344443, 0.1905703843, -0.1854292452, 0.1800690591, -0.0769351721, 0.1531750858, 0.0848983228, -0.1336221695, 0.1280547082, 0.1484613121, -0.0277594775, -0.1551034600, 0.0823943317, 0.0643174350, -0.0788183063, 0.0762106776, 0.0242073983, 0.0263604075, 0.1125132143, -0.1060078219, -0.1991036981, 0.1918284595, 0.0840535462, -0.1217572540, 0.0472959578, -0.0989014953, 0.2087621093, -0.1823205203, -0.0105943531, 0.0384185910, -0.1028940678, 0.1185675561, 0.0462585092, -0.0512450784, 0.0990857184, 0.2116090953, -0.0509551466, -0.1323211491, 0.1672795713, 0.2000471354, 0.0863650441, 0.0256348997, 0.1485285163, 0.0510468483, -0.0337763876, -0.0341346562, 0.1407789886, -0.0521683246, 0.1687902808, -0.0672319382, 0.1154437959, -0.0787539631, -0.1798828244, 0.1729774177, 0.0052112937, 0.0594650805, 0.0338179171, 0.0396455526, 0.0651315451, 0.0241717249, 0.0589820743, -0.1591632813, 0.1442280114, -0.2010892630, 0.0796580911, -0.1434063315, -0.1692698151, 0.2002624571, 0.1403183043, 0.0042257905, 0.0713099539, 0.0852792859, 0.2020341158, 0.0972422063, 0.1421691179, -0.1759033650, -0.1923001707, -0.1595743597, -0.1895710528, 0.2113615572, 0.1198105216, 0.1897158623, 0.1519897580, 0.1169688702, 0.0630189180, 0.0186039954, 0.0013304949, 0.1581035554, 0.1829706430, 0.1218507886, -0.0516599715, -0.1732880026, 0.1261597276, 0.0492627323, -0.0481002182, 0.0445055366, 0.1528100669, -0.0859618038, 0.1968157589, -0.1851369143, 0.2037501633, 0.1451233029, -0.1401752084, 0.0779571831, 0.0972661674, -0.0483306795, -0.0958286598, -0.1751645356, 0.0244353861, 0.1761728227, 0.0009850562, -0.0998479649, 0.0216421187, 0.1283885539, -0.1615431905, 0.1778119206, -0.2018036395, 0.0518199205, 0.1242860556, 0.0953228772, -0.0126432031, 0.1637348831, -0.0028868914, 0.1344926059, 0.0586344898, 0.1754533648, -0.2111395746, -0.0661977828, -0.1522785276, 0.0873704851, -0.0004187524, 0.1675336361, 0.1108632386, 0.0430812538, -0.1502431035, 0.1938326657, -0.1104866415, -0.0683636963, -0.0831161290, 0.0355570614, -0.2026015371, 0.0559004545, 0.0382340848, 0.0799589157, -0.0211348683, -0.1368488669, -0.1282242835, 0.0260183066, 0.1688709855, -0.0368644297, -0.1862521470, 0.0476023853, -0.0792344213, -0.1053574905, 0.1902099550, 0.1507623792, 0.1542567611, 0.1710912287, -0.0019168407, 0.2112519443, 0.1955697238, -0.1300433576, 0.0924468338, -0.1891560704, -0.0391472429, -0.1859188527, -0.2114342898, -0.1893524379, 0.1264006793, -0.0839566737, -0.1194514036, -0.0930093676, -0.1221729517, 0.0454541147, -0.1912920475, 0.1893217266, -0.1293410361, 0.1383384168, 0.1342498362, 0.1058112085, 0.0181810260, -0.1570251286, 0.1479201913, 0.0062170327, 0.0490781963, -0.2000998408, -0.0083201230, -0.0939723626, 0.1157927513, 0.0630370677, -0.0091766268, -0.0765612125, -0.0905905217, 0.0746472776, -0.0515676588, -0.0877936929, -0.1437296271, -0.2062004805, 0.0459145308, 0.0518745780, -0.0567450970, 0.2010192573, -0.0243847072, -0.0786848813, 0.1182677150, -0.0290865153, -0.0413807184, -0.1611226648, -0.0477492362, 0.0337571353, -0.0053299367, 0.1461633444, -0.1096765473, -0.0238418728, 0.0018897504, -0.1042069793, 0.1136350632, 0.1388032734, -0.0648652017, 0.0302183181, 0.1621866226, -0.1386421025, -0.0704583973, 0.0239891857, -0.1453436017, -0.0245934725, 0.1979980171, -0.0843390226, 0.0007893592, 0.0350620151, 0.2009984255, 0.1280063689, 0.0126281083, 0.0310563296, -0.1027310491, 0.0386101604, 0.0696326494, -0.2083996236, 0.1151551306, 0.0441848934, 0.1600982249, -0.1232326254, -0.0260440856, -0.1348734796, -0.0952562988, 0.1961986721, 0.1452758908, -0.1939922422, 0.0091093183, 0.0370045602, -0.0122943968, 0.1697953939, 0.1073029041, 0.1232846677, 0.1302166581, 0.0340778232, 0.0419728458, 0.1299465299, 0.0913463235, -0.0027413219, -0.1219573766, 0.0513713360, -0.1140092835, 0.2118974030, -0.1113556996, -0.2100419700, -0.0568319708, -0.0482634902, -0.0355322957, 0.1515703499, 0.1702822149, -0.1693487465, 0.2012262940, 0.1006334126, 0.0732228756, 0.1557646692, -0.1909618974, -0.1565110236, 0.0937556624, 0.0888049304, -0.0952448621, -0.0188108236, -0.1042839885, 0.0419894755, -0.1621105671, -0.0983826593, -0.0272268206, -0.1381223500, 0.0549430847, -0.0194458663, 0.0039207488, -0.1663725376, 0.1870987415, -0.1859398931, 0.1687123477, 0.0482874215, -0.1615109742, 0.0982285440, 0.1731853783, 0.1082703173, 0.1116540730, 0.2082655728, -0.0078319907, 0.2052211761, -0.0949357599, 0.1129602194, 0.1065994501, 0.0399096012, 0.0829414725, 0.1299278736, -0.2051162422, 0.0627848506, 0.1472616196, -0.1903744340, 0.1651630700, -0.1418522298, -0.0410842746, 0.0962750018, 0.0493612885, 0.1878988147, -0.0499424338, -0.0915017724, 0.0851533711, -0.0916376412, -0.1698620021, -0.1871181130, -0.0783956498, 0.1575850844, -0.1168074310, -0.1657191664, -0.0658403933, 0.1936830878, 0.0523431897, 0.1185898781, -0.0176909715, -0.0143125355, 0.0721827745, -0.0973571986, 0.0904549956, 0.1836954057, -0.0886407495, 0.0323009789, 0.1663124263, 0.0151741803, 0.0074783564, -0.0942574739, 0.1947118938, -0.0421919227, -0.1184858158, 0.2109894753, -0.0226028264, -0.1724603176, -0.2043152004, -0.0026250184, -0.0081331134, -0.1256359667, 0.0432811379, 0.0452671051, 0.0373051465, -0.1479172260, -0.1526697725, -0.0647729933, 0.1266577542, 0.1120478809, 0.1817023754, -0.2120599747, 0.0862949491, 0.0168930739, -0.2018598616, -0.1736362427, -0.0817916691, -0.0788579136, 0.0714763403, 0.0890515149, -0.2124472558, 0.1023100317, -0.0289710313, 0.1125129759, 0.0315441042, -0.0292290002, 0.0617497563, 0.0402621329, 0.0301108211, 0.2063018680, 0.1398603022, -0.1295326203, -0.0214233398, 0.1308341920, 0.0003687292, -0.1712298542, 0.1937851012, 0.0021202117, -0.0376309156, -0.0598136187, 0.1916348040, 0.1275726259, 0.1723597646, 0.1401208639, -0.0029467195, -0.1655184329, -0.1739171445, 0.2098056674, 0.0084194988, 0.0375558734, -0.1408582330, 0.0006600469, -0.1534451544, 0.1627846956, -0.1271483898, -0.1370807290, 0.1105353534, -0.0278621614, -0.0206038952, 0.1613380015, 0.1314874887, -0.0099503249, -0.0465818495, -0.0490111560, -0.1488530338, -0.0213380009, 0.1212062538, 0.0407195985, -0.1816841662, -0.0523589998, -0.1792617738, 0.1531568468, 0.0089685768, 0.0235614926, -0.0178877860, 0.1825806797, -0.1412900835, 0.1882363856, 0.0958912671, -0.1089919060, -0.0834980160, -0.0736042261, 0.0398091674, -0.1313294470, -0.0783142149, 0.0504100323, 0.0822021961, -0.0462735593, -0.1051808000, 0.0246717483, -0.0896309838, -0.0401306301, -0.0251594186, 0.0796609521, -0.1438814104, -0.0223538578, -0.0244199783, 0.1629701853, 0.1265147924, 0.0364100039, -0.0175888985, -0.1557615250, 0.0770325661, -0.1606579125, -0.0355778933, 0.1474189758, 0.0702895820, -0.2091641724, 0.1953218877, 0.0043252558, 0.0129832029, -0.1255178303, 0.0872347653, -0.0282660574, 0.1322372854, 0.0334073156, 0.0594078302, 0.1398628652, -0.0369449407, 0.1382974684, 0.0596849620, 0.0111430287, 0.1559647024, 0.1321473718, 0.1628567278, 0.0509160459, 0.1169908643, 0.1601838768, -0.1885716617, -0.1836548895, 0.1762075722, -0.0656511039, -0.1660412848, 0.1848152578, -0.2090318203, -0.1517060250, 0.1312254369, -0.1492921561, 0.0980155170, 0.1366658807, 0.1977568865, 0.1404947937, 0.1480135918, 0.1731882691, 0.0772440135, 0.0025944114, -0.1132899225, 0.0496724248, 0.1860830486, -0.1336355954, -0.0278831422, -0.0055948198, 0.1560053527, -0.0739876330, -0.0067940801, -0.1273649335, 0.0620990396, 0.1703686118, 0.1816574931, 0.1523585916, -0.1919798404, -0.0987751260, 0.1137881577, 0.1714571118, -0.0949567556, -0.0509785265, -0.0433674455, 0.0025682300, -0.1018572673, 0.2032278180, 0.1624566317, -0.1094431356, 0.1545654237, -0.0564386845, -0.0159603804, 0.0222223550, -0.1085324958, 0.0756898224, 0.0739400983, -0.0236016512, -0.1739635020, -0.0718785524, 0.1224631369, 0.0379896164, -0.2022826672, 0.0342850089, 0.1086674035, -0.0425202996, -0.0250317305, -0.0254981518, 0.1734285057, -0.0076459050, 0.1249652505, 0.1001253128, -0.0738305748, 0.1741576195, 0.1829492152, -0.0310747325, 0.0060606301, 0.0945225060, 0.1241886616, -0.0296901464, 0.0009692907, 0.0344382077, -0.0205199718, -0.1175931245, -0.0696323812, -0.1005026698, 0.0062219203, -0.1890629530, -0.1190022081, -0.1363080889, -0.1013581082, 0.2035762072, 0.1073179841, 0.1970246136, -0.0273063630, -0.1769396067, 0.0624212325, -0.1262149811, -0.0768698156, -0.0423385203, -0.1450702250, -0.1801055074, -0.0268956572, 0.0560451150, -0.1114352494, 0.1087172627, -0.2066947520, -0.0380227119, 0.0018448085, 0.1122630239, 0.0720984936, 0.0490970612, 0.0986473858, -0.0048467368, 0.0085182041, 0.1405288875, 0.1927247047, -0.1678233147, 0.0235735923, -0.0336104333, 0.1021865904, -0.0218194127, 0.0798167288, -0.0714006424, 0.0763245523, -0.2099650204, 0.1664243340, 0.0584085882, 0.2119176984, 0.1464650333, 0.2063736618, -0.1791144609, 0.1117559969, 0.1103233099, 0.1025905907, 0.0931468010, -0.2046590745, -0.0736854970, -0.0054731816, -0.0823983401, -0.0584122092, 0.1528870165, 0.1687346697, 0.0803000331, -0.0039590746, 0.0534914136, 0.0935313106, -0.0145738572, 0.1680481434, 0.1247592270, -0.1519022733, 0.0225370526, 0.2074175775, 0.0663752258, -0.0572958589, 0.1314680576, -0.0081505477, 0.1502386928, 0.0843608379, -0.0505757928, 0.0318961591, -0.1350189149, 0.2059093714, -0.1096357852, -0.0237801224, -0.0912672877, -0.0329676718, -0.0144457668, 0.1773395538, 0.0272649378, -0.0634466112, -0.1111930907, 0.1688987911, 0.0674479306, 0.1422763169, 0.1402884126, 0.1684876680, -0.0936151668, -0.0196692646, -0.1291329861, 0.1792899370, -0.1618148834, 0.1808791459, 0.1992952228, -0.1180936098, 0.0815925598, 0.1380904317, -0.1840451658, 0.1549934149, 0.0875937343, -0.0849592090, 0.0974246562, -0.0104719996, -0.1704319566, -0.1461453140, 0.1322407424, -0.0554242581, 0.0936799943, -0.0386036634, 0.1452425122, 0.0899178684, -0.0412901789, 0.0560518205, -0.1611335427, 0.1422611177, 0.1953564882, 0.0727872550, 0.0488506258, -0.1748843044, -0.1653818488, 0.1663266420, -0.1325635165, -0.0699115545, 0.1830326617, -0.0022758096, 0.0998718441, 0.1550491154, 0.0415105820, -0.1932657659, -0.0377684534, 0.1460716128, 0.2040894628, -0.1827876568, 0.2034503520, 0.0465519428, 0.1580714285, 0.0621053874, 0.1651513875, 0.1507709920, 0.1027133167, 0.1883013546, -0.1740298271, 0.1747498512, -0.0905787274, 0.1860815585, -0.0746505708, 0.0537184179, -0.0758107007, -0.0454756021, -0.1685490757, -0.1549349576, -0.1699792594, -0.2082224786, 0.1378434300, -0.1509437114, -0.0446635783, -0.1351365447, 0.0446104705, -0.1861547530, 0.0029438734, 0.1290639639, -0.1048939601, -0.0368072987, -0.1131323949, -0.2130697817, 0.0702968538, -0.1823674440, -0.1840161979, -0.0068235993, 0.1415870786, 0.1259913146, 0.0572944880, -0.1511217207, -0.1518146992, -0.0302279294, 0.0081147105, -0.0265112668, 0.0647821426, 0.1110815108, -0.1381454766, 0.1686417460, 0.1248066425, 0.1109326482, -0.1001610830, 0.2065006196, -0.1484271139, 0.2000478804, 0.0129306018, 0.1010906696, 0.0494739711, 0.1341028810, -0.0126507729, -0.0906337276, -0.0796923041, -0.1187514141, 0.0626639128, 0.1592695117, -0.0600781441, -0.1760297269, 0.1624909341, 0.2064928412, -0.0690795928, 0.1862381101, 0.0610037744, -0.0018520802, -0.0035834312, -0.0278175771, -0.1491471827, 0.1348098814, -0.0514868349, -0.1080121920, -0.1104326621, 0.2023530304, -0.0406453907, 0.0713945329, 0.1608239710, -0.1471444964, -0.2112867832, -0.0019274056, -0.1672579646, 0.1421840489, 0.1175822914, -0.0851505399, 0.1390727758, -0.0979966521, -0.1673496217, 0.0396300852, 0.1642152369, 0.1630523801, 0.1590069234, -0.1655886769, -0.0681497008, 0.0405101776, 0.1699393094, -0.0245542228, -0.1818218231, -0.0424215794, 0.0926091373, -0.1783550382, 0.1543887854, 0.0718891919, -0.1927368641, 0.1659371257, 0.1914150417, 0.1347251534, 0.0423839688, -0.0580154210, -0.0447445065, -0.1811912656, -0.1356982589, 0.0058128387, 0.0032359511, 0.1545306444, -0.0575654060, -0.1548760533, -0.1092362031, -0.1805575043, -0.1575052738, -0.0652302206, -0.0790501535, 0.1490799487, 0.0498728454, 0.1736911535, 0.0337035507, 0.0347825885, 0.1907315850, 0.0940455198, -0.1271450371, -0.1469286680, 0.0499047041, -0.1211973503, 0.1857516170, -0.1012217775, 0.1606440544, 0.1949877143, 0.0010551512, 0.1897149086, 0.0091839880, -0.0053898692, 0.0590130389, -0.0634863079, 0.0069778711, -0.0761531889, 0.1508392990, -0.0640203953, -0.1421354562, 0.1939566135, 0.1684629321, -0.0360288620, -0.1836050153, 0.0923433304, 0.0136799514, -0.2008460909, -0.1974148452, 0.0965938270, 0.1779162288, 0.1597458720, -0.0529540777, -0.1671065390, -0.1075444445, 0.1343218088, 0.1139514744, 0.0594527125, -0.1444732845, 0.0543672740, 0.1798780859, -0.0765798688, 0.1536311805, 0.0859356225, 0.1940051615, 0.1727126539, 0.0379105210, 0.0009198934, -0.1782970428, 0.0198643059, 0.0361964107, 0.2025280297, -0.1845655739, -0.0162867159, 0.1495032609, 0.0997734070, 0.0528253615, -0.2013835311, 0.0945262611, -0.1260560751, -0.2058556378, 0.0438373685, -0.1610147059, 0.1749124229, -0.1420629621, -0.1523222476, 0.0423185527, 0.0682304204, -0.1083713099, 0.1326313913, -0.1834546626, -0.0828554183, -0.1987082362, 0.1442075372, 0.0832913816, -0.0681697726, -0.0933425650, -0.1998527944, -0.2001420259, -0.0934497640, -0.1489324868, 0.1759579480, -0.1881609559, 0.1892626584, 0.1499628127, -0.2007803619, 0.1305122972, 0.0622969568, 0.1794747412, 0.0820458233, -0.0254466087, 0.0773642957, -0.0267990828, 0.0644598305, -0.1568169296, 0.1258660853, -0.1860484630, 0.1883485615, 0.1727247536, 0.1197294891, -0.1694395840, 0.1129588187, 0.0532492101, 0.1438889802, 0.0986272693, -0.0438405275, -0.0657222122, -0.0719935447, 0.0421020687, -0.0541504771, 0.1208387911, -0.2131919265, 0.0039448440, -0.0854387432, -0.1607017815, 0.0815662742, 0.1249569058, 0.0407440066, -0.1564131677, -0.1577273607, -0.1736676693, 0.0977464616, 0.0630435646, 0.0068023056, 0.0708548129, 0.1436045170, 0.0072188228, -0.1178695410, 0.1501477957, 0.0042518079, 0.1290286183, 0.1199949980, -0.0904974490, -0.2128094137, 0.0700814426, -0.1686827689, 0.1664354205, 0.1718768477, -0.1842298806, 0.0531402528, -0.0238433480, -0.2039491236, -0.0819852352, 0.1844753027, 0.0296037793, -0.0350253582, 0.1872778535, -0.1650556624, -0.0567166358, 0.1191662848, -0.1457097828, -0.0642208606, 0.0548260212, 0.1760723889, -0.0513615906, 0.0929824710, 0.1938198209, -0.0034515262, 0.1158276498, -0.0828904361, 0.0234277099, 0.0763218999, 0.1054467559, 0.1146610975, -0.0648252517, 0.0624802113, 0.2022757232, -0.1753597260, 0.1490517855, -0.1511972994, 0.1661396027, -0.1716566384, -0.0434365273, -0.1507773399, 0.0630852878, -0.0973015353, -0.1589654088, -0.1886912286, 0.2025721669, 0.1810853183, -0.0706967413, 0.0383313596, 0.1245371401, 0.1146691144, -0.0449625701, 0.0436422825, 0.1395887136, -0.1616845131, 0.1066615582, 0.1780829430, -0.0645134449, 0.1557524800, -0.0882606283, -0.1103699356, -0.1888148487, 0.1427669227, -0.0163445026, -0.1656727493, -0.0337721258, 0.2112357020, 0.0161519647, 0.0182989091, -0.1249348521, 0.1998015642, -0.2016466260, 0.0259066820, 0.1043611467, -0.0022014976, 0.1776066720, 0.1349163353, 0.1535488367, 0.1053943336, -0.0207833797, -0.0530792624, 0.0430369377, 0.1755416393, 0.0766601861, -0.0773406029, 0.0147576630, 0.0559092760, 0.0843859911, -0.1002954841, 0.0615185797, -0.1131670624, 0.0017252117, -0.1220274195, -0.1376246065, -0.1835173368, -0.1174220815, -0.1680146903, -0.1507832408, 0.1809541285, 0.1313103437, -0.1905061454, -0.0216181725, -0.1844664514, -0.0534408838, -0.2044046670, 0.0049962848, -0.1204927266, 0.1276222467, 0.0318249911, -0.1870529354, 0.1569690108, 0.0279721469, 0.2019387484, 0.1913354099, -0.0546239167, -0.1964109242, -0.1925244331, 0.0739316642, -0.1145623252, 0.1245226264, -0.1919418126, -0.0579973161, -0.0511387438, 0.0103970766, 0.1590977013, 0.1299258471, 0.0437954962, 0.1557581723, 0.1993747354, 0.0341538638, 0.0599365234, -0.1906317025, -0.1545984149, -0.1063477322, -0.1067869589, -0.1613583267, 0.1209427416, -0.0941306502, 0.0978935659, 0.1584370136, -0.0206309855, -0.2008893490, 0.0891769528, 0.1714769900, -0.1579600126, 0.0751194954, -0.0583976209, -0.1104251891, 0.0307909846, 0.1872331798, -0.1938214451, -0.2099076360, -0.0078707188, -0.1876039505, -0.1131740287, 0.1190108061, 0.1344430447, -0.1948728263, -0.0047534555, 0.1290161610, -0.1333805770, -0.0967373103, -0.1476974785, -0.1990575939, -0.1990798116, 0.1665185988, 0.0363839716, -0.1362581700, -0.1713395417, -0.0987100676, -0.0854968429, -0.1141184196, -0.0776877850, 0.0548579991, 0.1284639835, 0.0501741171, -0.1944070756, 0.1335031390, -0.0683825612, -0.0699648261, -0.0992463827, 0.0448395014, 0.0899653435, -0.0744938701, -0.0096022338, 0.1873570085, 0.0732779801, -0.1916254908, -0.0531954616, -0.0220243633, -0.1768929362, 0.1347981393, -0.0774987340, -0.1386564374, -0.1722143590, 0.1197276711, -0.0297907889, 0.0230280310, 0.1581282616, 0.0137360692, 0.0143634677, 0.0532052815, 0.0497603118, 0.0923163891, -0.0899877176, -0.0450925976, -0.1556188911, -0.0994720757, -0.1373393983, -0.0370617509, -0.1319033206, -0.0236480683, 0.0797799826, -0.1062793136, 0.0500923395, 0.0054854304, -0.0232686102, 0.0268861502, 0.1068070829, 0.1481148601, -0.0765626878, -0.2049585134, -0.2074185312, 0.1376159191, 0.1162165105, 0.1596168578, 0.2111602724, -0.1718850732, -0.1022058651, 0.0040615499, 0.0975148380, -0.1960753500, 0.0795379877, 0.1664321125, -0.1130281910, 0.1508635581, -0.1652863920, 0.0242457390, 0.0055758506, -0.0306469351, -0.1158140376, -0.0395158827, -0.0917486027, 0.0528489947, -0.1595364809, 0.0755034685, 0.0998315513, -0.0077430904, -0.0779739022, 0.1347191036, 0.0529284477, -0.1888697445, 0.2032252252, 0.1789621711, 0.0117135048, -0.0093316138, 0.0515504181, -0.0069679618, 0.0242062807, 0.0760845244, 0.1489381790, -0.2005273253, 0.1012580693, 0.1794412434, -0.0231635869, 0.1566728652, -0.0870216787, 0.1510018110, -0.0404780507, -0.0720026940, -0.0239696652, -0.1116491482, 0.1134687364, -0.0718342364, 0.0246311873, 0.0601386726, -0.0144272596, -0.0647571385, -0.0739642531, -0.0646997988, 0.1861934364, -0.1823046654, 0.1959239542, -0.2009767294, -0.0160039365, -0.0794434398, 0.1750234663, 0.0874374807, 0.1707782745, 0.1825541854, -0.0467963964, -0.0234479457, -0.1295272261, -0.0882118866, 0.1365664005, 0.1647350192, 0.1123317480, -0.1775737703, -0.0438817590, 0.1012901366, -0.0697916448, 0.0002094805, -0.1149990633, -0.0234351307, -0.1668582857, 0.1332397759, -0.0910778865, -0.0948271379, 0.1515246630, 0.0342892855, 0.0003544390, -0.0739539862, 0.1579813659, -0.1103885919, -0.1934318841, 0.1029623449, -0.1023991257, -0.1770507097, 0.1144099236, -0.1180014014, -0.1217893288, -0.0216405988, -0.2123173326, 0.1234333515, -0.0110137612, -0.0702448487, -0.1057308912, 0.0890272558, 0.1160265207, 0.1072906852, -0.1487851739, -0.0729204863, 0.0325599611, -0.1984154582, 0.1357439160, 0.1908751130, -0.1651226133, -0.0818393081, -0.0859399438, -0.1118555740, 0.1012180746, -0.1372910589, 0.1543109715, -0.0700101107, -0.1153733879, 0.1927016973, -0.1514202058, -0.0399074256, -0.1110946834, 0.1895937324, 0.1058147252, 0.0465854406, 0.0037314594, 0.0336747766, -0.0988306329, 0.1484581232, -0.0304508209, -0.0265737921, -0.1864701658, -0.0615098476, -0.2006002665, -0.0114497393, -0.2109055966, 0.1424169540, 0.1540012062, -0.0719988793, 0.0591722727, 0.2031416595, -0.0165841281, 0.1612119377, -0.0742466301, -0.1312684417, 0.0608208776, -0.0316384435, -0.0817120224, 0.0872193575, 0.1956618726, -0.0404774398, 0.1140631735, -0.0501891673, -0.1804451048, 0.0997518897, -0.1699244082, -0.1335892379, 0.1278506219, 0.0197480470, -0.0585744530, 0.0234824568, -0.1051296145, 0.0362330079, -0.1587586254, 0.0151935965, 0.0355547667, 0.0052086562, -0.1169655174, -0.1713310182, -0.0385859758, -0.0837848634, 0.1440131068, -0.0401693135, -0.0738870949, -0.0715562850, 0.0477899909, -0.0151329041, -0.0192564577, -0.1984879375, 0.1764692068, -0.0540780425, 0.1339556873, 0.1013427079, 0.1356646121, 0.0366824567, -0.2079485506, 0.0675307810, 0.0513723493, -0.0202654600, 0.0328555405, -0.1610383391, 0.0330421478, -0.0760183930, 0.0774135888, 0.1138041914, 0.0724302232, 0.0473278463, 0.0798558295, 0.1625003517, 0.1401090324, -0.0781959444, 0.0051681399, -0.0166549385, -0.1576520801, 0.0759117901, -0.1660232395, 0.0300527215, -0.0842814296, -0.1780070066, -0.0144460648, -0.1311115324, -0.0554333478, -0.0296566933, -0.0202657580, -0.1877194941, 0.0399649739, 0.2036542892, -0.0825829059, -0.1474654377, 0.1191262007, 0.0360662788, 0.1118718386, 0.1384701431, -0.0842552930, 0.1759040654, -0.1586447060, -0.1873539686, 0.0091989934, -0.0039460659, 0.0245167613, 0.1099811196, -0.1016512513, 0.1695171595, -0.1549521983, -0.0917722955, -0.0526238680, 0.1569677293, 0.0747935176, 0.1457156241, -0.0392616242, 0.0045026094, 0.0586986244, 0.1585946977, 0.0240565389, 0.0721940100, -0.0179607868, -0.0745855123, 0.1442858577, 0.0884040296, 0.1972596943, 0.1373186111, 0.1396714151, 0.1481304765, 0.2042340338, -0.1433375180, 0.1879104972, 0.1883034706, -0.0375428647, 0.0876332223, -0.1979481578, 0.1876739562, -0.0831981152, 0.1516041160, -0.1019506454, -0.0926410481, -0.2048652470, -0.1704465002, 0.0091331154, -0.0848201811, -0.0127605647, -0.0296472460, 0.2019983232, 0.1860531569, 0.1715733707, -0.1858924627, 0.1668051183, -0.1521826088, 0.1237525642, -0.0924146920, 0.1166935265, 0.1696141362, 0.0671969652, -0.0248258710, 0.0338087231, -0.1298024356, -0.1412873417, -0.0938943326, 0.0255146325, -0.0767071545, -0.1595285088, -0.0689493716, -0.1350239515, -0.0762471259, -0.1737507731, -0.0865042210, 0.1237120032, 0.1740107238, 0.1906027198, 0.1435766220, -0.0496110618, 0.2051031291, -0.1019685343, 0.1054754555, -0.1568296850, 0.0534400046, 0.1224918664, -0.0571731478, -0.1844448447, -0.1931433082, 0.1145355999, 0.1861183643, 0.2112169862, -0.2071847171, -0.1183616370, 0.0267622173, -0.0111140013, -0.0748765171, -0.0343641043, 0.1867268980, 0.0073581487, -0.1785207093, 0.0156961530, -0.0324758887, 0.1932121813, 0.1859124005, 0.1032010913, -0.0417507589, -0.0692599416, -0.0419545919, -0.1674657762, 0.0691252351, -0.0761830360, -0.0556465387, 0.0874100626, 0.0407373905, 0.1677820981, -0.1047263220, -0.0004046112, -0.1613337100, 0.0772895217, 0.1394611299, -0.1292207241, 0.1378256083, 0.1551188529, 0.0093925595, -0.1140830368, 0.0083839595, -0.1780405492, -0.1162949502, -0.0319907516, -0.2126251012, -0.0337369442, 0.0166796893, -0.0834767222, 0.1906233728, -0.0643443912, -0.1505066603, -0.2028512210, 0.1418441832, 0.0258653611, 0.2078367770, 0.1635337472, -0.0844045877, 0.1793107092, 0.1728874147, -0.1903070360, 0.1823727190, 0.0281185955, 0.1103662848, 0.1913473010, 0.1985392869, 0.1925708055, -0.2113988549, -0.1326120645, -0.0053517967, 0.1622230113, -0.0963383913, 0.0758258998, -0.1000966355, 0.2115381956, 0.1619590819, 0.0606486797, -0.2107422203, 0.0434962511, 0.0496878326, -0.0737221986, -0.1311294138, 0.0231507868, 0.0533021986, 0.2003799677, -0.2059152126, -0.1476105750, 0.1615459025, -0.0945557505, -0.1844131798, 0.0907543898, -0.0892151371, -0.0803146809, -0.1402549595, 0.1689867973, 0.1396781802, -0.0881352276, -0.0759515911, 0.0551408827, 0.1586233675, -0.0432564318, 0.0208853930, -0.0288933069, -0.1734358221, 0.0157984346, -0.2012790740, 0.0118523687, 0.0947940350, -0.0750545859, 0.0994751751, 0.0760326087, -0.0599491745, -0.1075237021, -0.0623507500, 0.0252066404, -0.1730477214, 0.0188627839, 0.0291252583, 0.0546479225, -0.2006445974, -0.1803621650, -0.1530943662, -0.2109929770, 0.0681557357, 0.1000976861, -0.0689093620, 0.0986846983, -0.1617750823, 0.1346070766, -0.1434522867, 0.1873315871, -0.0810629129, 0.0585987568, -0.2078234553, 0.0861922204, -0.1149285138, 0.1015041471, 0.0587496758, -0.0816388279, 0.0329773873, -0.1751419157, 0.0617503226, -0.0125437230, -0.0608698875, -0.1515468657, 0.0312709361, 0.0630266964, 0.0740807056, -0.0399111360, -0.0375293493, -0.0139126033, 0.0200311840, -0.0200245231, -0.1484813988, 0.2052195966, 0.0477811992, 0.0990149975, -0.1714024246, -0.2094894946, -0.1313878894, -0.1148661450, 0.0304362923, 0.0647411346, 0.0184717923, 0.1958904266, 0.0704886317, -0.2035749555, 0.1110543609, -0.0554997325, 0.1144627333, -0.1712825596, -0.0720108747, 0.1296592355, 0.1444630623, -0.1581989676, 0.1138352454, -0.1145668477, -0.0837427229, -0.0041969121, 0.1294562817, 0.0548149943, -0.2026207447, -0.0274128020, 0.0741438866, 0.2122734189, 0.1474706233, -0.1592406482, 0.1181590259, 0.0398111939, -0.0797617882, -0.0818977058, -0.0535846353, -0.0138099790, 0.0738448501, -0.0227702558, 0.0595405102, 0.0758373141, 0.1493564546, 0.1753648520, 0.2115623355, 0.0326047838, 0.0795084834, -0.1598423868, -0.0082726479, -0.0116433501, -0.0979276747, -0.0745778382, 0.0494920313, 0.1692018509, -0.1930025518, -0.1778339744, -0.1058364213, -0.2035454214, 0.1553150117, -0.1060210392, 0.1822800636, 0.1885613501, 0.1408819556, -0.1401152760, -0.0881394446, -0.0391691625, 0.1795762181, -0.1603543609, 0.1908683181, 0.0162536800, -0.2088878602, -0.0978953987, -0.1938916445, 0.0695549250, 0.1291896701, -0.0831993371, -0.2024009079, 0.1975736916, 0.0419121087, -0.1825169325, -0.0131265521, -0.0304873288, 0.1385656893, -0.1155586168, -0.0952081606, 0.1655867398, 0.1476935148, -0.1647372097, 0.1462611556, 0.0466453433, 0.0614350736, 0.1485420465, 0.1639919877, 0.0604065061, 0.2065810859, -0.1950193793, -0.0875226706, -0.1095805839, -0.0771680325, 0.1688233614, 0.1457514167, 0.0789042711, 0.0510345995, -0.0439327359, 0.1476272345, 0.0209182799, -0.1571552157, -0.1447319984, 0.1360955238, 0.1790454686, -0.0366974473, -0.0223669112, -0.2093652189, 0.0970938802, 0.0873357058, -0.1303490102, 0.1705565453, -0.0405270606, 0.0477897823, -0.1483874172, 0.1627970040 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w2.h b/model/AE_model/hls4ml_prj/firmware/weights/w2.h deleted file mode 100644 index b9d880d..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w2.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [100, 32] -//Min -0.213195428252 -//Max 0.213079929352 -//Number of zeros 0 - -#ifndef W2_H_ -#define W2_H_ - -#ifndef __SYNTHESIS__ -model_default_t w2[3200]; -#else -model_default_t w2[3200] = {-0.0747238696, 0.0702665448, -0.2050665915, -0.1304139793, 0.1610298455, -0.1810131520, -0.0231247544, -0.0361172110, 0.0461444557, 0.0359051973, 0.0760371387, -0.2113457471, 0.0999777019, 0.0359689891, -0.1927438825, 0.0936444104, -0.1948066503, 0.0397396982, 0.0563738942, -0.1845022887, 0.1011802554, -0.1888832152, -0.1760497987, -0.1750413775, 0.1093027294, 0.0974972248, -0.1233510599, -0.0611993670, -0.1355045438, 0.1683713198, 0.1798975170, 0.0213785619, -0.0560328066, -0.1530482173, 0.0548693240, 0.0343294889, -0.0711358637, 0.0912140608, 0.1809859574, 0.1149189472, 0.1054931581, -0.0636578053, -0.0942127407, 0.1773730516, 0.2120944262, 0.0772497058, 0.0976216793, 0.1192027032, 0.1474955380, 0.1808525324, -0.1679046899, 0.0302044004, -0.1142014265, 0.0415002108, 0.0487659574, -0.0340339541, 0.1995163858, 0.0966926217, 0.1879581511, -0.1030610502, -0.1011514291, -0.1468277574, 0.1659207642, -0.1842445284, 0.0208937377, -0.2034995109, 0.1920813918, 0.1997976005, 0.1374559999, -0.1527216285, -0.0834722519, 0.0123545229, 0.0552387834, 0.0926317871, 0.1921240985, -0.1326754987, -0.1813822836, -0.0326681733, 0.0065337121, -0.1843209714, 0.0786501765, -0.0897448957, 0.1941747069, 0.1248153448, 0.1492989063, 0.1165934801, 0.1772582233, 0.1636407971, 0.0535315573, 0.1117191911, 0.0433555543, 0.0710774064, 0.1352140903, 0.0605131090, -0.0881200880, -0.0305309892, 0.0763566196, 0.0928750336, -0.1551524103, -0.0275730342, 0.1828040183, 0.1478491127, -0.0047877729, 0.1009497941, 0.0961081386, 0.0965725780, 0.0553318560, 0.0013379157, 0.0985064209, -0.0789774209, 0.0182258189, 0.1944918633, 0.1619832516, -0.0111588240, 0.0247146487, 0.2024116218, -0.0613928288, -0.1978193074, -0.1667818874, 0.0785077810, 0.1043009162, -0.1804296076, 0.0209509730, 0.0505620539, 0.0428503454, -0.1396937966, -0.0319835395, -0.0479197204, 0.1023346782, -0.1610890180, 0.1083749235, -0.1606936604, -0.0941008106, 0.0156576782, -0.1311611831, 0.0280482024, -0.0584021956, -0.1437120289, -0.0527850091, 0.0450398922, 0.1743397117, -0.1097086221, -0.1784005910, -0.1217441857, 0.0298525393, 0.0874874890, -0.1523758769, 0.1969851255, 0.0338514149, 0.1471830904, -0.1563977748, 0.0323705077, 0.0171378851, 0.0746625364, 0.0708424747, 0.0754641891, -0.2068636715, 0.1751983464, 0.1664066911, -0.1142128110, 0.0260509402, 0.1997905970, 0.1474956870, 0.0921829641, -0.2072199881, -0.0147853196, -0.1459300816, -0.0892340988, -0.0889594033, -0.0213264525, 0.2104727328, -0.1749198288, -0.0741588920, -0.0848147422, 0.1499308944, -0.0320727378, -0.1704946905, 0.1370982528, -0.1597510427, 0.0103891939, 0.1807686388, -0.1413751245, -0.0901559144, -0.1192921996, 0.1687165797, -0.2074870616, -0.1928701401, -0.0669201016, 0.1421534419, -0.1442528218, 0.0908613503, -0.0952229574, 0.2038098872, -0.0267766118, 0.0151951164, 0.1892472506, 0.2125876546, -0.1569796354, -0.2104967088, 0.0884851515, -0.1223398298, 0.2005375922, -0.1431695074, -0.2004103661, -0.0165345669, 0.1019257307, -0.1666406840, 0.1041443050, 0.1377868652, 0.0636464655, -0.0799396485, 0.0861123502, 0.1729778945, 0.1917064190, -0.1925877780, -0.0982609242, 0.0424757600, -0.1279396266, -0.1854511499, 0.1656659544, 0.1626098752, -0.1451410949, 0.1050138772, 0.0140170008, -0.0016366541, -0.1785351932, -0.0096530616, -0.1227467284, 0.2013838887, -0.0196719617, 0.1457566619, 0.0698645711, -0.0506878197, -0.0471427590, 0.2125827074, 0.0489243269, 0.0402944684, -0.0839135051, -0.0288685113, -0.1964230835, -0.0570136905, -0.0616854131, -0.1989611685, 0.1908734441, -0.1933027208, 0.1848526597, -0.0239524394, -0.0085199922, 0.1121234000, -0.1739788949, -0.1694386750, 0.0083744079, 0.1795202494, -0.0554620773, -0.0602274835, 0.1674101651, -0.0737326741, 0.1095213592, -0.0379525721, -0.0252632648, 0.0479144752, 0.0578884780, -0.1163546816, 0.2028668225, -0.0403439105, -0.0248067081, -0.1026851013, -0.0549643934, -0.1903476566, -0.0831966400, -0.0815107822, 0.1428983808, 0.1499240398, 0.1336150169, 0.0306331515, -0.1386979073, 0.0693302453, -0.1745532900, -0.0618710965, -0.0677071065, 0.1083213389, -0.1957625747, -0.0262940675, 0.0788343847, 0.0354494005, 0.0325540155, 0.0333747715, 0.1720476747, -0.0050642937, 0.0154831707, -0.1973226815, 0.1037870646, -0.0082861632, 0.0791448057, -0.1626487225, -0.1265460849, 0.1839307547, -0.1693492085, 0.1280570030, -0.1016471311, 0.0476514399, 0.0513041019, 0.0320510864, -0.0869730860, 0.0718724132, -0.0137081146, -0.1089694872, 0.0720199347, 0.1315560937, 0.0817287564, 0.0773424208, -0.0913953781, 0.1013099253, -0.1286484152, -0.0467070341, 0.0211089551, 0.0025796741, 0.2097119689, -0.1783920527, -0.1623266935, 0.1405432224, 0.0569670200, 0.1915337443, 0.1316097677, -0.1873059273, -0.1660270989, -0.0686397552, -0.1768479049, -0.1941861510, -0.1430532634, -0.1345467418, -0.0608831942, 0.1528359950, -0.1801085621, -0.1618970335, -0.0384509116, 0.1670229435, -0.0734604150, -0.1029334590, -0.0753931701, 0.0075235516, 0.0085687339, -0.1843736917, 0.0329272598, 0.1680009067, 0.1883189380, 0.0350664407, 0.1527980864, 0.1766326427, -0.2059459686, 0.0709660947, 0.0986067653, -0.1684172153, 0.2084665298, 0.1004770994, -0.0400849879, 0.1573551893, 0.2078708708, 0.2048985958, 0.1998811662, -0.1924828142, -0.1506332308, -0.0651212335, 0.0612077713, -0.1890182197, 0.1755529344, 0.0698769987, -0.0095744282, 0.0152651668, -0.0292068422, -0.1200814024, 0.0461067855, 0.0474772453, 0.0015643686, 0.0931799114, -0.1282588840, 0.0867186785, -0.1885387897, 0.0013438165, 0.1249091327, 0.0619903505, 0.0521927774, -0.1607024521, 0.0634821951, 0.0705485642, -0.1398805380, 0.2093632817, 0.1580654383, 0.0336693376, -0.1646576077, 0.1115638614, 0.1249285936, -0.1532698274, -0.1884149611, 0.0932014585, 0.0517255962, 0.0089468211, -0.1837435812, 0.1259187460, -0.0921760425, 0.1063024402, 0.1357710660, 0.1838632524, 0.0786914527, 0.0544321239, 0.0473594069, -0.0513110608, 0.1398054659, -0.1390701830, -0.1819920540, 0.0718535483, 0.0709967315, -0.1687692255, -0.0864441842, 0.0273480564, -0.1973255873, 0.0981178880, -0.1333549023, 0.1491134763, -0.0804392695, -0.1057778150, 0.0567161739, -0.1458514035, -0.0863720030, 0.0843233168, -0.0496387184, 0.1119783819, 0.1851776242, 0.1442417502, 0.2072727978, 0.1606869400, -0.1883433908, 0.1129450798, 0.1143928468, -0.1908319741, -0.0253121704, 0.0722504854, 0.1173419654, -0.0715675205, 0.1647857428, 0.1161437929, 0.0974222124, -0.1756055355, -0.0168303549, -0.0217503905, -0.1586980820, -0.1896074563, -0.0390761346, -0.0023331940, 0.1008508205, 0.0488894582, 0.0642848015, 0.1373653114, -0.1095423549, 0.1388662159, 0.1861095726, -0.0074812621, -0.0166262686, -0.0528066158, -0.1696114987, 0.1061561108, -0.0549411625, -0.1410522461, -0.1265841126, 0.0688604712, 0.1769667864, 0.1361033320, -0.0097976327, 0.0556917787, 0.1916642189, 0.0340525061, -0.0521488637, -0.1872127503, 0.0439819992, -0.1107872576, -0.0538937896, 0.1570566595, -0.0902339444, -0.0609310865, -0.1839942336, 0.1206285357, -0.0781041831, -0.1185983568, 0.0614432991, 0.1199873686, -0.0158654302, 0.0093431026, 0.0897020102, 0.0271121413, -0.1121155247, -0.1972154826, -0.0506454259, 0.0792386234, 0.1528101861, -0.1691373885, -0.1117611304, -0.1237250715, 0.1570326090, 0.0836027861, -0.1249725148, -0.1913276762, 0.1799748838, 0.0317695886, 0.0915957987, -0.0537778884, 0.1019198895, 0.0789291859, -0.0185148865, 0.1365544200, 0.0012650341, 0.2046919167, -0.1252259612, -0.0282614827, -0.0599798858, -0.0252795815, -0.0837962478, -0.0550680757, 0.0649763048, -0.0104622394, 0.1165009737, -0.2109362483, -0.1376764476, 0.2091076672, -0.1718324572, -0.1353810281, -0.1705467850, -0.0097470433, 0.1090845764, 0.1511430740, 0.1596433222, -0.0172036588, -0.1752222180, -0.0907011330, -0.0523476005, -0.0778975636, -0.0292850733, -0.1940959841, -0.0887255818, -0.0513249934, -0.0652970076, -0.0926434845, 0.1552390754, -0.0443678498, 0.1251921058, -0.1626410484, 0.0926787555, 0.1792289913, -0.1946324557, -0.1256407946, -0.0225305408, 0.1979660094, 0.1523216963, -0.0357439667, -0.0577572435, 0.1088013351, 0.0912234187, -0.0291785747, -0.1710796058, -0.2067052275, 0.2029761076, 0.1381095350, -0.1073800027, 0.0964722335, -0.1850559413, -0.1840608269, 0.1598322690, 0.0071673691, -0.2129073739, -0.1250619292, 0.0389801264, 0.0823149681, -0.0658542216, 0.0289013386, 0.2020024061, 0.0472106636, 0.1408573091, 0.1113214791, -0.2086748779, 0.1343995333, 0.0877676606, 0.1859664321, 0.0506578684, 0.1138330102, 0.1881920695, -0.0601821393, 0.1593374908, -0.0242364258, -0.1655089855, 0.1032479107, 0.2029424012, -0.0320668966, -0.0417693704, -0.1471744329, 0.1772362888, -0.1648610830, -0.0230969042, -0.1128182113, 0.0837174952, -0.1439721882, 0.1391288936, -0.1311879307, -0.1222508177, -0.1577120572, 0.2007710040, 0.0791011453, -0.0675868988, -0.0520371348, 0.0969536901, 0.0871776640, -0.1623048484, -0.0280459076, -0.0025532395, -0.1955051720, -0.0410415232, -0.1748048514, -0.0075336695, -0.0997597724, 0.1552977860, 0.0717715621, 0.0068704188, 0.0518671572, -0.0879601240, 0.0918017626, 0.1279027760, 0.1960412264, 0.0597797036, 0.0250352323, -0.0911321789, -0.1874019951, 0.0814309716, 0.0181226730, -0.1598652601, -0.0310108364, 0.0554268360, 0.0855072737, 0.1992585957, -0.1658549309, 0.1668510139, -0.1960341185, 0.0550440252, 0.0207350850, 0.1846005023, 0.0892125368, 0.0696214139, -0.1345083117, 0.0902889371, -0.1219682544, -0.0440082699, 0.1583348811, 0.1831572652, -0.0227335095, 0.2093854845, 0.1487198472, -0.0454178154, -0.1200702712, 0.0506695807, -0.1670876890, 0.0730926692, -0.0377478153, 0.1500038505, 0.2061194479, 0.1362510622, 0.0697242916, 0.0146648437, -0.0070878267, 0.0881031454, -0.1372570097, 0.1414441466, -0.0860091299, -0.2012100369, 0.1995158792, 0.1993721426, 0.2129037678, -0.0387273282, 0.0281131566, 0.1571446359, -0.0163650513, 0.0592943728, 0.1159420907, -0.1847553849, 0.0912800431, -0.1641400456, 0.1106509268, 0.1053180397, -0.1962069422, 0.1062380970, 0.0709238946, -0.0276379883, -0.0647808164, -0.0817310363, 0.1182181835, 0.1167886853, 0.0541085303, 0.1357671916, -0.1107763276, -0.0280494690, 0.1466166675, 0.0162720680, 0.0692138076, 0.0160253942, 0.1892643869, 0.1467187405, -0.1632732302, 0.1803488433, -0.1579830348, -0.1282528043, -0.0057222545, 0.0341107547, 0.0340652168, -0.1217539459, 0.1527514756, -0.0568480343, -0.1957312226, -0.0784360170, -0.1140084714, 0.0536070466, 0.0229471028, 0.1840257049, -0.1380712688, 0.0556440949, 0.1309313476, -0.1331313998, -0.0476581454, 0.0168934762, 0.1444199979, 0.1245186925, 0.1474438906, -0.0554386973, -0.1847412437, 0.0342960954, 0.0485461652, -0.2036251724, 0.0709468126, -0.0379859209, -0.1454381943, -0.0714997649, 0.0947059095, -0.1664340049, 0.1834268570, 0.0919531882, -0.1530278325, 0.2068942785, -0.0420753658, 0.1849041581, -0.1002729163, 0.1988419294, 0.0943531394, -0.1277283132, 0.0976471305, 0.0186871588, -0.0238777101, 0.0256373882, -0.0616322905, -0.1633119583, -0.2113031894, -0.0011393726, 0.1629575789, 0.1692775488, -0.0856769979, -0.0398735255, 0.2087187469, 0.1409768164, -0.0698124766, -0.0291483849, 0.0173804462, -0.0529693663, -0.1211816445, -0.0941947475, -0.1876989007, 0.1341651678, -0.0228612423, 0.1899296641, -0.0659681857, 0.1791129708, 0.0353442281, 0.1920144558, 0.0855770707, -0.2012451589, -0.1596216261, -0.0576818138, -0.0696182549, -0.0370560586, 0.1411648989, 0.0936513543, -0.1266936064, 0.0163802356, 0.2037049830, 0.0435677767, -0.1233056635, -0.1006579623, -0.0307743698, -0.0632095784, 0.0825739205, -0.0214114487, -0.1908553988, -0.0510985851, 0.0406039655, -0.1050481349, 0.0843189955, -0.0153014511, -0.1254773140, 0.2034479380, -0.0365235507, 0.0924013257, -0.1451801807, 0.2093302011, -0.1621778160, 0.0323058516, -0.1886439472, 0.0478064120, -0.1992603689, 0.1910296679, 0.0627740026, 0.0920626819, -0.1851127744, 0.0248233825, -0.2017012686, 0.1918494999, -0.1685944796, 0.1771685481, -0.0458932370, 0.1198258400, -0.0307605863, 0.1338742971, 0.2016800642, -0.2129886448, 0.0085784942, 0.0989363194, -0.0552743524, -0.1927256882, -0.0771643668, 0.0592687428, -0.1586670280, -0.0870227963, 0.0503590405, 0.0408625007, 0.1513848305, -0.1753961742, -0.0910049975, 0.1904300451, -0.1627425551, 0.0149302930, -0.0194987208, -0.1019753963, 0.0691846609, -0.1802852452, -0.2079423964, -0.0232513696, 0.1148614585, 0.1473616362, -0.1185828522, -0.1476247460, -0.0781639218, 0.0003054440, -0.1946229935, 0.0906373858, 0.0520909131, -0.0696749389, 0.1836592555, -0.0613439381, 0.2026910484, 0.0019484013, -0.0996881574, -0.0979242697, -0.2061058730, -0.0485235900, 0.0323083997, 0.1120965779, 0.0698562562, -0.2026646733, -0.0974542350, -0.1153426319, 0.0070716590, -0.1193417609, 0.0585309565, 0.1077032387, -0.1405243129, -0.1469416320, -0.0118951201, 0.1504545212, 0.2068819106, -0.0345447063, 0.1558310688, -0.0401609689, -0.1281215549, -0.1485913992, -0.0325951278, 0.0236924887, -0.1412186623, -0.0989285335, -0.1125764102, 0.2117060721, -0.1755986810, -0.0379357487, -0.1456120461, -0.1759462059, 0.1071435511, -0.1095023528, 0.0897330940, 0.0590722859, -0.0538412184, -0.1669235080, 0.1190285385, 0.1856550872, -0.1246593967, -0.0452941358, -0.1681733429, -0.1650929302, 0.1673581600, 0.1749532223, 0.1103092432, 0.1773640811, 0.0196264684, -0.0606461763, 0.1917156577, -0.1570813507, -0.0482148975, 0.1045039296, -0.0833038390, 0.1934553087, -0.2046683282, 0.0115418434, 0.2022055686, 0.0367304832, -0.1198011190, -0.1145377755, 0.1659276783, -0.1711680442, 0.0928618014, 0.0347656608, 0.2130160928, 0.0912171602, 0.0163737386, -0.0857663006, -0.0393097103, -0.2092131227, -0.0897728577, -0.0448745340, -0.1397090405, -0.0905019715, 0.0188910365, 0.0904752910, -0.1662477106, -0.1537895799, 0.0561960340, 0.0095788538, -0.0508569330, -0.1168929264, -0.1259870529, 0.0583164394, 0.1533126831, -0.1222576797, 0.1557004750, 0.0525202155, -0.1796438098, -0.0919916779, -0.0360903740, 0.0956878662, 0.0841439664, 0.0375068188, -0.2066167742, 0.0058252811, 0.0962599516, -0.0490829796, 0.0021192431, 0.0402545631, 0.1363182664, -0.1359829307, -0.1802334040, 0.1274853051, -0.1081600040, -0.1473830491, -0.1813733876, -0.0096957684, 0.0478501320, 0.0771263540, -0.2086321861, -0.0535877794, 0.1153199673, 0.1019386351, 0.0595577359, -0.1449661255, 0.1209572852, -0.1217929348, 0.1701689661, -0.1500580311, 0.1806248426, -0.1651500612, -0.0812479854, -0.0782255232, 0.0879411995, -0.0171717256, 0.0299322009, -0.1999279261, 0.0488563776, -0.2054077685, -0.1058893874, 0.1868181527, 0.1597919166, -0.1933054030, -0.0893015489, 0.2095572650, 0.1075255275, 0.0263815522, -0.1575437635, 0.0937550962, 0.0803167522, 0.1283850074, 0.1627438664, -0.1260104328, 0.1386916041, 0.0021191388, 0.1538386345, 0.0292192996, -0.1366710663, 0.0025791675, 0.0551883876, -0.0341164470, 0.2125579715, -0.0129152983, 0.0043642521, 0.1742798090, -0.1281677485, 0.0298834443, -0.0716484934, -0.1951778680, 0.0928669870, 0.1479415894, -0.0937376246, 0.1383763552, 0.1601681709, 0.1671158969, -0.1943475455, 0.1315532625, -0.0645507574, 0.0437509716, 0.1643465757, -0.1303095669, -0.0779238343, -0.0417658091, 0.1274443269, -0.1462714225, 0.0412399173, 0.1863614321, 0.0664007664, 0.1757509708, -0.1520830393, 0.0112962723, 0.0828160644, -0.2097683549, 0.0648523867, -0.0168878883, -0.0203789175, 0.1985651553, 0.1011780202, 0.1745383441, 0.1499823034, 0.2079764009, 0.0816646516, 0.1186003983, -0.0535969287, 0.1682977676, -0.0158083439, -0.1617091000, 0.0476481318, 0.1407393217, 0.0001622587, 0.0945599675, 0.0866003931, 0.0938604176, 0.1383636296, 0.1371096373, 0.1208607852, -0.0270037204, -0.1119401604, 0.0896398425, -0.1295544803, -0.1550250798, -0.1024166644, -0.0933098793, -0.1743687242, -0.0390040576, 0.0148617625, 0.0447485149, 0.1119694412, 0.0492811799, 0.0449284017, -0.0321076661, -0.0946635082, 0.1151131690, 0.0400865078, 0.0852429867, -0.0430465490, 0.1623199284, 0.0557721853, 0.1113232076, -0.1964957714, -0.1067959070, 0.0526090264, -0.1610911041, 0.0771970153, 0.1714132428, 0.0462478995, -0.0748775899, 0.1127077639, -0.0926309302, 0.1933218837, -0.0828977525, 0.0463362336, -0.1324259192, 0.2050657868, -0.1675897986, 0.1589995027, 0.1578087807, -0.0372102261, 0.0368894935, 0.0065888613, 0.0016215146, -0.2060333490, 0.1892905235, -0.1701564491, 0.0464455187, 0.1175576448, 0.0851863623, 0.0066614002, 0.1565407217, -0.1849170774, -0.0165613592, 0.1825207472, 0.0341811627, -0.1399172395, -0.0554997325, -0.0532411635, -0.1934920549, -0.1772823632, -0.0655783117, 0.1964595318, 0.1447093785, 0.1229943335, 0.0632467866, -0.0328790694, 0.1104698777, 0.0611682236, -0.0608098954, -0.0657706559, -0.0787817091, -0.1938354671, 0.1142753959, -0.0829502642, 0.0175814778, -0.1325020641, -0.0780659616, -0.1990582049, 0.2112723887, -0.1553747505, -0.0798613131, 0.0551274121, 0.1428200603, 0.1224687994, 0.0259825736, 0.1331348717, 0.1315174103, 0.1793091893, -0.0879709423, 0.0909688175, -0.0981649011, 0.0858121514, 0.1802685261, -0.0026372671, -0.1356098205, -0.1719633490, -0.1789807230, 0.0798831582, 0.0582580268, -0.1044361293, -0.1631913334, 0.1257994473, 0.0747932494, 0.1154229939, 0.0231893063, 0.0567423105, 0.0604450405, -0.2107093334, -0.0749627799, -0.1914475858, 0.0437601209, 0.1855938733, 0.2007837594, 0.1338332295, -0.1269670725, 0.0130960494, -0.1011529490, -0.1249871552, 0.1358241141, 0.0872164071, -0.0887128264, -0.1060122475, -0.1883794218, 0.2048520744, 0.0388409793, -0.0951914415, -0.0441533476, -0.0458308160, 0.0420882702, -0.1980627775, 0.1205570698, 0.2019619942, 0.0513183177, 0.1594775319, 0.1197360158, -0.0784743875, -0.1497696638, -0.0182491541, -0.1293919683, 0.0574680269, 0.1754296124, -0.0589711368, 0.0111865401, 0.0450025797, 0.0575985610, 0.0642512143, -0.1421603560, 0.1481683850, 0.0333788991, 0.1222280562, 0.0098046362, 0.0922617912, 0.1810188293, 0.1967584193, -0.1292517185, 0.1636549234, -0.1694006473, 0.0721220374, -0.0027960688, 0.0289781541, -0.1374978870, -0.1105206013, 0.0905115902, 0.0465723872, 0.0512376726, 0.0014149249, -0.1960090548, 0.1336880624, 0.1239778697, 0.0018246323, -0.1423616111, 0.1602640748, 0.1318146884, -0.1008566096, 0.0192181915, 0.0763817430, 0.0348337740, 0.1360687315, -0.1250124723, 0.1015513539, -0.0817829818, -0.1092065126, 0.0173519254, 0.0436394513, -0.0468415469, 0.1463158429, -0.0785777271, 0.0302119702, 0.0263187736, -0.0074735880, 0.1262762845, -0.0813904703, 0.1677648127, 0.1713149846, -0.0686187595, -0.0685251802, -0.0151415914, -0.1574501246, 0.1367207766, 0.1761445999, 0.2093665898, -0.0521663427, -0.1315490901, 0.1619792581, -0.1619434357, -0.1917611063, 0.1341825426, 0.0560451448, -0.1994723231, -0.0339842439, -0.1655012965, 0.1874391139, -0.0665728748, -0.2021121830, -0.0587394089, 0.1683867872, -0.1739189178, 0.1563077569, 0.1677886844, -0.1587698460, 0.2030812800, -0.1093225107, 0.2130799294, 0.1177565455, 0.1293844581, -0.2131954283, -0.1952110082, 0.1411190331, 0.0855821371, 0.1532515883, -0.1028959453, -0.0664155930, -0.0840103477, 0.0148153603, -0.1788078398, -0.1269693077, 0.0636402369, 0.0710251033, 0.1511216760, 0.0666429698, 0.1180694997, 0.2021875083, -0.0425276607, -0.1047077700, 0.1603533924, 0.1251109242, 0.0810645223, 0.1455161870, -0.0240291953, -0.1777985990, 0.1208658814, -0.0302214772, -0.1385754049, -0.1722335666, -0.1607687324, -0.0364927053, -0.0314335376, -0.0647694319, 0.1739393473, -0.0728218853, 0.1783054173, 0.1548511386, 0.1999092102, 0.0302997530, -0.0426795483, 0.0648125410, -0.0877423137, 0.1345773935, 0.1706428230, -0.0795313269, -0.0809811801, 0.0900012851, -0.0148148537, -0.1967352778, -0.1688222438, -0.1740829945, -0.1589090228, 0.0538221598, -0.1631648540, -0.1131669134, 0.0895903707, 0.0421771407, 0.0514474511, -0.1988473684, 0.1412400603, 0.1809027493, -0.0732579082, -0.0802176893, -0.1999509037, 0.0048704296, -0.1728903055, 0.0200094730, 0.1794625521, 0.0761397183, 0.0587445498, 0.1545799077, 0.1583607793, 0.0414906144, -0.0822204798, 0.0681066811, 0.1219957471, -0.1745245755, 0.0641526580, 0.0150034875, -0.0179223567, 0.0015339851, -0.1800732315, -0.0712532401, -0.1482105255, -0.1208747253, -0.1311452836, 0.1096603274, -0.1164696068, 0.2121781409, -0.0507577211, -0.0616377890, 0.0436992049, 0.0920339227, 0.2028413117, -0.1719179600, 0.1553429663, 0.0769672096, 0.1607833207, -0.0776915997, 0.1592099369, 0.0526845157, -0.2035764307, -0.1737343967, 0.1263822019, -0.1020136252, 0.2073834538, -0.1773916483, -0.1785380840, 0.1485368013, 0.0042837858, -0.1991783679, -0.0641485304, 0.1616183221, 0.0172713548, -0.1680070758, 0.0367290080, 0.0426670909, 0.0856925845, -0.1223958433, -0.0784772336, -0.2052665502, -0.0422638059, -0.1747235209, 0.0624602735, 0.0655645430, -0.0677023828, 0.2100816667, 0.1441288888, -0.1587779820, 0.0161279142, 0.0624574423, -0.2083326280, 0.1074596941, 0.0567601025, -0.0765303075, -0.1200548187, -0.1794728637, -0.1170208678, 0.1262377501, 0.0309961885, 0.0251553059, 0.1659008861, 0.1706125140, 0.1145618260, -0.0490875095, -0.1169596165, -0.0409267992, 0.0618336797, -0.2048173696, 0.0021907091, -0.0061539114, 0.1302522421, -0.1065987349, -0.1958718151, 0.0671834946, -0.1894103289, 0.0651319623, 0.0262213349, 0.1392145455, -0.1988502592, -0.0136579871, -0.0205741525, -0.0671000928, -0.1551161259, 0.0107717514, 0.0022179037, -0.0987654179, 0.1287915409, 0.1183460951, 0.0700584650, -0.0870736241, 0.0667438209, -0.0383139253, 0.1231867075, -0.0771709383, -0.2019595951, 0.1078383923, -0.0091558397, -0.1216481179, 0.1064752638, 0.1958286464, 0.0468741357, 0.1828132868, -0.0485149920, -0.1939623505, 0.2035515308, -0.0663258284, 0.0211003572, -0.2053535283, 0.1489544809, 0.1923023164, 0.0543997586, -0.1097443104, -0.1778039783, -0.1685322076, -0.0611888468, 0.0956527889, 0.0198410153, 0.1694431603, -0.1582887471, 0.1487581134, 0.0298632234, 0.2071783245, -0.0590164810, -0.1364271343, 0.1506095529, -0.1012387052, 0.0093348622, 0.1344440579, 0.1307239830, -0.0739731491, -0.1634575874, 0.0750719607, -0.0726677626, 0.0165913999, -0.1260736585, 0.0848121047, 0.1920724511, 0.1866309941, -0.1440292150, 0.0530213714, -0.1068393663, -0.1572163105, -0.1817591935, 0.0872799456, -0.1363787353, 0.0342573524, 0.1573859155, 0.0643665493, -0.0841873884, 0.0996667445, -0.1815573871, -0.1556952894, 0.1443904340, -0.1696757972, 0.1797145605, 0.1919395328, -0.0852943808, -0.0432171375, 0.1305790842, 0.0064933598, 0.1770673990, -0.1004561633, -0.0653946549, -0.1894420534, 0.1474712789, 0.1597555578, 0.0644319654, 0.0112381727, 0.1773147881, 0.1368961930, -0.1696494222, -0.0794858336, 0.0543223917, -0.1608809680, 0.1402814388, 0.1976004243, 0.1423691213, 0.1369906366, 0.1369352937, -0.1916384101, -0.0003434718, -0.1823771000, -0.0920493752, -0.1194690466, -0.1343110800, -0.1054637805, -0.2012929916, 0.0553362668, 0.1735905111, -0.0886167511, 0.0628515184, -0.0775610059, -0.1044777557, -0.0881972462, 0.0609320104, -0.0460686982, 0.1779697835, 0.0804338157, -0.1629889756, -0.0943208560, -0.1311645955, 0.0961579978, -0.1141553745, 0.0923919678, -0.1632291526, 0.1006371677, -0.1108925790, -0.0012696087, 0.0399169922, 0.1142591834, -0.1421104372, -0.0174781978, 0.1302104592, -0.2063336521, 0.1987169683, 0.0140927434, 0.2010957599, 0.0888950527, -0.1703964770, -0.1330864727, -0.1129195169, 0.1431652904, -0.0087963045, 0.1897248328, -0.0336518139, -0.1243215725, 0.1992536485, -0.1858008653, -0.0389436781, -0.1441355646, -0.0483581275, -0.1993281692, -0.1753670871, -0.1082982644, -0.1959311366, 0.1117576361, -0.2010479867, -0.1241202354, -0.1972450167, 0.0678546131, 0.1490649879, -0.1754833460, 0.1168682873, -0.1774145216, 0.0227796584, -0.1417134553, 0.0673241615, 0.1737882197, 0.0875216126, 0.0729320347, -0.0616698563, -0.1281520426, -0.1989519149, 0.0506260693, 0.0031040460, -0.0599344969, -0.0999724045, 0.0916744471, -0.0527899414, 0.0402813554, 0.0755846500, -0.1540571600, 0.0956314206, -0.1533639282, 0.1268324852, -0.0474900454, -0.0872085243, 0.0557737052, -0.0806360841, 0.0710445642, 0.1065910161, 0.1539396346, -0.1553277373, 0.0808281302, -0.0243396163, -0.0551216006, -0.0355269164, 0.1911634505, 0.1564151049, 0.1697790921, -0.0528497696, 0.0984633863, -0.0529521406, -0.2101432383, 0.1568694413, 0.1261364520, -0.0316334069, -0.0699019432, 0.1140802503, -0.1544983685, -0.0391753614, -0.1233761162, 0.1802347600, -0.0190109462, -0.0831044316, -0.2082015872, -0.2094552815, -0.1421009302, 0.0446969271, 0.1180342734, 0.0346517116, -0.1930497289, -0.0490227938, -0.1677147895, -0.0491812974, 0.1212866604, 0.1160207093, 0.2117471397, 0.1301966608, -0.2032881081, -0.1543271691, -0.1442168951, -0.1038520783, 0.0471235514, -0.1585114300, 0.0527115166, -0.1329412460, 0.0585195124, 0.1939077675, -0.0408542603, 0.0379559696, -0.1076223180, 0.1626552641, -0.0470750630, -0.1445066631, 0.0631578267, -0.1279372871, 0.1168318689, -0.0907143429, -0.0983053446, 0.0499971211, -0.1543325186, -0.0352110416, -0.1911678612, 0.2012702823, -0.0674726218, -0.0280527174, -0.1482307613, -0.0866022259, 0.0135001093, -0.0755891651, 0.1493487954, -0.0923628435, 0.1512388885, 0.1105206609, -0.1233010888, -0.1604435742, -0.0687525570, 0.0480512083, 0.0533574522, 0.0810398459, 0.2036272585, 0.1289487779, 0.0090710521, -0.0519945920, 0.1261376739, -0.2042019963, 0.1476466656, 0.0121955872, -0.1674290150, 0.0097776949, 0.1986927986, 0.1322011054, -0.0863118172, 0.0273644179, -0.1336909980, 0.1636165977, -0.1228503212, -0.0751855224, -0.1121777445, -0.1152681634, -0.1866390705, -0.0889009461, -0.1258024275, -0.1915954500, -0.1558095515, -0.0735427141, 0.1202566326, 0.0228019208, -0.1811176538, 0.0133337379, 0.1875566244, 0.1818839908, 0.1318564713, 0.1887971163, -0.1080502123, -0.0883422121, -0.0622210801, 0.1333971620, -0.1905879378, 0.1017746627, -0.0049944073, -0.0265125483, 0.0914417803, 0.0491191149, 0.0685849488, -0.0211933255, 0.0164035708, -0.1089145392, -0.0075309128, -0.1465310752, -0.0649724603, 0.0363533199, -0.1956815124, 0.2007778585, -0.0128664970, -0.0485958755, -0.1622623503, -0.0534678698, -0.1758344322, -0.1261566281, -0.0731016994, 0.1904644072, 0.0895338953, -0.0453352630, 0.0471154749, 0.0413264632, 0.0719670057, -0.0446490943, -0.1264902353, 0.0893809497, -0.1692527831, 0.1201239526, 0.0458091199, 0.0051479638, -0.1877388060, -0.1992911696, 0.0982604623, 0.0934755504, 0.1866677403, -0.0781512558, 0.1888723373, 0.0367126018, -0.1654497683, -0.0991836563, -0.2052423656, -0.1020171270, 0.1388156414, 0.0897136331, -0.1058568060, -0.2055169046, 0.1068682373, -0.0308343023, 0.0184083432, 0.1758403778, -0.1735419035, 0.1746751964, 0.0020956099, 0.1933275759, 0.1729234457, -0.0949942693, -0.0631643981, 0.0157373846, -0.1988634169, 0.1142289639, 0.0629304647, -0.1140842587, -0.1448621303, 0.1459372640, -0.1504361033, -0.0824999511, 0.0407643914, 0.1589671671, -0.1848030090, 0.1760683060, -0.1430222541, 0.2027480304, -0.1728915274, 0.0866293609, -0.1914968938, 0.0221603960, 0.0069704056, 0.0888171196, -0.0728658438, -0.1679234058, 0.2006779015, 0.0904677510, 0.0584804118, -0.1882095039, 0.0623434186, 0.0868101716, -0.1981459409, -0.1769716740, -0.1821801215, -0.1996962428, -0.0516619980, -0.0329256803, -0.0241647512, 0.2022213340, -0.1534017473, 0.0064666271, 0.0136136115, -0.1948258728, -0.1259876639, 0.1414062977, -0.0981904715, -0.1901355386, 0.1337595284, 0.0206441581, -0.1829779744, -0.2119307518, -0.2014321238, -0.2070757300, 0.2016168833, 0.1520060301, 0.0576945245, -0.1641073674, 0.2129188180, 0.1198900342, 0.1515713036, -0.0608581454, -0.0445007682, 0.0263260454, -0.0153774023, -0.0441926867, -0.1944570839, -0.1918360293, -0.0928257108, 0.1664627194, -0.0336474329, -0.1162796989, 0.1217368543, -0.1634105742, 0.0026267916, -0.0529325753, 0.0312067270, 0.0766163766, -0.0213577747, 0.0142683089, 0.0897280276, 0.1391752064, 0.0983397663, -0.0214587152, 0.1951382756, 0.0966913998, 0.0634912848, 0.1193961501, -0.0797929019, -0.1105776280, -0.2024938762, -0.2046627402, -0.0074753165, 0.1339516044, 0.1118431091, 0.0258384198, -0.1532483846, 0.1079897285, -0.1471315920, -0.1969375908, -0.0491231382, 0.1895702481, -0.0908532664, -0.0205998272, -0.0303425491, 0.0942589343, -0.1515416354, -0.1911843270, -0.1956821084, 0.0328252465, -0.0698693544, 0.1393386424, 0.1255013645, -0.1359865367, -0.1153906658, -0.2013411373, 0.1948916912, 0.1798245609, -0.1803007573, 0.1591883600, 0.1799423993, -0.0448904485, 0.1550146639, 0.0960927308, -0.0381173640, 0.0505827665, 0.0100210309, -0.1992234588, 0.2105712891, 0.1631121039, -0.1470948756, 0.0464096367, -0.0892922506, 0.0061459243, -0.1188981086, 0.2076775134, -0.0202621520, -0.1745906472, 0.0017700940, -0.1732509434, -0.1283423007, -0.2061740905, -0.1173758730, 0.1094646454, 0.0291360766, 0.1319639087, 0.0616571903, -0.1173392236, 0.0388348997, 0.0463386178, 0.0711835325, 0.1015142202, 0.2081853747, 0.0392340720, -0.0313192159, 0.1544469893, -0.1229915842, -0.0897011310, 0.0191840380, 0.0172591656, -0.1115615144, -0.0446022749, -0.0246111602, -0.1259313822, 0.0429498255, 0.0209326744, 0.1083736420, -0.1967430562, -0.0494222790, -0.1241185591, -0.2087697238, -0.1070556492, 0.1874563396, -0.1921684742, -0.0546354055, 0.0826970339, -0.1646238118, 0.1755934060, 0.1608643532, 0.0891706645, 0.1062918007, -0.1836696267, 0.0712143481, 0.0263563842, 0.0245463997, 0.1114870608, -0.0054905117, -0.1699474901, 0.0511034727, -0.0389646143, 0.1326921284, 0.2091339231, -0.1154052541, 0.1012003720, -0.1097671837, 0.0535662770, -0.0994428918, -0.0913146585, -0.1386704594, 0.2016600966, 0.0887771845, -0.1257243603, -0.0820882767, 0.1031100452, -0.0497890711, 0.0502878428, 0.1775922179, 0.1025641263, 0.1124098301, 0.1815298498, 0.0270941556, -0.1643512994, -0.1529047638, 0.0486496985, -0.0657847375, 0.1740065515, 0.1092291474, 0.1655963063, 0.0181917548, -0.0301538259, -0.0105724931, 0.0343169272, 0.0566281378, 0.1327677667, 0.2033062577, 0.0455288291, 0.0444711447, 0.0478150547, -0.0963646695, 0.1863059402, -0.2023345679, 0.1783591509, -0.0955072045, -0.0467385054, -0.0059748739, -0.0564950109, -0.1791038364, -0.1472482979, 0.0740091801, -0.1851411313, 0.0521834791, -0.0583557785, -0.1822416335, -0.1446902156, 0.0449821949, 0.1829200089, 0.1103640497, -0.0638640821, 0.0577831566, 0.1330929101, 0.0252168626, 0.1610595286, 0.1414406896, 0.1278419197, -0.0865726322, -0.0298154354, -0.1893062741, -0.0276203007, -0.2051651925, 0.1729630530, -0.1191663966, -0.0101634115, 0.1196340322, -0.2021226138, 0.0506027341, -0.0275796354, -0.2118948251, 0.0645498037, 0.0415663421, 0.0208124965, 0.0297508389, -0.1058726087, -0.0960093141, 0.0323980153, 0.1219114363, 0.0073639899, -0.0621746629, -0.1616859287, 0.2098265588, -0.0894307122, 0.1868473291, -0.0518244058, 0.0832658112, -0.0944210961, 0.1686597764, -0.2128241658, -0.0369138420, 0.0180789083, 0.2084040940, 0.0804129243, 0.0320252180, -0.2106931210, -0.1005151719, 0.1411907077, 0.1748240590, 0.1631378233, 0.0596881211, 0.1924263835, -0.0611590594, -0.0674935132, -0.1090021208, -0.0104370862, -0.1327804625, -0.0579845607, 0.1376307607, -0.0479622185, 0.1878094971, 0.0128329992, -0.0724753141, -0.0014405549, -0.0314305872, -0.1874136925, 0.1370508671, -0.0533346981, 0.1863775849, -0.0191536844, 0.0459181368, 0.1270267069, -0.1028755605, -0.0549217910, -0.0981757790, -0.0725408345, 0.0917052329, -0.1448445469, 0.0885515809, 0.1468529701, -0.1390465051, -0.1744889915, 0.1972120702, 0.1607232392, -0.0518392920, 0.1493856907, 0.0715863705, -0.1714482307, 0.1151228249, 0.1040072143, 0.1014150381, -0.1442594230, -0.1425091177, 0.1732893288, 0.0037401915, -0.0359322429, -0.0604691803, -0.1113087833, 0.0732270181, -0.0263893753, 0.0746116340, -0.1455382407, -0.1982153356, 0.1978387833, 0.1625904143, 0.0273582637, 0.0730413198, -0.1056326926, 0.0026047826, 0.0402204394, 0.0023018867, -0.0022009313, 0.0595671237, -0.0149376094, 0.0018262118, 0.0813457966, -0.1641079187, -0.0237189680, -0.1038066894, 0.1900723577, 0.1491495371, 0.1897017062, -0.0005613714, 0.1973762214, 0.1174893677, -0.0404330194, -0.1657633334, -0.0062251240, -0.0278593600, -0.0390315652, -0.2048531473, -0.0512534678, -0.0491373241, -0.0703801662, 0.1991268694, -0.0515239984, 0.1231005192, 0.0469681025, -0.1932683587, -0.1080608368, -0.0281383246, 0.0494581759, -0.1514368653, 0.0292558372, -0.1003489047, 0.0911124647, 0.1564387381, -0.0335830301, 0.1455479562, -0.1816011071, -0.1823195070, 0.1514663398, 0.1406163275, 0.1885030866, 0.1242824793, -0.1546808034, 0.0902919769, 0.1428492665, 0.1209816337, 0.1254950166, 0.0104650855, -0.0278489888, 0.2117148340, 0.0476858020, -0.0285566598, -0.0231694877, 0.0942659080, 0.1007203162, -0.0654558539, -0.0197696090, -0.0360016674, -0.0822589099, -0.1410555989, -0.0435803235, -0.1660849452, -0.0906480104, -0.0888994262, 0.1141942441, -0.0609730631, -0.1611536741, -0.0345421582, -0.1260350943, 0.0602631271, 0.0068634599, -0.0013623685, 0.0577225685, 0.0498258770, -0.0454781502, 0.1336076856, -0.1478631496, -0.0520296097, 0.1747241914, -0.1216610819, 0.1275118887, 0.1920532286, 0.1035468876, 0.2099753916, 0.0930824578, 0.0928864479, 0.0606037974, 0.2127641439, -0.1250537485, -0.1049612612, -0.0707738549, 0.0462386906, -0.1050541848, 0.2092462778, -0.1090416685, 0.0559493899, 0.1075286865, -0.0880913138, 0.0391494930, 0.1240768135, 0.1675392091, -0.0021153390, 0.1942414045, -0.0543267131, 0.0014681518, -0.0163033903, 0.1526921391, -0.0191472322, 0.1401652992, -0.0621625632, -0.2075629979, 0.1902502179, -0.0940558240, 0.1499597728, -0.0059809238, -0.1281908303, -0.0047522932, -0.1359102726, 0.0226327628, -0.0899245366, 0.0602328181, 0.0490871668, -0.1129359379, 0.1284369528, -0.0491100848, -0.0632094890, -0.1382881999, -0.0992899984, 0.0823422670, -0.0516955405, 0.1959424615, 0.1074351966, -0.2029730082, -0.0280252695, -0.1267211139, 0.2108168900, 0.0787534416, 0.1409596801, -0.0079249591, -0.2029214650, 0.1065075397, -0.0624595284, 0.1264002025, -0.0331930071, -0.0036305487, 0.0398704708, -0.0536184311, 0.0965144336, 0.1448169947, -0.1047319099, -0.0682462305, -0.0593087673, 0.0430641770, 0.0490980446, -0.0456942320, 0.1098040938, 0.0605421364, 0.0756760538, -0.1713852435, -0.1462914050, 0.1456372142, 0.0425437689, -0.1593762636, -0.0411698669, -0.0468895286, -0.0404934138, -0.0533497930, -0.2037094980, -0.1210984290, 0.0971468687, -0.0182767957, 0.1336697638, 0.1266036332, -0.1628730297, -0.0623703599, 0.1259144247, -0.2109924704, 0.0345640779, -0.2010063082, -0.0547237545, 0.1184599996, 0.0638903081, 0.0830134451, 0.2000322342, 0.1686373353, -0.1161610633, -0.1020248532, 0.1424554884, -0.0655421168, -0.0307706594, -0.0887754485, -0.1944266409, 0.1821271181, 0.0132096559, -0.0968938693, -0.1559327245, 0.0559995472, -0.0802386403, -0.1336320937, -0.1590941101, 0.1365468502, -0.0255953968, -0.0536271185, -0.0097687095, -0.1681897640, -0.1241566315, -0.0073689669, 0.1953168511, 0.0262402445, -0.1826559603, -0.0381529480, -0.0196370333, 0.0424892902, -0.0236828327, 0.0686831176, -0.1641728282, 0.1568455398, -0.1511853039, -0.0903801322, -0.0461353958, 0.0670965314, -0.1016566381, 0.1658084691, 0.1047852933, -0.1087132022, -0.1448681355, 0.1455472410, -0.0213940144, 0.1067807972, 0.1495614052, -0.0840581208, -0.1165622175, -0.1263452619, -0.0158583075, -0.1421947777, 0.1319160759, 0.1434713006, -0.0974691808, 0.0908687115, -0.0406492501, 0.2123927176, -0.1030678079, -0.0699986815, 0.0642950237, -0.0251826495, -0.0854823589, -0.1096509323, -0.0907092616, -0.2105641663, -0.1021737903, 0.0008561462, -0.2098904550, 0.1004408002, -0.0734445602, -0.0726897717, 0.1675332189, 0.1239057779, 0.0097715557, 0.0667681992, -0.1043640971, 0.1285540164, -0.0009112954, 0.1687436104, 0.1890211105, -0.0713083297, -0.0517095178, -0.0946692005, 0.1738456786, -0.1756263822, 0.1022707820, -0.1381054819, 0.0597068667, 0.1020123959, -0.1869646460, 0.1419177353, -0.1837271750, 0.0649304092, -0.0428975075, 0.0641330183, -0.1485097110, -0.0235622525, 0.0734207630, 0.1333397627, 0.0865913332, 0.0552074015, 0.1373053789, 0.0575802624, -0.0595466942, -0.0077782124, -0.1688821316, 0.0683797002, 0.0604126155, -0.1187862828, 0.1183215976, 0.0236799270, 0.0590337217, 0.0101673752, -0.1912313998, -0.1972816139, -0.0144357085, 0.1284356415, -0.1677064002, -0.1458736658, 0.0945150852, 0.0660020411, -0.2040407658, -0.0652025193, -0.1958839595, -0.0476699769, -0.1194568947, 0.0389118493, 0.1122297049, 0.0849995613, -0.1303817034, 0.1943291426, 0.0884832144, -0.1713939905, 0.1361604333, 0.1700559258, 0.0888699889, 0.1491132975, 0.0110910237, -0.0082112402, -0.2113815248, 0.1223022044, -0.1369983256, -0.0939085633, -0.1901251674, -0.1781198978, -0.1601606905, -0.1569926441, 0.1607081890, -0.0785849988, 0.1184020936, -0.0174237043, 0.1962739825, 0.0148686767, -0.1977183521, 0.0811325610, -0.2109922618, -0.0841675103, -0.0702919215, -0.0306952149, 0.1349979043, 0.1646722853, -0.0834002197, 0.1565574706, 0.0698181689, 0.0968342423, 0.0466661155, 0.1813298166, 0.0681289136, 0.0577867925, -0.1417659670, 0.0790274739, 0.0039386451, 0.0658430755, 0.1567339599, -0.0266019553, -0.0230122209, 0.1224775314, 0.1286482215, -0.0073128492, -0.2068894356, -0.0707175732, 0.1901448369, -0.1007148921, -0.2069893181, -0.2129065543, -0.2112892717, -0.1419645101, -0.0425458103, 0.1253262460, 0.0262898952, 0.1234650314, -0.0945816711, 0.1455450356, -0.1626341790, 0.1400247514, 0.1259462237, 0.0135621727, -0.1350647509, -0.1089950055, -0.0118958801, 0.1709047556, -0.1979926378, -0.0529204160, 0.0565693378, 0.0054066479, -0.2076760978, 0.1579419076, -0.1331384778, 0.1450648904, 0.0945485234, 0.1897557676, -0.1987455487, -0.0204036236, -0.1410997212, 0.1950822473, -0.0571822971, 0.1841697991, -0.0832832009, -0.0292502493, 0.0540054739, -0.0874012262, -0.1223381013, -0.0359581560, 0.1441550851, 0.1913868487, 0.0666281581, 0.1085380316, -0.1803641915, -0.2118480057, -0.0779354274, -0.1355263591, 0.0061643273, 0.0883840919, 0.0734911263, -0.0222379565, -0.1470552981, 0.0930044353, 0.0301488936, -0.1041629091, 0.1124871969, -0.0324787796, 0.1621141732, -0.0302986354, 0.0320253670, -0.0254642069, 0.0735721886, 0.1294092536, 0.1970367730, 0.1374342442, -0.0098119080, -0.1765737236, 0.0717885792, -0.1637127101, 0.0017922521, -0.1634298861, 0.0551188588, 0.1021533012, -0.1480292082, -0.1404761374, 0.0176453292, -0.2029290348, -0.1242469549, -0.1500332206, 0.0987029970, 0.0664662719, -0.1982329637, -0.0825024992, 0.0352124721, 0.1985097826, 0.0569595098, 0.0618391335, 0.1393162012, -0.0402746350, -0.0187438279, 0.0287175924, -0.0901775211, -0.1571455002, 0.0820456743, -0.1526470482, -0.0679484606, -0.1871128678, -0.1030577943, 0.1164523661, -0.1777411997, 0.2028335333, 0.1062799096, -0.1306673586, 0.0193794817, -0.1056451425, -0.0782839805, -0.1838641018, -0.1612155437, 0.1994944513, -0.1032967493, -0.0007423908, -0.1928774118, -0.1026488543, 0.0221969932, 0.0957674682, -0.1590662003, -0.1756756902, -0.1925190091, 0.1713214517, -0.1357954144, -0.0678046048, 0.1436020434, 0.1913373470, -0.0668297112, 0.1408542097, 0.0131400675, -0.0122715235, 0.0858298540, 0.0434364676, 0.0581994653, -0.0372000188, 0.0917010307, -0.1772421449, 0.2118621469, 0.2043992281, 0.0180346370, -0.1003166810, -0.1554493606, 0.1346953809, -0.0091408342, 0.0495243967, 0.1684330404, 0.0888979435, 0.1670624614, -0.1518383324, 0.0951341093, 0.0481031239, -0.0930296481, 0.2053811252, 0.0390005410, 0.1204590797, -0.1965785623, -0.2108087689, 0.0492499173, -0.1559493393, 0.0439987779, 0.0180086643, -0.0299904495, -0.0337069035, 0.0596897304, -0.0415356904, 0.1043559611, 0.0512758791, -0.1627185047, 0.0060975403, 0.0107195526, 0.0437085629, 0.2009048462, -0.1879913360, -0.1152206361, 0.0925723314, 0.1455665529, -0.0639835298, -0.0555260181, 0.1588294208, -0.0340011120, -0.1726251692, -0.1559307873, 0.1641682684, -0.1031779572, -0.0363223106, -0.2074585408, -0.1596251428, 0.0819325745, 0.1213523746, 0.0321856886, 0.0748675764, 0.2040767074, -0.0269059688, -0.0252219886, 0.1771601140, 0.0397257209, 0.0009780973, 0.0286276191, -0.2082468867, 0.1639084220, -0.0625818223, -0.1664599180, -0.0204231888, 0.1186442077, 0.0199112147, -0.1199412122, 0.1855714321, -0.1853042543, 0.0248175263, 0.1296752989, -0.1034716070, 0.1024605334, -0.1043592170, -0.1110985950, 0.1371198595, 0.2005972564, 0.1089456379, 0.0813475251, 0.1458572149, -0.1875934303, -0.0878109336, -0.1656404734, -0.0481218696, -0.0147879571, -0.0365189314, -0.1881186664, -0.0101490766, -0.1450003982, 0.0966188908, 0.0816202760, 0.0858395994, -0.0378078520, -0.1166864485, -0.2124664634, -0.1445667446, -0.1350740641, 0.0993289948, 0.0006026477, -0.0420859903, 0.1917885542, -0.1255790293, -0.0350225717, -0.2000366598, 0.1605901718, -0.1603719890, -0.0448665023, -0.0817638189, -0.1180410981, 0.1242516339, -0.2098187208, -0.1168854013, -0.1516601741, 0.2077189088, -0.2060550451, -0.0837537944, 0.1635324657, -0.1471616328, 0.0553687513, 0.1319250762, -0.1697462499, 0.0211914480, 0.2054221630, 0.0742321312, -0.0818149596, 0.1701242328, 0.0754314959, -0.1620253772, 0.0616166890, 0.0198826492, 0.0850143135, -0.0293497741, 0.0385374427, -0.1875057369, -0.1260208488, -0.0509605855, -0.2069230825, -0.1423363388, 0.0270057023, -0.0100039542, 0.0066857487, 0.0064863414, -0.1084620431, 0.0748348832, 0.1903536022, -0.0189216882, 0.0647348762, -0.1130325645, -0.0280791521, 0.1684472561, -0.0679326504, 0.0550275743, -0.2121178657, -0.1230209097, -0.2067865580, -0.1724447161, -0.0941479802, -0.2128460258, 0.1200295091, 0.1585270762, 0.0048917681, -0.1262075007, 0.2128604949, 0.1981873214, -0.0792624801, 0.0499543250, -0.1759408712, 0.0397666395, -0.1297239959, 0.0539006889, 0.0158702582, 0.0525951087, 0.0104503036, -0.1166705415, -0.1007425413, -0.0335223973, -0.0363929272, -0.0247373134, -0.0816320181, 0.0663042665, 0.0471885502, -0.1701354086, 0.0133253038, -0.0290323794, -0.0628939718, 0.1963127851, 0.1712224483, 0.1359584332, 0.0572720766, 0.0033609420, -0.1027953550, -0.0740710050, 0.1231857538, 0.0393924117, 0.0514275730, 0.1134273708, 0.1358176172, -0.0179544836, -0.0428474993, -0.0171023011, -0.2041860372, -0.1511560827, 0.0329139382, -0.0457010418, 0.1883136630, 0.1534592807, -0.0542723686, -0.1335345954, 0.1261513531, 0.0454059839, -0.1233780980, 0.1302312016, 0.1201035678, 0.1464537084, 0.0493889451, -0.1329772770, 0.1709606051, -0.1870940626, -0.1035034806, -0.0046339035, 0.0043433607, 0.1246011853, 0.0860475600, 0.0112697929, 0.0109259784, -0.1088009328, 0.0451144576, 0.0881381333, 0.0288242400, 0.0178651661, 0.2085936964, 0.1395792663, 0.0561457574, -0.1421446502, 0.1660542786, -0.0913557336, -0.1580511034, -0.0692827702, 0.1781054735, -0.1359718442, 0.1693622172, 0.1706989706, -0.1860644817, 0.0008527339, 0.1799221635, -0.0847420543, -0.1547217220, -0.0242664218, 0.0821223855, -0.0366279185, 0.1579120159, 0.0282838047, 0.0498765707, -0.1640301049, -0.1360980570, 0.0567750931, -0.0627196282, 0.0094111115, -0.0854918212, -0.0437347442, 0.1329703629, -0.0725088567, 0.1103307307, -0.0504474938, 0.0505414307, 0.1265490353, -0.2080813795, 0.1661646962, 0.0103915930, 0.0793212950, -0.0289316922, -0.0177615285, 0.0827395320, 0.0938742459, 0.0911233425, -0.1122500226, 0.0554215610, -0.1822759956, 0.1217783391, 0.1194887161, 0.1549885869, -0.1796352714, 0.0217099786, 0.1249144673, 0.1293254197, -0.2064816654, -0.0156392753, 0.1515989304, -0.0573394150, -0.0397448242, -0.0883652940, 0.0087602139, -0.1320590675, -0.0012755543, 0.0074295104, 0.0264889598, -0.1099150479, 0.0306335688, 0.1872678101, -0.1059957743, -0.1681141704, 0.0320923179, -0.0743228644, -0.0371268243, 0.0887113512, 0.2068048120, -0.1959859282, -0.1684667319, 0.2029729187, -0.1361901611, -0.0789012164, -0.1442584097, -0.1696847975, 0.0996335745, 0.1952257156, 0.0415257215, -0.2088347971, 0.1613855064, 0.0910006762, -0.2028978318, -0.1083787307, -0.0743597150, -0.1370799541, -0.1911847442, -0.1457047611, -0.0623703152, -0.1246905029, -0.0984734967, 0.1318724751, 0.1303057075, -0.1093793437, -0.0508935899, -0.0765071809, -0.0111884177, -0.1807311922, -0.0703602433, -0.1799080819, -0.1261800528, -0.0470359623, 0.1881902814, 0.0471602082, 0.0792753398, 0.2045003772, 0.1398940086, -0.1819617003, 0.1283333600, -0.0361667722, -0.0006352365, 0.1356659532, -0.2093663812, 0.0505688190, -0.0889607742, 0.1192332506, -0.0245460868, 0.0301766992, 0.0701677799, 0.0392634571, 0.0366925746, 0.1453541815, -0.1476673931, -0.0009120107, -0.0534066707, -0.1067317575, -0.2066733539, -0.0566889346, 0.0450963676, 0.0414687097, 0.1335349977, -0.1520926356, -0.1424853206, -0.0996622816, 0.1847671568, -0.0335486233, -0.0234564245, -0.1365759075, 0.0068013966, 0.0895885527, -0.1611822844, 0.1875145733, 0.1700508296, 0.1791161299, 0.0502313972, 0.1339436173, -0.1496843696, -0.0048265010, -0.0859003514, 0.1516091824, -0.0743022263, 0.1891787946, -0.0211467147, -0.1220617816, 0.1598131657, -0.1144109517, 0.0861026943, -0.0619688481, 0.0408543050, -0.1235215962, -0.0368760228, 0.0546551347, 0.0205015689, 0.0478628278, -0.0267687291, 0.2078846097, -0.1167297587, 0.0474349558, -0.0933977664, -0.0598359853, 0.0006468296, -0.1521905959, 0.1903777421, 0.1955339909, -0.1681201756, -0.0718923360, 0.1000526547, 0.1975592673, -0.0782697946, -0.0607591271, -0.0573827773, -0.1979690492, 0.1500097513, -0.0116083771, -0.0183549225, -0.1110346541, -0.1526011080, -0.0931197703, 0.0978282094, 0.1528442800, -0.1779505312, 0.0492412746, 0.0135434717, -0.1821183711, -0.0539662242, 0.0648232102, -0.1835660934, 0.0774909556, -0.1061648875, -0.0018143058, -0.1021513268, -0.0782599300, 0.1797921360, -0.1122998893, -0.0137408972, 0.0591432452, -0.0047023296, 0.0441930890, 0.1600920558, 0.0812759399, 0.0577342212, 0.0126988590, -0.0504227877, -0.0159302801, -0.1607423425, 0.1282382011, -0.0441544652, -0.0640320778, -0.1724980921, -0.1329568923, 0.0787885785, -0.1252467930, -0.1387143284, -0.0785312206, 0.0326679200, 0.0394001901, 0.0371861458, 0.2077334225, 0.1461085975, 0.1211211979, 0.0385516584, 0.0018767864, 0.0775760412, -0.0718859732, -0.1748803854, -0.2082360983, -0.0951147377, -0.0277354270, 0.1811922789, -0.2120816261, 0.1423982084, 0.0527060628, 0.0443730950, 0.1091656983, -0.1891245544, 0.1849547327, -0.0563776344, -0.1372431815, -0.1792159081, 0.0771172941, -0.1128707677, 0.1613407731, -0.0392446369, -0.1591635942, 0.0720368326, -0.0328554362, -0.1781554818, -0.0167741776, 0.0256045461, -0.1106735989, -0.1167926863, -0.1380546987, 0.0477854609, -0.1729764640, 0.1947746873, 0.0698388219, -0.1423616111, -0.0137424171, 0.2067546248, -0.1112923175, 0.0375417471}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w2.txt b/model/AE_model/hls4ml_prj/firmware/weights/w2.txt deleted file mode 100644 index 1860f7a..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w2.txt +++ /dev/null @@ -1 +0,0 @@ --0.0747238696, 0.0702665448, -0.2050665915, -0.1304139793, 0.1610298455, -0.1810131520, -0.0231247544, -0.0361172110, 0.0461444557, 0.0359051973, 0.0760371387, -0.2113457471, 0.0999777019, 0.0359689891, -0.1927438825, 0.0936444104, -0.1948066503, 0.0397396982, 0.0563738942, -0.1845022887, 0.1011802554, -0.1888832152, -0.1760497987, -0.1750413775, 0.1093027294, 0.0974972248, -0.1233510599, -0.0611993670, -0.1355045438, 0.1683713198, 0.1798975170, 0.0213785619, -0.0560328066, -0.1530482173, 0.0548693240, 0.0343294889, -0.0711358637, 0.0912140608, 0.1809859574, 0.1149189472, 0.1054931581, -0.0636578053, -0.0942127407, 0.1773730516, 0.2120944262, 0.0772497058, 0.0976216793, 0.1192027032, 0.1474955380, 0.1808525324, -0.1679046899, 0.0302044004, -0.1142014265, 0.0415002108, 0.0487659574, -0.0340339541, 0.1995163858, 0.0966926217, 0.1879581511, -0.1030610502, -0.1011514291, -0.1468277574, 0.1659207642, -0.1842445284, 0.0208937377, -0.2034995109, 0.1920813918, 0.1997976005, 0.1374559999, -0.1527216285, -0.0834722519, 0.0123545229, 0.0552387834, 0.0926317871, 0.1921240985, -0.1326754987, -0.1813822836, -0.0326681733, 0.0065337121, -0.1843209714, 0.0786501765, -0.0897448957, 0.1941747069, 0.1248153448, 0.1492989063, 0.1165934801, 0.1772582233, 0.1636407971, 0.0535315573, 0.1117191911, 0.0433555543, 0.0710774064, 0.1352140903, 0.0605131090, -0.0881200880, -0.0305309892, 0.0763566196, 0.0928750336, -0.1551524103, -0.0275730342, 0.1828040183, 0.1478491127, -0.0047877729, 0.1009497941, 0.0961081386, 0.0965725780, 0.0553318560, 0.0013379157, 0.0985064209, -0.0789774209, 0.0182258189, 0.1944918633, 0.1619832516, -0.0111588240, 0.0247146487, 0.2024116218, -0.0613928288, -0.1978193074, -0.1667818874, 0.0785077810, 0.1043009162, -0.1804296076, 0.0209509730, 0.0505620539, 0.0428503454, -0.1396937966, -0.0319835395, -0.0479197204, 0.1023346782, -0.1610890180, 0.1083749235, -0.1606936604, -0.0941008106, 0.0156576782, -0.1311611831, 0.0280482024, -0.0584021956, -0.1437120289, -0.0527850091, 0.0450398922, 0.1743397117, -0.1097086221, -0.1784005910, -0.1217441857, 0.0298525393, 0.0874874890, -0.1523758769, 0.1969851255, 0.0338514149, 0.1471830904, -0.1563977748, 0.0323705077, 0.0171378851, 0.0746625364, 0.0708424747, 0.0754641891, -0.2068636715, 0.1751983464, 0.1664066911, -0.1142128110, 0.0260509402, 0.1997905970, 0.1474956870, 0.0921829641, -0.2072199881, -0.0147853196, -0.1459300816, -0.0892340988, -0.0889594033, -0.0213264525, 0.2104727328, -0.1749198288, -0.0741588920, -0.0848147422, 0.1499308944, -0.0320727378, -0.1704946905, 0.1370982528, -0.1597510427, 0.0103891939, 0.1807686388, -0.1413751245, -0.0901559144, -0.1192921996, 0.1687165797, -0.2074870616, -0.1928701401, -0.0669201016, 0.1421534419, -0.1442528218, 0.0908613503, -0.0952229574, 0.2038098872, -0.0267766118, 0.0151951164, 0.1892472506, 0.2125876546, -0.1569796354, -0.2104967088, 0.0884851515, -0.1223398298, 0.2005375922, -0.1431695074, -0.2004103661, -0.0165345669, 0.1019257307, -0.1666406840, 0.1041443050, 0.1377868652, 0.0636464655, -0.0799396485, 0.0861123502, 0.1729778945, 0.1917064190, -0.1925877780, -0.0982609242, 0.0424757600, -0.1279396266, -0.1854511499, 0.1656659544, 0.1626098752, -0.1451410949, 0.1050138772, 0.0140170008, -0.0016366541, -0.1785351932, -0.0096530616, -0.1227467284, 0.2013838887, -0.0196719617, 0.1457566619, 0.0698645711, -0.0506878197, -0.0471427590, 0.2125827074, 0.0489243269, 0.0402944684, -0.0839135051, -0.0288685113, -0.1964230835, -0.0570136905, -0.0616854131, -0.1989611685, 0.1908734441, -0.1933027208, 0.1848526597, -0.0239524394, -0.0085199922, 0.1121234000, -0.1739788949, -0.1694386750, 0.0083744079, 0.1795202494, -0.0554620773, -0.0602274835, 0.1674101651, -0.0737326741, 0.1095213592, -0.0379525721, -0.0252632648, 0.0479144752, 0.0578884780, -0.1163546816, 0.2028668225, -0.0403439105, -0.0248067081, -0.1026851013, -0.0549643934, -0.1903476566, -0.0831966400, -0.0815107822, 0.1428983808, 0.1499240398, 0.1336150169, 0.0306331515, -0.1386979073, 0.0693302453, -0.1745532900, -0.0618710965, -0.0677071065, 0.1083213389, -0.1957625747, -0.0262940675, 0.0788343847, 0.0354494005, 0.0325540155, 0.0333747715, 0.1720476747, -0.0050642937, 0.0154831707, -0.1973226815, 0.1037870646, -0.0082861632, 0.0791448057, -0.1626487225, -0.1265460849, 0.1839307547, -0.1693492085, 0.1280570030, -0.1016471311, 0.0476514399, 0.0513041019, 0.0320510864, -0.0869730860, 0.0718724132, -0.0137081146, -0.1089694872, 0.0720199347, 0.1315560937, 0.0817287564, 0.0773424208, -0.0913953781, 0.1013099253, -0.1286484152, -0.0467070341, 0.0211089551, 0.0025796741, 0.2097119689, -0.1783920527, -0.1623266935, 0.1405432224, 0.0569670200, 0.1915337443, 0.1316097677, -0.1873059273, -0.1660270989, -0.0686397552, -0.1768479049, -0.1941861510, -0.1430532634, -0.1345467418, -0.0608831942, 0.1528359950, -0.1801085621, -0.1618970335, -0.0384509116, 0.1670229435, -0.0734604150, -0.1029334590, -0.0753931701, 0.0075235516, 0.0085687339, -0.1843736917, 0.0329272598, 0.1680009067, 0.1883189380, 0.0350664407, 0.1527980864, 0.1766326427, -0.2059459686, 0.0709660947, 0.0986067653, -0.1684172153, 0.2084665298, 0.1004770994, -0.0400849879, 0.1573551893, 0.2078708708, 0.2048985958, 0.1998811662, -0.1924828142, -0.1506332308, -0.0651212335, 0.0612077713, -0.1890182197, 0.1755529344, 0.0698769987, -0.0095744282, 0.0152651668, -0.0292068422, -0.1200814024, 0.0461067855, 0.0474772453, 0.0015643686, 0.0931799114, -0.1282588840, 0.0867186785, -0.1885387897, 0.0013438165, 0.1249091327, 0.0619903505, 0.0521927774, -0.1607024521, 0.0634821951, 0.0705485642, -0.1398805380, 0.2093632817, 0.1580654383, 0.0336693376, -0.1646576077, 0.1115638614, 0.1249285936, -0.1532698274, -0.1884149611, 0.0932014585, 0.0517255962, 0.0089468211, -0.1837435812, 0.1259187460, -0.0921760425, 0.1063024402, 0.1357710660, 0.1838632524, 0.0786914527, 0.0544321239, 0.0473594069, -0.0513110608, 0.1398054659, -0.1390701830, -0.1819920540, 0.0718535483, 0.0709967315, -0.1687692255, -0.0864441842, 0.0273480564, -0.1973255873, 0.0981178880, -0.1333549023, 0.1491134763, -0.0804392695, -0.1057778150, 0.0567161739, -0.1458514035, -0.0863720030, 0.0843233168, -0.0496387184, 0.1119783819, 0.1851776242, 0.1442417502, 0.2072727978, 0.1606869400, -0.1883433908, 0.1129450798, 0.1143928468, -0.1908319741, -0.0253121704, 0.0722504854, 0.1173419654, -0.0715675205, 0.1647857428, 0.1161437929, 0.0974222124, -0.1756055355, -0.0168303549, -0.0217503905, -0.1586980820, -0.1896074563, -0.0390761346, -0.0023331940, 0.1008508205, 0.0488894582, 0.0642848015, 0.1373653114, -0.1095423549, 0.1388662159, 0.1861095726, -0.0074812621, -0.0166262686, -0.0528066158, -0.1696114987, 0.1061561108, -0.0549411625, -0.1410522461, -0.1265841126, 0.0688604712, 0.1769667864, 0.1361033320, -0.0097976327, 0.0556917787, 0.1916642189, 0.0340525061, -0.0521488637, -0.1872127503, 0.0439819992, -0.1107872576, -0.0538937896, 0.1570566595, -0.0902339444, -0.0609310865, -0.1839942336, 0.1206285357, -0.0781041831, -0.1185983568, 0.0614432991, 0.1199873686, -0.0158654302, 0.0093431026, 0.0897020102, 0.0271121413, -0.1121155247, -0.1972154826, -0.0506454259, 0.0792386234, 0.1528101861, -0.1691373885, -0.1117611304, -0.1237250715, 0.1570326090, 0.0836027861, -0.1249725148, -0.1913276762, 0.1799748838, 0.0317695886, 0.0915957987, -0.0537778884, 0.1019198895, 0.0789291859, -0.0185148865, 0.1365544200, 0.0012650341, 0.2046919167, -0.1252259612, -0.0282614827, -0.0599798858, -0.0252795815, -0.0837962478, -0.0550680757, 0.0649763048, -0.0104622394, 0.1165009737, -0.2109362483, -0.1376764476, 0.2091076672, -0.1718324572, -0.1353810281, -0.1705467850, -0.0097470433, 0.1090845764, 0.1511430740, 0.1596433222, -0.0172036588, -0.1752222180, -0.0907011330, -0.0523476005, -0.0778975636, -0.0292850733, -0.1940959841, -0.0887255818, -0.0513249934, -0.0652970076, -0.0926434845, 0.1552390754, -0.0443678498, 0.1251921058, -0.1626410484, 0.0926787555, 0.1792289913, -0.1946324557, -0.1256407946, -0.0225305408, 0.1979660094, 0.1523216963, -0.0357439667, -0.0577572435, 0.1088013351, 0.0912234187, -0.0291785747, -0.1710796058, -0.2067052275, 0.2029761076, 0.1381095350, -0.1073800027, 0.0964722335, -0.1850559413, -0.1840608269, 0.1598322690, 0.0071673691, -0.2129073739, -0.1250619292, 0.0389801264, 0.0823149681, -0.0658542216, 0.0289013386, 0.2020024061, 0.0472106636, 0.1408573091, 0.1113214791, -0.2086748779, 0.1343995333, 0.0877676606, 0.1859664321, 0.0506578684, 0.1138330102, 0.1881920695, -0.0601821393, 0.1593374908, -0.0242364258, -0.1655089855, 0.1032479107, 0.2029424012, -0.0320668966, -0.0417693704, -0.1471744329, 0.1772362888, -0.1648610830, -0.0230969042, -0.1128182113, 0.0837174952, -0.1439721882, 0.1391288936, -0.1311879307, -0.1222508177, -0.1577120572, 0.2007710040, 0.0791011453, -0.0675868988, -0.0520371348, 0.0969536901, 0.0871776640, -0.1623048484, -0.0280459076, -0.0025532395, -0.1955051720, -0.0410415232, -0.1748048514, -0.0075336695, -0.0997597724, 0.1552977860, 0.0717715621, 0.0068704188, 0.0518671572, -0.0879601240, 0.0918017626, 0.1279027760, 0.1960412264, 0.0597797036, 0.0250352323, -0.0911321789, -0.1874019951, 0.0814309716, 0.0181226730, -0.1598652601, -0.0310108364, 0.0554268360, 0.0855072737, 0.1992585957, -0.1658549309, 0.1668510139, -0.1960341185, 0.0550440252, 0.0207350850, 0.1846005023, 0.0892125368, 0.0696214139, -0.1345083117, 0.0902889371, -0.1219682544, -0.0440082699, 0.1583348811, 0.1831572652, -0.0227335095, 0.2093854845, 0.1487198472, -0.0454178154, -0.1200702712, 0.0506695807, -0.1670876890, 0.0730926692, -0.0377478153, 0.1500038505, 0.2061194479, 0.1362510622, 0.0697242916, 0.0146648437, -0.0070878267, 0.0881031454, -0.1372570097, 0.1414441466, -0.0860091299, -0.2012100369, 0.1995158792, 0.1993721426, 0.2129037678, -0.0387273282, 0.0281131566, 0.1571446359, -0.0163650513, 0.0592943728, 0.1159420907, -0.1847553849, 0.0912800431, -0.1641400456, 0.1106509268, 0.1053180397, -0.1962069422, 0.1062380970, 0.0709238946, -0.0276379883, -0.0647808164, -0.0817310363, 0.1182181835, 0.1167886853, 0.0541085303, 0.1357671916, -0.1107763276, -0.0280494690, 0.1466166675, 0.0162720680, 0.0692138076, 0.0160253942, 0.1892643869, 0.1467187405, -0.1632732302, 0.1803488433, -0.1579830348, -0.1282528043, -0.0057222545, 0.0341107547, 0.0340652168, -0.1217539459, 0.1527514756, -0.0568480343, -0.1957312226, -0.0784360170, -0.1140084714, 0.0536070466, 0.0229471028, 0.1840257049, -0.1380712688, 0.0556440949, 0.1309313476, -0.1331313998, -0.0476581454, 0.0168934762, 0.1444199979, 0.1245186925, 0.1474438906, -0.0554386973, -0.1847412437, 0.0342960954, 0.0485461652, -0.2036251724, 0.0709468126, -0.0379859209, -0.1454381943, -0.0714997649, 0.0947059095, -0.1664340049, 0.1834268570, 0.0919531882, -0.1530278325, 0.2068942785, -0.0420753658, 0.1849041581, -0.1002729163, 0.1988419294, 0.0943531394, -0.1277283132, 0.0976471305, 0.0186871588, -0.0238777101, 0.0256373882, -0.0616322905, -0.1633119583, -0.2113031894, -0.0011393726, 0.1629575789, 0.1692775488, -0.0856769979, -0.0398735255, 0.2087187469, 0.1409768164, -0.0698124766, -0.0291483849, 0.0173804462, -0.0529693663, -0.1211816445, -0.0941947475, -0.1876989007, 0.1341651678, -0.0228612423, 0.1899296641, -0.0659681857, 0.1791129708, 0.0353442281, 0.1920144558, 0.0855770707, -0.2012451589, -0.1596216261, -0.0576818138, -0.0696182549, -0.0370560586, 0.1411648989, 0.0936513543, -0.1266936064, 0.0163802356, 0.2037049830, 0.0435677767, -0.1233056635, -0.1006579623, -0.0307743698, -0.0632095784, 0.0825739205, -0.0214114487, -0.1908553988, -0.0510985851, 0.0406039655, -0.1050481349, 0.0843189955, -0.0153014511, -0.1254773140, 0.2034479380, -0.0365235507, 0.0924013257, -0.1451801807, 0.2093302011, -0.1621778160, 0.0323058516, -0.1886439472, 0.0478064120, -0.1992603689, 0.1910296679, 0.0627740026, 0.0920626819, -0.1851127744, 0.0248233825, -0.2017012686, 0.1918494999, -0.1685944796, 0.1771685481, -0.0458932370, 0.1198258400, -0.0307605863, 0.1338742971, 0.2016800642, -0.2129886448, 0.0085784942, 0.0989363194, -0.0552743524, -0.1927256882, -0.0771643668, 0.0592687428, -0.1586670280, -0.0870227963, 0.0503590405, 0.0408625007, 0.1513848305, -0.1753961742, -0.0910049975, 0.1904300451, -0.1627425551, 0.0149302930, -0.0194987208, -0.1019753963, 0.0691846609, -0.1802852452, -0.2079423964, -0.0232513696, 0.1148614585, 0.1473616362, -0.1185828522, -0.1476247460, -0.0781639218, 0.0003054440, -0.1946229935, 0.0906373858, 0.0520909131, -0.0696749389, 0.1836592555, -0.0613439381, 0.2026910484, 0.0019484013, -0.0996881574, -0.0979242697, -0.2061058730, -0.0485235900, 0.0323083997, 0.1120965779, 0.0698562562, -0.2026646733, -0.0974542350, -0.1153426319, 0.0070716590, -0.1193417609, 0.0585309565, 0.1077032387, -0.1405243129, -0.1469416320, -0.0118951201, 0.1504545212, 0.2068819106, -0.0345447063, 0.1558310688, -0.0401609689, -0.1281215549, -0.1485913992, -0.0325951278, 0.0236924887, -0.1412186623, -0.0989285335, -0.1125764102, 0.2117060721, -0.1755986810, -0.0379357487, -0.1456120461, -0.1759462059, 0.1071435511, -0.1095023528, 0.0897330940, 0.0590722859, -0.0538412184, -0.1669235080, 0.1190285385, 0.1856550872, -0.1246593967, -0.0452941358, -0.1681733429, -0.1650929302, 0.1673581600, 0.1749532223, 0.1103092432, 0.1773640811, 0.0196264684, -0.0606461763, 0.1917156577, -0.1570813507, -0.0482148975, 0.1045039296, -0.0833038390, 0.1934553087, -0.2046683282, 0.0115418434, 0.2022055686, 0.0367304832, -0.1198011190, -0.1145377755, 0.1659276783, -0.1711680442, 0.0928618014, 0.0347656608, 0.2130160928, 0.0912171602, 0.0163737386, -0.0857663006, -0.0393097103, -0.2092131227, -0.0897728577, -0.0448745340, -0.1397090405, -0.0905019715, 0.0188910365, 0.0904752910, -0.1662477106, -0.1537895799, 0.0561960340, 0.0095788538, -0.0508569330, -0.1168929264, -0.1259870529, 0.0583164394, 0.1533126831, -0.1222576797, 0.1557004750, 0.0525202155, -0.1796438098, -0.0919916779, -0.0360903740, 0.0956878662, 0.0841439664, 0.0375068188, -0.2066167742, 0.0058252811, 0.0962599516, -0.0490829796, 0.0021192431, 0.0402545631, 0.1363182664, -0.1359829307, -0.1802334040, 0.1274853051, -0.1081600040, -0.1473830491, -0.1813733876, -0.0096957684, 0.0478501320, 0.0771263540, -0.2086321861, -0.0535877794, 0.1153199673, 0.1019386351, 0.0595577359, -0.1449661255, 0.1209572852, -0.1217929348, 0.1701689661, -0.1500580311, 0.1806248426, -0.1651500612, -0.0812479854, -0.0782255232, 0.0879411995, -0.0171717256, 0.0299322009, -0.1999279261, 0.0488563776, -0.2054077685, -0.1058893874, 0.1868181527, 0.1597919166, -0.1933054030, -0.0893015489, 0.2095572650, 0.1075255275, 0.0263815522, -0.1575437635, 0.0937550962, 0.0803167522, 0.1283850074, 0.1627438664, -0.1260104328, 0.1386916041, 0.0021191388, 0.1538386345, 0.0292192996, -0.1366710663, 0.0025791675, 0.0551883876, -0.0341164470, 0.2125579715, -0.0129152983, 0.0043642521, 0.1742798090, -0.1281677485, 0.0298834443, -0.0716484934, -0.1951778680, 0.0928669870, 0.1479415894, -0.0937376246, 0.1383763552, 0.1601681709, 0.1671158969, -0.1943475455, 0.1315532625, -0.0645507574, 0.0437509716, 0.1643465757, -0.1303095669, -0.0779238343, -0.0417658091, 0.1274443269, -0.1462714225, 0.0412399173, 0.1863614321, 0.0664007664, 0.1757509708, -0.1520830393, 0.0112962723, 0.0828160644, -0.2097683549, 0.0648523867, -0.0168878883, -0.0203789175, 0.1985651553, 0.1011780202, 0.1745383441, 0.1499823034, 0.2079764009, 0.0816646516, 0.1186003983, -0.0535969287, 0.1682977676, -0.0158083439, -0.1617091000, 0.0476481318, 0.1407393217, 0.0001622587, 0.0945599675, 0.0866003931, 0.0938604176, 0.1383636296, 0.1371096373, 0.1208607852, -0.0270037204, -0.1119401604, 0.0896398425, -0.1295544803, -0.1550250798, -0.1024166644, -0.0933098793, -0.1743687242, -0.0390040576, 0.0148617625, 0.0447485149, 0.1119694412, 0.0492811799, 0.0449284017, -0.0321076661, -0.0946635082, 0.1151131690, 0.0400865078, 0.0852429867, -0.0430465490, 0.1623199284, 0.0557721853, 0.1113232076, -0.1964957714, -0.1067959070, 0.0526090264, -0.1610911041, 0.0771970153, 0.1714132428, 0.0462478995, -0.0748775899, 0.1127077639, -0.0926309302, 0.1933218837, -0.0828977525, 0.0463362336, -0.1324259192, 0.2050657868, -0.1675897986, 0.1589995027, 0.1578087807, -0.0372102261, 0.0368894935, 0.0065888613, 0.0016215146, -0.2060333490, 0.1892905235, -0.1701564491, 0.0464455187, 0.1175576448, 0.0851863623, 0.0066614002, 0.1565407217, -0.1849170774, -0.0165613592, 0.1825207472, 0.0341811627, -0.1399172395, -0.0554997325, -0.0532411635, -0.1934920549, -0.1772823632, -0.0655783117, 0.1964595318, 0.1447093785, 0.1229943335, 0.0632467866, -0.0328790694, 0.1104698777, 0.0611682236, -0.0608098954, -0.0657706559, -0.0787817091, -0.1938354671, 0.1142753959, -0.0829502642, 0.0175814778, -0.1325020641, -0.0780659616, -0.1990582049, 0.2112723887, -0.1553747505, -0.0798613131, 0.0551274121, 0.1428200603, 0.1224687994, 0.0259825736, 0.1331348717, 0.1315174103, 0.1793091893, -0.0879709423, 0.0909688175, -0.0981649011, 0.0858121514, 0.1802685261, -0.0026372671, -0.1356098205, -0.1719633490, -0.1789807230, 0.0798831582, 0.0582580268, -0.1044361293, -0.1631913334, 0.1257994473, 0.0747932494, 0.1154229939, 0.0231893063, 0.0567423105, 0.0604450405, -0.2107093334, -0.0749627799, -0.1914475858, 0.0437601209, 0.1855938733, 0.2007837594, 0.1338332295, -0.1269670725, 0.0130960494, -0.1011529490, -0.1249871552, 0.1358241141, 0.0872164071, -0.0887128264, -0.1060122475, -0.1883794218, 0.2048520744, 0.0388409793, -0.0951914415, -0.0441533476, -0.0458308160, 0.0420882702, -0.1980627775, 0.1205570698, 0.2019619942, 0.0513183177, 0.1594775319, 0.1197360158, -0.0784743875, -0.1497696638, -0.0182491541, -0.1293919683, 0.0574680269, 0.1754296124, -0.0589711368, 0.0111865401, 0.0450025797, 0.0575985610, 0.0642512143, -0.1421603560, 0.1481683850, 0.0333788991, 0.1222280562, 0.0098046362, 0.0922617912, 0.1810188293, 0.1967584193, -0.1292517185, 0.1636549234, -0.1694006473, 0.0721220374, -0.0027960688, 0.0289781541, -0.1374978870, -0.1105206013, 0.0905115902, 0.0465723872, 0.0512376726, 0.0014149249, -0.1960090548, 0.1336880624, 0.1239778697, 0.0018246323, -0.1423616111, 0.1602640748, 0.1318146884, -0.1008566096, 0.0192181915, 0.0763817430, 0.0348337740, 0.1360687315, -0.1250124723, 0.1015513539, -0.0817829818, -0.1092065126, 0.0173519254, 0.0436394513, -0.0468415469, 0.1463158429, -0.0785777271, 0.0302119702, 0.0263187736, -0.0074735880, 0.1262762845, -0.0813904703, 0.1677648127, 0.1713149846, -0.0686187595, -0.0685251802, -0.0151415914, -0.1574501246, 0.1367207766, 0.1761445999, 0.2093665898, -0.0521663427, -0.1315490901, 0.1619792581, -0.1619434357, -0.1917611063, 0.1341825426, 0.0560451448, -0.1994723231, -0.0339842439, -0.1655012965, 0.1874391139, -0.0665728748, -0.2021121830, -0.0587394089, 0.1683867872, -0.1739189178, 0.1563077569, 0.1677886844, -0.1587698460, 0.2030812800, -0.1093225107, 0.2130799294, 0.1177565455, 0.1293844581, -0.2131954283, -0.1952110082, 0.1411190331, 0.0855821371, 0.1532515883, -0.1028959453, -0.0664155930, -0.0840103477, 0.0148153603, -0.1788078398, -0.1269693077, 0.0636402369, 0.0710251033, 0.1511216760, 0.0666429698, 0.1180694997, 0.2021875083, -0.0425276607, -0.1047077700, 0.1603533924, 0.1251109242, 0.0810645223, 0.1455161870, -0.0240291953, -0.1777985990, 0.1208658814, -0.0302214772, -0.1385754049, -0.1722335666, -0.1607687324, -0.0364927053, -0.0314335376, -0.0647694319, 0.1739393473, -0.0728218853, 0.1783054173, 0.1548511386, 0.1999092102, 0.0302997530, -0.0426795483, 0.0648125410, -0.0877423137, 0.1345773935, 0.1706428230, -0.0795313269, -0.0809811801, 0.0900012851, -0.0148148537, -0.1967352778, -0.1688222438, -0.1740829945, -0.1589090228, 0.0538221598, -0.1631648540, -0.1131669134, 0.0895903707, 0.0421771407, 0.0514474511, -0.1988473684, 0.1412400603, 0.1809027493, -0.0732579082, -0.0802176893, -0.1999509037, 0.0048704296, -0.1728903055, 0.0200094730, 0.1794625521, 0.0761397183, 0.0587445498, 0.1545799077, 0.1583607793, 0.0414906144, -0.0822204798, 0.0681066811, 0.1219957471, -0.1745245755, 0.0641526580, 0.0150034875, -0.0179223567, 0.0015339851, -0.1800732315, -0.0712532401, -0.1482105255, -0.1208747253, -0.1311452836, 0.1096603274, -0.1164696068, 0.2121781409, -0.0507577211, -0.0616377890, 0.0436992049, 0.0920339227, 0.2028413117, -0.1719179600, 0.1553429663, 0.0769672096, 0.1607833207, -0.0776915997, 0.1592099369, 0.0526845157, -0.2035764307, -0.1737343967, 0.1263822019, -0.1020136252, 0.2073834538, -0.1773916483, -0.1785380840, 0.1485368013, 0.0042837858, -0.1991783679, -0.0641485304, 0.1616183221, 0.0172713548, -0.1680070758, 0.0367290080, 0.0426670909, 0.0856925845, -0.1223958433, -0.0784772336, -0.2052665502, -0.0422638059, -0.1747235209, 0.0624602735, 0.0655645430, -0.0677023828, 0.2100816667, 0.1441288888, -0.1587779820, 0.0161279142, 0.0624574423, -0.2083326280, 0.1074596941, 0.0567601025, -0.0765303075, -0.1200548187, -0.1794728637, -0.1170208678, 0.1262377501, 0.0309961885, 0.0251553059, 0.1659008861, 0.1706125140, 0.1145618260, -0.0490875095, -0.1169596165, -0.0409267992, 0.0618336797, -0.2048173696, 0.0021907091, -0.0061539114, 0.1302522421, -0.1065987349, -0.1958718151, 0.0671834946, -0.1894103289, 0.0651319623, 0.0262213349, 0.1392145455, -0.1988502592, -0.0136579871, -0.0205741525, -0.0671000928, -0.1551161259, 0.0107717514, 0.0022179037, -0.0987654179, 0.1287915409, 0.1183460951, 0.0700584650, -0.0870736241, 0.0667438209, -0.0383139253, 0.1231867075, -0.0771709383, -0.2019595951, 0.1078383923, -0.0091558397, -0.1216481179, 0.1064752638, 0.1958286464, 0.0468741357, 0.1828132868, -0.0485149920, -0.1939623505, 0.2035515308, -0.0663258284, 0.0211003572, -0.2053535283, 0.1489544809, 0.1923023164, 0.0543997586, -0.1097443104, -0.1778039783, -0.1685322076, -0.0611888468, 0.0956527889, 0.0198410153, 0.1694431603, -0.1582887471, 0.1487581134, 0.0298632234, 0.2071783245, -0.0590164810, -0.1364271343, 0.1506095529, -0.1012387052, 0.0093348622, 0.1344440579, 0.1307239830, -0.0739731491, -0.1634575874, 0.0750719607, -0.0726677626, 0.0165913999, -0.1260736585, 0.0848121047, 0.1920724511, 0.1866309941, -0.1440292150, 0.0530213714, -0.1068393663, -0.1572163105, -0.1817591935, 0.0872799456, -0.1363787353, 0.0342573524, 0.1573859155, 0.0643665493, -0.0841873884, 0.0996667445, -0.1815573871, -0.1556952894, 0.1443904340, -0.1696757972, 0.1797145605, 0.1919395328, -0.0852943808, -0.0432171375, 0.1305790842, 0.0064933598, 0.1770673990, -0.1004561633, -0.0653946549, -0.1894420534, 0.1474712789, 0.1597555578, 0.0644319654, 0.0112381727, 0.1773147881, 0.1368961930, -0.1696494222, -0.0794858336, 0.0543223917, -0.1608809680, 0.1402814388, 0.1976004243, 0.1423691213, 0.1369906366, 0.1369352937, -0.1916384101, -0.0003434718, -0.1823771000, -0.0920493752, -0.1194690466, -0.1343110800, -0.1054637805, -0.2012929916, 0.0553362668, 0.1735905111, -0.0886167511, 0.0628515184, -0.0775610059, -0.1044777557, -0.0881972462, 0.0609320104, -0.0460686982, 0.1779697835, 0.0804338157, -0.1629889756, -0.0943208560, -0.1311645955, 0.0961579978, -0.1141553745, 0.0923919678, -0.1632291526, 0.1006371677, -0.1108925790, -0.0012696087, 0.0399169922, 0.1142591834, -0.1421104372, -0.0174781978, 0.1302104592, -0.2063336521, 0.1987169683, 0.0140927434, 0.2010957599, 0.0888950527, -0.1703964770, -0.1330864727, -0.1129195169, 0.1431652904, -0.0087963045, 0.1897248328, -0.0336518139, -0.1243215725, 0.1992536485, -0.1858008653, -0.0389436781, -0.1441355646, -0.0483581275, -0.1993281692, -0.1753670871, -0.1082982644, -0.1959311366, 0.1117576361, -0.2010479867, -0.1241202354, -0.1972450167, 0.0678546131, 0.1490649879, -0.1754833460, 0.1168682873, -0.1774145216, 0.0227796584, -0.1417134553, 0.0673241615, 0.1737882197, 0.0875216126, 0.0729320347, -0.0616698563, -0.1281520426, -0.1989519149, 0.0506260693, 0.0031040460, -0.0599344969, -0.0999724045, 0.0916744471, -0.0527899414, 0.0402813554, 0.0755846500, -0.1540571600, 0.0956314206, -0.1533639282, 0.1268324852, -0.0474900454, -0.0872085243, 0.0557737052, -0.0806360841, 0.0710445642, 0.1065910161, 0.1539396346, -0.1553277373, 0.0808281302, -0.0243396163, -0.0551216006, -0.0355269164, 0.1911634505, 0.1564151049, 0.1697790921, -0.0528497696, 0.0984633863, -0.0529521406, -0.2101432383, 0.1568694413, 0.1261364520, -0.0316334069, -0.0699019432, 0.1140802503, -0.1544983685, -0.0391753614, -0.1233761162, 0.1802347600, -0.0190109462, -0.0831044316, -0.2082015872, -0.2094552815, -0.1421009302, 0.0446969271, 0.1180342734, 0.0346517116, -0.1930497289, -0.0490227938, -0.1677147895, -0.0491812974, 0.1212866604, 0.1160207093, 0.2117471397, 0.1301966608, -0.2032881081, -0.1543271691, -0.1442168951, -0.1038520783, 0.0471235514, -0.1585114300, 0.0527115166, -0.1329412460, 0.0585195124, 0.1939077675, -0.0408542603, 0.0379559696, -0.1076223180, 0.1626552641, -0.0470750630, -0.1445066631, 0.0631578267, -0.1279372871, 0.1168318689, -0.0907143429, -0.0983053446, 0.0499971211, -0.1543325186, -0.0352110416, -0.1911678612, 0.2012702823, -0.0674726218, -0.0280527174, -0.1482307613, -0.0866022259, 0.0135001093, -0.0755891651, 0.1493487954, -0.0923628435, 0.1512388885, 0.1105206609, -0.1233010888, -0.1604435742, -0.0687525570, 0.0480512083, 0.0533574522, 0.0810398459, 0.2036272585, 0.1289487779, 0.0090710521, -0.0519945920, 0.1261376739, -0.2042019963, 0.1476466656, 0.0121955872, -0.1674290150, 0.0097776949, 0.1986927986, 0.1322011054, -0.0863118172, 0.0273644179, -0.1336909980, 0.1636165977, -0.1228503212, -0.0751855224, -0.1121777445, -0.1152681634, -0.1866390705, -0.0889009461, -0.1258024275, -0.1915954500, -0.1558095515, -0.0735427141, 0.1202566326, 0.0228019208, -0.1811176538, 0.0133337379, 0.1875566244, 0.1818839908, 0.1318564713, 0.1887971163, -0.1080502123, -0.0883422121, -0.0622210801, 0.1333971620, -0.1905879378, 0.1017746627, -0.0049944073, -0.0265125483, 0.0914417803, 0.0491191149, 0.0685849488, -0.0211933255, 0.0164035708, -0.1089145392, -0.0075309128, -0.1465310752, -0.0649724603, 0.0363533199, -0.1956815124, 0.2007778585, -0.0128664970, -0.0485958755, -0.1622623503, -0.0534678698, -0.1758344322, -0.1261566281, -0.0731016994, 0.1904644072, 0.0895338953, -0.0453352630, 0.0471154749, 0.0413264632, 0.0719670057, -0.0446490943, -0.1264902353, 0.0893809497, -0.1692527831, 0.1201239526, 0.0458091199, 0.0051479638, -0.1877388060, -0.1992911696, 0.0982604623, 0.0934755504, 0.1866677403, -0.0781512558, 0.1888723373, 0.0367126018, -0.1654497683, -0.0991836563, -0.2052423656, -0.1020171270, 0.1388156414, 0.0897136331, -0.1058568060, -0.2055169046, 0.1068682373, -0.0308343023, 0.0184083432, 0.1758403778, -0.1735419035, 0.1746751964, 0.0020956099, 0.1933275759, 0.1729234457, -0.0949942693, -0.0631643981, 0.0157373846, -0.1988634169, 0.1142289639, 0.0629304647, -0.1140842587, -0.1448621303, 0.1459372640, -0.1504361033, -0.0824999511, 0.0407643914, 0.1589671671, -0.1848030090, 0.1760683060, -0.1430222541, 0.2027480304, -0.1728915274, 0.0866293609, -0.1914968938, 0.0221603960, 0.0069704056, 0.0888171196, -0.0728658438, -0.1679234058, 0.2006779015, 0.0904677510, 0.0584804118, -0.1882095039, 0.0623434186, 0.0868101716, -0.1981459409, -0.1769716740, -0.1821801215, -0.1996962428, -0.0516619980, -0.0329256803, -0.0241647512, 0.2022213340, -0.1534017473, 0.0064666271, 0.0136136115, -0.1948258728, -0.1259876639, 0.1414062977, -0.0981904715, -0.1901355386, 0.1337595284, 0.0206441581, -0.1829779744, -0.2119307518, -0.2014321238, -0.2070757300, 0.2016168833, 0.1520060301, 0.0576945245, -0.1641073674, 0.2129188180, 0.1198900342, 0.1515713036, -0.0608581454, -0.0445007682, 0.0263260454, -0.0153774023, -0.0441926867, -0.1944570839, -0.1918360293, -0.0928257108, 0.1664627194, -0.0336474329, -0.1162796989, 0.1217368543, -0.1634105742, 0.0026267916, -0.0529325753, 0.0312067270, 0.0766163766, -0.0213577747, 0.0142683089, 0.0897280276, 0.1391752064, 0.0983397663, -0.0214587152, 0.1951382756, 0.0966913998, 0.0634912848, 0.1193961501, -0.0797929019, -0.1105776280, -0.2024938762, -0.2046627402, -0.0074753165, 0.1339516044, 0.1118431091, 0.0258384198, -0.1532483846, 0.1079897285, -0.1471315920, -0.1969375908, -0.0491231382, 0.1895702481, -0.0908532664, -0.0205998272, -0.0303425491, 0.0942589343, -0.1515416354, -0.1911843270, -0.1956821084, 0.0328252465, -0.0698693544, 0.1393386424, 0.1255013645, -0.1359865367, -0.1153906658, -0.2013411373, 0.1948916912, 0.1798245609, -0.1803007573, 0.1591883600, 0.1799423993, -0.0448904485, 0.1550146639, 0.0960927308, -0.0381173640, 0.0505827665, 0.0100210309, -0.1992234588, 0.2105712891, 0.1631121039, -0.1470948756, 0.0464096367, -0.0892922506, 0.0061459243, -0.1188981086, 0.2076775134, -0.0202621520, -0.1745906472, 0.0017700940, -0.1732509434, -0.1283423007, -0.2061740905, -0.1173758730, 0.1094646454, 0.0291360766, 0.1319639087, 0.0616571903, -0.1173392236, 0.0388348997, 0.0463386178, 0.0711835325, 0.1015142202, 0.2081853747, 0.0392340720, -0.0313192159, 0.1544469893, -0.1229915842, -0.0897011310, 0.0191840380, 0.0172591656, -0.1115615144, -0.0446022749, -0.0246111602, -0.1259313822, 0.0429498255, 0.0209326744, 0.1083736420, -0.1967430562, -0.0494222790, -0.1241185591, -0.2087697238, -0.1070556492, 0.1874563396, -0.1921684742, -0.0546354055, 0.0826970339, -0.1646238118, 0.1755934060, 0.1608643532, 0.0891706645, 0.1062918007, -0.1836696267, 0.0712143481, 0.0263563842, 0.0245463997, 0.1114870608, -0.0054905117, -0.1699474901, 0.0511034727, -0.0389646143, 0.1326921284, 0.2091339231, -0.1154052541, 0.1012003720, -0.1097671837, 0.0535662770, -0.0994428918, -0.0913146585, -0.1386704594, 0.2016600966, 0.0887771845, -0.1257243603, -0.0820882767, 0.1031100452, -0.0497890711, 0.0502878428, 0.1775922179, 0.1025641263, 0.1124098301, 0.1815298498, 0.0270941556, -0.1643512994, -0.1529047638, 0.0486496985, -0.0657847375, 0.1740065515, 0.1092291474, 0.1655963063, 0.0181917548, -0.0301538259, -0.0105724931, 0.0343169272, 0.0566281378, 0.1327677667, 0.2033062577, 0.0455288291, 0.0444711447, 0.0478150547, -0.0963646695, 0.1863059402, -0.2023345679, 0.1783591509, -0.0955072045, -0.0467385054, -0.0059748739, -0.0564950109, -0.1791038364, -0.1472482979, 0.0740091801, -0.1851411313, 0.0521834791, -0.0583557785, -0.1822416335, -0.1446902156, 0.0449821949, 0.1829200089, 0.1103640497, -0.0638640821, 0.0577831566, 0.1330929101, 0.0252168626, 0.1610595286, 0.1414406896, 0.1278419197, -0.0865726322, -0.0298154354, -0.1893062741, -0.0276203007, -0.2051651925, 0.1729630530, -0.1191663966, -0.0101634115, 0.1196340322, -0.2021226138, 0.0506027341, -0.0275796354, -0.2118948251, 0.0645498037, 0.0415663421, 0.0208124965, 0.0297508389, -0.1058726087, -0.0960093141, 0.0323980153, 0.1219114363, 0.0073639899, -0.0621746629, -0.1616859287, 0.2098265588, -0.0894307122, 0.1868473291, -0.0518244058, 0.0832658112, -0.0944210961, 0.1686597764, -0.2128241658, -0.0369138420, 0.0180789083, 0.2084040940, 0.0804129243, 0.0320252180, -0.2106931210, -0.1005151719, 0.1411907077, 0.1748240590, 0.1631378233, 0.0596881211, 0.1924263835, -0.0611590594, -0.0674935132, -0.1090021208, -0.0104370862, -0.1327804625, -0.0579845607, 0.1376307607, -0.0479622185, 0.1878094971, 0.0128329992, -0.0724753141, -0.0014405549, -0.0314305872, -0.1874136925, 0.1370508671, -0.0533346981, 0.1863775849, -0.0191536844, 0.0459181368, 0.1270267069, -0.1028755605, -0.0549217910, -0.0981757790, -0.0725408345, 0.0917052329, -0.1448445469, 0.0885515809, 0.1468529701, -0.1390465051, -0.1744889915, 0.1972120702, 0.1607232392, -0.0518392920, 0.1493856907, 0.0715863705, -0.1714482307, 0.1151228249, 0.1040072143, 0.1014150381, -0.1442594230, -0.1425091177, 0.1732893288, 0.0037401915, -0.0359322429, -0.0604691803, -0.1113087833, 0.0732270181, -0.0263893753, 0.0746116340, -0.1455382407, -0.1982153356, 0.1978387833, 0.1625904143, 0.0273582637, 0.0730413198, -0.1056326926, 0.0026047826, 0.0402204394, 0.0023018867, -0.0022009313, 0.0595671237, -0.0149376094, 0.0018262118, 0.0813457966, -0.1641079187, -0.0237189680, -0.1038066894, 0.1900723577, 0.1491495371, 0.1897017062, -0.0005613714, 0.1973762214, 0.1174893677, -0.0404330194, -0.1657633334, -0.0062251240, -0.0278593600, -0.0390315652, -0.2048531473, -0.0512534678, -0.0491373241, -0.0703801662, 0.1991268694, -0.0515239984, 0.1231005192, 0.0469681025, -0.1932683587, -0.1080608368, -0.0281383246, 0.0494581759, -0.1514368653, 0.0292558372, -0.1003489047, 0.0911124647, 0.1564387381, -0.0335830301, 0.1455479562, -0.1816011071, -0.1823195070, 0.1514663398, 0.1406163275, 0.1885030866, 0.1242824793, -0.1546808034, 0.0902919769, 0.1428492665, 0.1209816337, 0.1254950166, 0.0104650855, -0.0278489888, 0.2117148340, 0.0476858020, -0.0285566598, -0.0231694877, 0.0942659080, 0.1007203162, -0.0654558539, -0.0197696090, -0.0360016674, -0.0822589099, -0.1410555989, -0.0435803235, -0.1660849452, -0.0906480104, -0.0888994262, 0.1141942441, -0.0609730631, -0.1611536741, -0.0345421582, -0.1260350943, 0.0602631271, 0.0068634599, -0.0013623685, 0.0577225685, 0.0498258770, -0.0454781502, 0.1336076856, -0.1478631496, -0.0520296097, 0.1747241914, -0.1216610819, 0.1275118887, 0.1920532286, 0.1035468876, 0.2099753916, 0.0930824578, 0.0928864479, 0.0606037974, 0.2127641439, -0.1250537485, -0.1049612612, -0.0707738549, 0.0462386906, -0.1050541848, 0.2092462778, -0.1090416685, 0.0559493899, 0.1075286865, -0.0880913138, 0.0391494930, 0.1240768135, 0.1675392091, -0.0021153390, 0.1942414045, -0.0543267131, 0.0014681518, -0.0163033903, 0.1526921391, -0.0191472322, 0.1401652992, -0.0621625632, -0.2075629979, 0.1902502179, -0.0940558240, 0.1499597728, -0.0059809238, -0.1281908303, -0.0047522932, -0.1359102726, 0.0226327628, -0.0899245366, 0.0602328181, 0.0490871668, -0.1129359379, 0.1284369528, -0.0491100848, -0.0632094890, -0.1382881999, -0.0992899984, 0.0823422670, -0.0516955405, 0.1959424615, 0.1074351966, -0.2029730082, -0.0280252695, -0.1267211139, 0.2108168900, 0.0787534416, 0.1409596801, -0.0079249591, -0.2029214650, 0.1065075397, -0.0624595284, 0.1264002025, -0.0331930071, -0.0036305487, 0.0398704708, -0.0536184311, 0.0965144336, 0.1448169947, -0.1047319099, -0.0682462305, -0.0593087673, 0.0430641770, 0.0490980446, -0.0456942320, 0.1098040938, 0.0605421364, 0.0756760538, -0.1713852435, -0.1462914050, 0.1456372142, 0.0425437689, -0.1593762636, -0.0411698669, -0.0468895286, -0.0404934138, -0.0533497930, -0.2037094980, -0.1210984290, 0.0971468687, -0.0182767957, 0.1336697638, 0.1266036332, -0.1628730297, -0.0623703599, 0.1259144247, -0.2109924704, 0.0345640779, -0.2010063082, -0.0547237545, 0.1184599996, 0.0638903081, 0.0830134451, 0.2000322342, 0.1686373353, -0.1161610633, -0.1020248532, 0.1424554884, -0.0655421168, -0.0307706594, -0.0887754485, -0.1944266409, 0.1821271181, 0.0132096559, -0.0968938693, -0.1559327245, 0.0559995472, -0.0802386403, -0.1336320937, -0.1590941101, 0.1365468502, -0.0255953968, -0.0536271185, -0.0097687095, -0.1681897640, -0.1241566315, -0.0073689669, 0.1953168511, 0.0262402445, -0.1826559603, -0.0381529480, -0.0196370333, 0.0424892902, -0.0236828327, 0.0686831176, -0.1641728282, 0.1568455398, -0.1511853039, -0.0903801322, -0.0461353958, 0.0670965314, -0.1016566381, 0.1658084691, 0.1047852933, -0.1087132022, -0.1448681355, 0.1455472410, -0.0213940144, 0.1067807972, 0.1495614052, -0.0840581208, -0.1165622175, -0.1263452619, -0.0158583075, -0.1421947777, 0.1319160759, 0.1434713006, -0.0974691808, 0.0908687115, -0.0406492501, 0.2123927176, -0.1030678079, -0.0699986815, 0.0642950237, -0.0251826495, -0.0854823589, -0.1096509323, -0.0907092616, -0.2105641663, -0.1021737903, 0.0008561462, -0.2098904550, 0.1004408002, -0.0734445602, -0.0726897717, 0.1675332189, 0.1239057779, 0.0097715557, 0.0667681992, -0.1043640971, 0.1285540164, -0.0009112954, 0.1687436104, 0.1890211105, -0.0713083297, -0.0517095178, -0.0946692005, 0.1738456786, -0.1756263822, 0.1022707820, -0.1381054819, 0.0597068667, 0.1020123959, -0.1869646460, 0.1419177353, -0.1837271750, 0.0649304092, -0.0428975075, 0.0641330183, -0.1485097110, -0.0235622525, 0.0734207630, 0.1333397627, 0.0865913332, 0.0552074015, 0.1373053789, 0.0575802624, -0.0595466942, -0.0077782124, -0.1688821316, 0.0683797002, 0.0604126155, -0.1187862828, 0.1183215976, 0.0236799270, 0.0590337217, 0.0101673752, -0.1912313998, -0.1972816139, -0.0144357085, 0.1284356415, -0.1677064002, -0.1458736658, 0.0945150852, 0.0660020411, -0.2040407658, -0.0652025193, -0.1958839595, -0.0476699769, -0.1194568947, 0.0389118493, 0.1122297049, 0.0849995613, -0.1303817034, 0.1943291426, 0.0884832144, -0.1713939905, 0.1361604333, 0.1700559258, 0.0888699889, 0.1491132975, 0.0110910237, -0.0082112402, -0.2113815248, 0.1223022044, -0.1369983256, -0.0939085633, -0.1901251674, -0.1781198978, -0.1601606905, -0.1569926441, 0.1607081890, -0.0785849988, 0.1184020936, -0.0174237043, 0.1962739825, 0.0148686767, -0.1977183521, 0.0811325610, -0.2109922618, -0.0841675103, -0.0702919215, -0.0306952149, 0.1349979043, 0.1646722853, -0.0834002197, 0.1565574706, 0.0698181689, 0.0968342423, 0.0466661155, 0.1813298166, 0.0681289136, 0.0577867925, -0.1417659670, 0.0790274739, 0.0039386451, 0.0658430755, 0.1567339599, -0.0266019553, -0.0230122209, 0.1224775314, 0.1286482215, -0.0073128492, -0.2068894356, -0.0707175732, 0.1901448369, -0.1007148921, -0.2069893181, -0.2129065543, -0.2112892717, -0.1419645101, -0.0425458103, 0.1253262460, 0.0262898952, 0.1234650314, -0.0945816711, 0.1455450356, -0.1626341790, 0.1400247514, 0.1259462237, 0.0135621727, -0.1350647509, -0.1089950055, -0.0118958801, 0.1709047556, -0.1979926378, -0.0529204160, 0.0565693378, 0.0054066479, -0.2076760978, 0.1579419076, -0.1331384778, 0.1450648904, 0.0945485234, 0.1897557676, -0.1987455487, -0.0204036236, -0.1410997212, 0.1950822473, -0.0571822971, 0.1841697991, -0.0832832009, -0.0292502493, 0.0540054739, -0.0874012262, -0.1223381013, -0.0359581560, 0.1441550851, 0.1913868487, 0.0666281581, 0.1085380316, -0.1803641915, -0.2118480057, -0.0779354274, -0.1355263591, 0.0061643273, 0.0883840919, 0.0734911263, -0.0222379565, -0.1470552981, 0.0930044353, 0.0301488936, -0.1041629091, 0.1124871969, -0.0324787796, 0.1621141732, -0.0302986354, 0.0320253670, -0.0254642069, 0.0735721886, 0.1294092536, 0.1970367730, 0.1374342442, -0.0098119080, -0.1765737236, 0.0717885792, -0.1637127101, 0.0017922521, -0.1634298861, 0.0551188588, 0.1021533012, -0.1480292082, -0.1404761374, 0.0176453292, -0.2029290348, -0.1242469549, -0.1500332206, 0.0987029970, 0.0664662719, -0.1982329637, -0.0825024992, 0.0352124721, 0.1985097826, 0.0569595098, 0.0618391335, 0.1393162012, -0.0402746350, -0.0187438279, 0.0287175924, -0.0901775211, -0.1571455002, 0.0820456743, -0.1526470482, -0.0679484606, -0.1871128678, -0.1030577943, 0.1164523661, -0.1777411997, 0.2028335333, 0.1062799096, -0.1306673586, 0.0193794817, -0.1056451425, -0.0782839805, -0.1838641018, -0.1612155437, 0.1994944513, -0.1032967493, -0.0007423908, -0.1928774118, -0.1026488543, 0.0221969932, 0.0957674682, -0.1590662003, -0.1756756902, -0.1925190091, 0.1713214517, -0.1357954144, -0.0678046048, 0.1436020434, 0.1913373470, -0.0668297112, 0.1408542097, 0.0131400675, -0.0122715235, 0.0858298540, 0.0434364676, 0.0581994653, -0.0372000188, 0.0917010307, -0.1772421449, 0.2118621469, 0.2043992281, 0.0180346370, -0.1003166810, -0.1554493606, 0.1346953809, -0.0091408342, 0.0495243967, 0.1684330404, 0.0888979435, 0.1670624614, -0.1518383324, 0.0951341093, 0.0481031239, -0.0930296481, 0.2053811252, 0.0390005410, 0.1204590797, -0.1965785623, -0.2108087689, 0.0492499173, -0.1559493393, 0.0439987779, 0.0180086643, -0.0299904495, -0.0337069035, 0.0596897304, -0.0415356904, 0.1043559611, 0.0512758791, -0.1627185047, 0.0060975403, 0.0107195526, 0.0437085629, 0.2009048462, -0.1879913360, -0.1152206361, 0.0925723314, 0.1455665529, -0.0639835298, -0.0555260181, 0.1588294208, -0.0340011120, -0.1726251692, -0.1559307873, 0.1641682684, -0.1031779572, -0.0363223106, -0.2074585408, -0.1596251428, 0.0819325745, 0.1213523746, 0.0321856886, 0.0748675764, 0.2040767074, -0.0269059688, -0.0252219886, 0.1771601140, 0.0397257209, 0.0009780973, 0.0286276191, -0.2082468867, 0.1639084220, -0.0625818223, -0.1664599180, -0.0204231888, 0.1186442077, 0.0199112147, -0.1199412122, 0.1855714321, -0.1853042543, 0.0248175263, 0.1296752989, -0.1034716070, 0.1024605334, -0.1043592170, -0.1110985950, 0.1371198595, 0.2005972564, 0.1089456379, 0.0813475251, 0.1458572149, -0.1875934303, -0.0878109336, -0.1656404734, -0.0481218696, -0.0147879571, -0.0365189314, -0.1881186664, -0.0101490766, -0.1450003982, 0.0966188908, 0.0816202760, 0.0858395994, -0.0378078520, -0.1166864485, -0.2124664634, -0.1445667446, -0.1350740641, 0.0993289948, 0.0006026477, -0.0420859903, 0.1917885542, -0.1255790293, -0.0350225717, -0.2000366598, 0.1605901718, -0.1603719890, -0.0448665023, -0.0817638189, -0.1180410981, 0.1242516339, -0.2098187208, -0.1168854013, -0.1516601741, 0.2077189088, -0.2060550451, -0.0837537944, 0.1635324657, -0.1471616328, 0.0553687513, 0.1319250762, -0.1697462499, 0.0211914480, 0.2054221630, 0.0742321312, -0.0818149596, 0.1701242328, 0.0754314959, -0.1620253772, 0.0616166890, 0.0198826492, 0.0850143135, -0.0293497741, 0.0385374427, -0.1875057369, -0.1260208488, -0.0509605855, -0.2069230825, -0.1423363388, 0.0270057023, -0.0100039542, 0.0066857487, 0.0064863414, -0.1084620431, 0.0748348832, 0.1903536022, -0.0189216882, 0.0647348762, -0.1130325645, -0.0280791521, 0.1684472561, -0.0679326504, 0.0550275743, -0.2121178657, -0.1230209097, -0.2067865580, -0.1724447161, -0.0941479802, -0.2128460258, 0.1200295091, 0.1585270762, 0.0048917681, -0.1262075007, 0.2128604949, 0.1981873214, -0.0792624801, 0.0499543250, -0.1759408712, 0.0397666395, -0.1297239959, 0.0539006889, 0.0158702582, 0.0525951087, 0.0104503036, -0.1166705415, -0.1007425413, -0.0335223973, -0.0363929272, -0.0247373134, -0.0816320181, 0.0663042665, 0.0471885502, -0.1701354086, 0.0133253038, -0.0290323794, -0.0628939718, 0.1963127851, 0.1712224483, 0.1359584332, 0.0572720766, 0.0033609420, -0.1027953550, -0.0740710050, 0.1231857538, 0.0393924117, 0.0514275730, 0.1134273708, 0.1358176172, -0.0179544836, -0.0428474993, -0.0171023011, -0.2041860372, -0.1511560827, 0.0329139382, -0.0457010418, 0.1883136630, 0.1534592807, -0.0542723686, -0.1335345954, 0.1261513531, 0.0454059839, -0.1233780980, 0.1302312016, 0.1201035678, 0.1464537084, 0.0493889451, -0.1329772770, 0.1709606051, -0.1870940626, -0.1035034806, -0.0046339035, 0.0043433607, 0.1246011853, 0.0860475600, 0.0112697929, 0.0109259784, -0.1088009328, 0.0451144576, 0.0881381333, 0.0288242400, 0.0178651661, 0.2085936964, 0.1395792663, 0.0561457574, -0.1421446502, 0.1660542786, -0.0913557336, -0.1580511034, -0.0692827702, 0.1781054735, -0.1359718442, 0.1693622172, 0.1706989706, -0.1860644817, 0.0008527339, 0.1799221635, -0.0847420543, -0.1547217220, -0.0242664218, 0.0821223855, -0.0366279185, 0.1579120159, 0.0282838047, 0.0498765707, -0.1640301049, -0.1360980570, 0.0567750931, -0.0627196282, 0.0094111115, -0.0854918212, -0.0437347442, 0.1329703629, -0.0725088567, 0.1103307307, -0.0504474938, 0.0505414307, 0.1265490353, -0.2080813795, 0.1661646962, 0.0103915930, 0.0793212950, -0.0289316922, -0.0177615285, 0.0827395320, 0.0938742459, 0.0911233425, -0.1122500226, 0.0554215610, -0.1822759956, 0.1217783391, 0.1194887161, 0.1549885869, -0.1796352714, 0.0217099786, 0.1249144673, 0.1293254197, -0.2064816654, -0.0156392753, 0.1515989304, -0.0573394150, -0.0397448242, -0.0883652940, 0.0087602139, -0.1320590675, -0.0012755543, 0.0074295104, 0.0264889598, -0.1099150479, 0.0306335688, 0.1872678101, -0.1059957743, -0.1681141704, 0.0320923179, -0.0743228644, -0.0371268243, 0.0887113512, 0.2068048120, -0.1959859282, -0.1684667319, 0.2029729187, -0.1361901611, -0.0789012164, -0.1442584097, -0.1696847975, 0.0996335745, 0.1952257156, 0.0415257215, -0.2088347971, 0.1613855064, 0.0910006762, -0.2028978318, -0.1083787307, -0.0743597150, -0.1370799541, -0.1911847442, -0.1457047611, -0.0623703152, -0.1246905029, -0.0984734967, 0.1318724751, 0.1303057075, -0.1093793437, -0.0508935899, -0.0765071809, -0.0111884177, -0.1807311922, -0.0703602433, -0.1799080819, -0.1261800528, -0.0470359623, 0.1881902814, 0.0471602082, 0.0792753398, 0.2045003772, 0.1398940086, -0.1819617003, 0.1283333600, -0.0361667722, -0.0006352365, 0.1356659532, -0.2093663812, 0.0505688190, -0.0889607742, 0.1192332506, -0.0245460868, 0.0301766992, 0.0701677799, 0.0392634571, 0.0366925746, 0.1453541815, -0.1476673931, -0.0009120107, -0.0534066707, -0.1067317575, -0.2066733539, -0.0566889346, 0.0450963676, 0.0414687097, 0.1335349977, -0.1520926356, -0.1424853206, -0.0996622816, 0.1847671568, -0.0335486233, -0.0234564245, -0.1365759075, 0.0068013966, 0.0895885527, -0.1611822844, 0.1875145733, 0.1700508296, 0.1791161299, 0.0502313972, 0.1339436173, -0.1496843696, -0.0048265010, -0.0859003514, 0.1516091824, -0.0743022263, 0.1891787946, -0.0211467147, -0.1220617816, 0.1598131657, -0.1144109517, 0.0861026943, -0.0619688481, 0.0408543050, -0.1235215962, -0.0368760228, 0.0546551347, 0.0205015689, 0.0478628278, -0.0267687291, 0.2078846097, -0.1167297587, 0.0474349558, -0.0933977664, -0.0598359853, 0.0006468296, -0.1521905959, 0.1903777421, 0.1955339909, -0.1681201756, -0.0718923360, 0.1000526547, 0.1975592673, -0.0782697946, -0.0607591271, -0.0573827773, -0.1979690492, 0.1500097513, -0.0116083771, -0.0183549225, -0.1110346541, -0.1526011080, -0.0931197703, 0.0978282094, 0.1528442800, -0.1779505312, 0.0492412746, 0.0135434717, -0.1821183711, -0.0539662242, 0.0648232102, -0.1835660934, 0.0774909556, -0.1061648875, -0.0018143058, -0.1021513268, -0.0782599300, 0.1797921360, -0.1122998893, -0.0137408972, 0.0591432452, -0.0047023296, 0.0441930890, 0.1600920558, 0.0812759399, 0.0577342212, 0.0126988590, -0.0504227877, -0.0159302801, -0.1607423425, 0.1282382011, -0.0441544652, -0.0640320778, -0.1724980921, -0.1329568923, 0.0787885785, -0.1252467930, -0.1387143284, -0.0785312206, 0.0326679200, 0.0394001901, 0.0371861458, 0.2077334225, 0.1461085975, 0.1211211979, 0.0385516584, 0.0018767864, 0.0775760412, -0.0718859732, -0.1748803854, -0.2082360983, -0.0951147377, -0.0277354270, 0.1811922789, -0.2120816261, 0.1423982084, 0.0527060628, 0.0443730950, 0.1091656983, -0.1891245544, 0.1849547327, -0.0563776344, -0.1372431815, -0.1792159081, 0.0771172941, -0.1128707677, 0.1613407731, -0.0392446369, -0.1591635942, 0.0720368326, -0.0328554362, -0.1781554818, -0.0167741776, 0.0256045461, -0.1106735989, -0.1167926863, -0.1380546987, 0.0477854609, -0.1729764640, 0.1947746873, 0.0698388219, -0.1423616111, -0.0137424171, 0.2067546248, -0.1112923175, 0.0375417471 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w4.h b/model/AE_model/hls4ml_prj/firmware/weights/w4.h deleted file mode 100644 index 3a792a7..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w4.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [32, 16] -//Min -0.352499961853 -//Max 0.353389114141 -//Number of zeros 0 - -#ifndef W4_H_ -#define W4_H_ - -#ifndef __SYNTHESIS__ -model_default_t w4[512]; -#else -model_default_t w4[512] = {0.2522660792, 0.0472463667, 0.1366372108, 0.2024352849, -0.2969901264, 0.3026663959, 0.0501541495, -0.1666901112, 0.2365196049, -0.0680378973, 0.0250868201, -0.0102412701, 0.1578937471, 0.2143684924, 0.1382856667, -0.2827171683, -0.2178026885, -0.1142235249, 0.1740548313, 0.0864422619, -0.0083185136, -0.2549129725, -0.2811457813, 0.1996429861, 0.2537213266, 0.0755288303, -0.2856190801, 0.2722628415, -0.2152007967, 0.2796703875, -0.0390861332, 0.2643250525, 0.2879633605, 0.1524617374, -0.2781186104, -0.2174984664, 0.1841109097, -0.1897617131, 0.0214126110, 0.2756588161, -0.1361463666, 0.1854020655, 0.0136580169, -0.1739453524, -0.2037086934, 0.2331032455, 0.1544366777, -0.0310810208, -0.0868646502, -0.2883892059, -0.2525816858, 0.1857602298, 0.0431617498, 0.2765824497, -0.3404836357, 0.0003150105, 0.1946421564, -0.1096425802, -0.3405165970, -0.1051194668, 0.2566929162, -0.2409150898, 0.1303486526, 0.0781851113, 0.3473711908, 0.2372477949, 0.2216028273, 0.2779108584, -0.2513145804, 0.2903170288, 0.3386500180, -0.1601095498, -0.3490774035, 0.2755789459, 0.1389393508, -0.1227984726, -0.0264718533, -0.2903637886, -0.0323203206, 0.2590620816, -0.2555358410, 0.2278597653, -0.3334189057, 0.2058431208, -0.1453105360, -0.1349785626, -0.1803222597, -0.2586718798, -0.0149415731, 0.2688183486, 0.0923562944, -0.2271783352, 0.0151425898, -0.0040425658, -0.0834903717, 0.2663768232, 0.1177851856, -0.1448882222, 0.1516865790, -0.0677892566, -0.2597764134, -0.1776642203, 0.0130518675, 0.3164511025, 0.2171913683, -0.1280924529, 0.0447063446, 0.0007674992, 0.1074218750, -0.1904782057, 0.2392567694, 0.2407195866, 0.1239655912, 0.1567451656, -0.2986667156, -0.3082947433, 0.1370418370, 0.2036338151, 0.1176812351, 0.0793665648, -0.2416863739, 0.0658439100, -0.0042414963, 0.2246252596, -0.1606845260, -0.1458802670, -0.0203119218, -0.2208561450, -0.0018605292, -0.3000907004, 0.0556296110, -0.0187504590, 0.0039853156, 0.1782450974, 0.3197682202, 0.1932768524, -0.3468171358, 0.2785635889, -0.1033156514, 0.2557075322, 0.0357322693, -0.2575861216, 0.2878656089, 0.1693320572, 0.2661882937, -0.1037750691, 0.3428892195, -0.0092120469, 0.2229680121, -0.1772950143, 0.1566817462, -0.0867876112, -0.2931596637, 0.2108038366, 0.1972967088, 0.0510829985, 0.0109108090, -0.2986655533, 0.3506550491, -0.2754515707, 0.0859443247, 0.1196147799, -0.1255364120, 0.0313510895, -0.0342764258, 0.2372231185, 0.0517332256, -0.0320222378, -0.1739752740, 0.0907683074, 0.2277970612, 0.0720131099, -0.0111514628, -0.2736310661, -0.2916364670, -0.1986997128, -0.0493109822, -0.1552847475, 0.0752177238, -0.0267810225, 0.0310347378, 0.2626370490, -0.0739502609, 0.3480634987, 0.1504200995, -0.1583263129, -0.2957593501, 0.0977295935, 0.3265363872, 0.1874836981, -0.3121306300, 0.0761997402, 0.1020076871, -0.0558571219, 0.1340036392, 0.0658659935, 0.0709926486, 0.2931231558, -0.2477214634, -0.0701777041, -0.0623439550, 0.0492672920, -0.1126132607, -0.0644860268, 0.3442813456, -0.2212160826, 0.1822416484, 0.1112949848, 0.1972921193, 0.1835783422, 0.3243238032, 0.0618469715, 0.3063533604, -0.1380225867, -0.3301715851, 0.3108427227, 0.1856992543, 0.2242860496, -0.2146092206, -0.3459119201, 0.3325545490, 0.1590670645, 0.0243660212, 0.2870775163, 0.3194306791, -0.1597813070, 0.2897755206, -0.3396409750, -0.2740365267, -0.1033969223, -0.3348458409, 0.0241163373, 0.1685589850, 0.2897036970, 0.2423589528, 0.1232318282, 0.0188603699, -0.2729655802, -0.2506482303, 0.3415875733, 0.1460860372, 0.1749170721, 0.3239216506, 0.0686807334, 0.3138040006, 0.1273040473, 0.1480102837, -0.2858326733, -0.3041563630, 0.1362886727, -0.1188396066, 0.1265843511, -0.0437925160, -0.0460978746, 0.0250332057, 0.0310298502, 0.1010590494, -0.1512655467, -0.1869540662, 0.2947747409, 0.1565559804, -0.0110582411, 0.2990426719, 0.0243928134, -0.2788370550, -0.0378508270, -0.1655397564, -0.1651211530, 0.0375331938, -0.0802819133, 0.2527566850, 0.1229048371, -0.3034744859, 0.3424619138, -0.0362816155, 0.3064639866, -0.3251633644, -0.0561561286, -0.1386810839, -0.1873771250, 0.0740217566, 0.2217447460, 0.0608623326, 0.3106425703, -0.0348601639, 0.0098693669, -0.0500967503, -0.2298890650, 0.2280974686, -0.1228047013, -0.0474307835, 0.1570421159, -0.2000223696, 0.3173082769, -0.0201079249, -0.0429591835, -0.1831246763, -0.3160712719, -0.3423962593, 0.2645605505, -0.1021868885, 0.2297706306, -0.2341932654, -0.0551784039, -0.1758562922, 0.0193399191, -0.2074202299, -0.2002149820, 0.2020036280, 0.2011649907, -0.1258551180, -0.1963172406, -0.0541504323, -0.2374510467, -0.1404965967, 0.1057842970, -0.2965692282, -0.0469761193, -0.2354142517, 0.3440479934, -0.3496401310, -0.1808980703, -0.0749126375, -0.2124531567, -0.2248300910, -0.2251703739, 0.2554413378, -0.2482712269, -0.1724860519, 0.0195343196, -0.0451986194, 0.2286693156, 0.3279499114, 0.1889200509, 0.1138151884, 0.0180296600, 0.3073146641, 0.1673120558, 0.1094814837, 0.0772020817, 0.1157795787, -0.2533926666, 0.3259659111, -0.3439531624, -0.2726703882, 0.1366222203, -0.2442966104, -0.0172941983, -0.1452773958, 0.3104448020, 0.0460897684, 0.3134374321, -0.3222556412, 0.1772699058, -0.0520446002, 0.3183539212, -0.1666575670, -0.3412561119, 0.0105834901, 0.1279655099, 0.2878932059, 0.0738310814, 0.2275222838, -0.2160684317, -0.2329547405, 0.3475213349, -0.1518996060, -0.0212351084, 0.0370311439, 0.1768586338, 0.2853400409, 0.0003355742, 0.3533891141, 0.0291419327, -0.0319198370, -0.2350160480, -0.2694121003, 0.3449537456, 0.1738234460, 0.1465523541, -0.0850296617, 0.2064615786, -0.1789806336, 0.1943366826, 0.2031005323, -0.3257991672, 0.1745655239, 0.2438239157, -0.0586784482, -0.2174407244, -0.3220714629, -0.2972910404, -0.0591732562, -0.1358150095, -0.0827436149, 0.1265739799, -0.1989234239, -0.0939453244, -0.0588552058, 0.0682870746, -0.3098084033, -0.0157452226, -0.0021830499, 0.3469319642, -0.2003855854, -0.2258851081, 0.3224907219, 0.1821571887, 0.1104185879, 0.0827558339, -0.1566830128, 0.0639002621, -0.3315552473, 0.2171516120, 0.2829327285, 0.1397499144, -0.2708459198, 0.1771211922, -0.1542973369, 0.0393754542, -0.1321950257, -0.0920447409, -0.3313350081, 0.1874585450, -0.2397718132, 0.0502000153, -0.3381247818, 0.0151134431, -0.3485126197, -0.2904728651, 0.0406396687, -0.0385329127, -0.0673590899, -0.1004101336, 0.0190165639, -0.2463100553, 0.1502141654, 0.0003126562, -0.2063763440, -0.2296684682, -0.3240451813, 0.2523455918, 0.2038686574, -0.1221953481, -0.1350431293, 0.1033753455, -0.0860537589, 0.0074554384, -0.2160798907, -0.0049291551, -0.2326308787, 0.1721382439, -0.2278418094, -0.3524999619, 0.3021522462, 0.1995970309, -0.1933335811, 0.2864403427, -0.1117373556, 0.0926416516, 0.0749163628, -0.2053885907, 0.2132308781, -0.2657345235, 0.1126402318, 0.2304289639, 0.0244826078, 0.1861351430, -0.2552723289, -0.0431680679, -0.1194522530, 0.1484715641, -0.0338370800, 0.2611546814, -0.3070992231, -0.1069100350, 0.0886633992, -0.1055363864, -0.2920034826, 0.3076080382, 0.0623235703, -0.1591702700, 0.2652751505, 0.2327668369, 0.0326506495, -0.3495071232, -0.2017550170, -0.3147802353, -0.0597256124, 0.0144264400, -0.3209062815, 0.0751461387, -0.1128112674, -0.1978781819, 0.2890134156, -0.2863400280, -0.0341001749, -0.3328914940, 0.2770535648, 0.2997204959, -0.1577824503, 0.0649192929, 0.1549009383, -0.2546662688, 0.0934955180, 0.2874326408, 0.0660888851, 0.2617536485, 0.2178303301, 0.0496521890, -0.0221074522, 0.0447048247}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w4.txt b/model/AE_model/hls4ml_prj/firmware/weights/w4.txt deleted file mode 100644 index 9a589b6..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w4.txt +++ /dev/null @@ -1 +0,0 @@ -0.2522660792, 0.0472463667, 0.1366372108, 0.2024352849, -0.2969901264, 0.3026663959, 0.0501541495, -0.1666901112, 0.2365196049, -0.0680378973, 0.0250868201, -0.0102412701, 0.1578937471, 0.2143684924, 0.1382856667, -0.2827171683, -0.2178026885, -0.1142235249, 0.1740548313, 0.0864422619, -0.0083185136, -0.2549129725, -0.2811457813, 0.1996429861, 0.2537213266, 0.0755288303, -0.2856190801, 0.2722628415, -0.2152007967, 0.2796703875, -0.0390861332, 0.2643250525, 0.2879633605, 0.1524617374, -0.2781186104, -0.2174984664, 0.1841109097, -0.1897617131, 0.0214126110, 0.2756588161, -0.1361463666, 0.1854020655, 0.0136580169, -0.1739453524, -0.2037086934, 0.2331032455, 0.1544366777, -0.0310810208, -0.0868646502, -0.2883892059, -0.2525816858, 0.1857602298, 0.0431617498, 0.2765824497, -0.3404836357, 0.0003150105, 0.1946421564, -0.1096425802, -0.3405165970, -0.1051194668, 0.2566929162, -0.2409150898, 0.1303486526, 0.0781851113, 0.3473711908, 0.2372477949, 0.2216028273, 0.2779108584, -0.2513145804, 0.2903170288, 0.3386500180, -0.1601095498, -0.3490774035, 0.2755789459, 0.1389393508, -0.1227984726, -0.0264718533, -0.2903637886, -0.0323203206, 0.2590620816, -0.2555358410, 0.2278597653, -0.3334189057, 0.2058431208, -0.1453105360, -0.1349785626, -0.1803222597, -0.2586718798, -0.0149415731, 0.2688183486, 0.0923562944, -0.2271783352, 0.0151425898, -0.0040425658, -0.0834903717, 0.2663768232, 0.1177851856, -0.1448882222, 0.1516865790, -0.0677892566, -0.2597764134, -0.1776642203, 0.0130518675, 0.3164511025, 0.2171913683, -0.1280924529, 0.0447063446, 0.0007674992, 0.1074218750, -0.1904782057, 0.2392567694, 0.2407195866, 0.1239655912, 0.1567451656, -0.2986667156, -0.3082947433, 0.1370418370, 0.2036338151, 0.1176812351, 0.0793665648, -0.2416863739, 0.0658439100, -0.0042414963, 0.2246252596, -0.1606845260, -0.1458802670, -0.0203119218, -0.2208561450, -0.0018605292, -0.3000907004, 0.0556296110, -0.0187504590, 0.0039853156, 0.1782450974, 0.3197682202, 0.1932768524, -0.3468171358, 0.2785635889, -0.1033156514, 0.2557075322, 0.0357322693, -0.2575861216, 0.2878656089, 0.1693320572, 0.2661882937, -0.1037750691, 0.3428892195, -0.0092120469, 0.2229680121, -0.1772950143, 0.1566817462, -0.0867876112, -0.2931596637, 0.2108038366, 0.1972967088, 0.0510829985, 0.0109108090, -0.2986655533, 0.3506550491, -0.2754515707, 0.0859443247, 0.1196147799, -0.1255364120, 0.0313510895, -0.0342764258, 0.2372231185, 0.0517332256, -0.0320222378, -0.1739752740, 0.0907683074, 0.2277970612, 0.0720131099, -0.0111514628, -0.2736310661, -0.2916364670, -0.1986997128, -0.0493109822, -0.1552847475, 0.0752177238, -0.0267810225, 0.0310347378, 0.2626370490, -0.0739502609, 0.3480634987, 0.1504200995, -0.1583263129, -0.2957593501, 0.0977295935, 0.3265363872, 0.1874836981, -0.3121306300, 0.0761997402, 0.1020076871, -0.0558571219, 0.1340036392, 0.0658659935, 0.0709926486, 0.2931231558, -0.2477214634, -0.0701777041, -0.0623439550, 0.0492672920, -0.1126132607, -0.0644860268, 0.3442813456, -0.2212160826, 0.1822416484, 0.1112949848, 0.1972921193, 0.1835783422, 0.3243238032, 0.0618469715, 0.3063533604, -0.1380225867, -0.3301715851, 0.3108427227, 0.1856992543, 0.2242860496, -0.2146092206, -0.3459119201, 0.3325545490, 0.1590670645, 0.0243660212, 0.2870775163, 0.3194306791, -0.1597813070, 0.2897755206, -0.3396409750, -0.2740365267, -0.1033969223, -0.3348458409, 0.0241163373, 0.1685589850, 0.2897036970, 0.2423589528, 0.1232318282, 0.0188603699, -0.2729655802, -0.2506482303, 0.3415875733, 0.1460860372, 0.1749170721, 0.3239216506, 0.0686807334, 0.3138040006, 0.1273040473, 0.1480102837, -0.2858326733, -0.3041563630, 0.1362886727, -0.1188396066, 0.1265843511, -0.0437925160, -0.0460978746, 0.0250332057, 0.0310298502, 0.1010590494, -0.1512655467, -0.1869540662, 0.2947747409, 0.1565559804, -0.0110582411, 0.2990426719, 0.0243928134, -0.2788370550, -0.0378508270, -0.1655397564, -0.1651211530, 0.0375331938, -0.0802819133, 0.2527566850, 0.1229048371, -0.3034744859, 0.3424619138, -0.0362816155, 0.3064639866, -0.3251633644, -0.0561561286, -0.1386810839, -0.1873771250, 0.0740217566, 0.2217447460, 0.0608623326, 0.3106425703, -0.0348601639, 0.0098693669, -0.0500967503, -0.2298890650, 0.2280974686, -0.1228047013, -0.0474307835, 0.1570421159, -0.2000223696, 0.3173082769, -0.0201079249, -0.0429591835, -0.1831246763, -0.3160712719, -0.3423962593, 0.2645605505, -0.1021868885, 0.2297706306, -0.2341932654, -0.0551784039, -0.1758562922, 0.0193399191, -0.2074202299, -0.2002149820, 0.2020036280, 0.2011649907, -0.1258551180, -0.1963172406, -0.0541504323, -0.2374510467, -0.1404965967, 0.1057842970, -0.2965692282, -0.0469761193, -0.2354142517, 0.3440479934, -0.3496401310, -0.1808980703, -0.0749126375, -0.2124531567, -0.2248300910, -0.2251703739, 0.2554413378, -0.2482712269, -0.1724860519, 0.0195343196, -0.0451986194, 0.2286693156, 0.3279499114, 0.1889200509, 0.1138151884, 0.0180296600, 0.3073146641, 0.1673120558, 0.1094814837, 0.0772020817, 0.1157795787, -0.2533926666, 0.3259659111, -0.3439531624, -0.2726703882, 0.1366222203, -0.2442966104, -0.0172941983, -0.1452773958, 0.3104448020, 0.0460897684, 0.3134374321, -0.3222556412, 0.1772699058, -0.0520446002, 0.3183539212, -0.1666575670, -0.3412561119, 0.0105834901, 0.1279655099, 0.2878932059, 0.0738310814, 0.2275222838, -0.2160684317, -0.2329547405, 0.3475213349, -0.1518996060, -0.0212351084, 0.0370311439, 0.1768586338, 0.2853400409, 0.0003355742, 0.3533891141, 0.0291419327, -0.0319198370, -0.2350160480, -0.2694121003, 0.3449537456, 0.1738234460, 0.1465523541, -0.0850296617, 0.2064615786, -0.1789806336, 0.1943366826, 0.2031005323, -0.3257991672, 0.1745655239, 0.2438239157, -0.0586784482, -0.2174407244, -0.3220714629, -0.2972910404, -0.0591732562, -0.1358150095, -0.0827436149, 0.1265739799, -0.1989234239, -0.0939453244, -0.0588552058, 0.0682870746, -0.3098084033, -0.0157452226, -0.0021830499, 0.3469319642, -0.2003855854, -0.2258851081, 0.3224907219, 0.1821571887, 0.1104185879, 0.0827558339, -0.1566830128, 0.0639002621, -0.3315552473, 0.2171516120, 0.2829327285, 0.1397499144, -0.2708459198, 0.1771211922, -0.1542973369, 0.0393754542, -0.1321950257, -0.0920447409, -0.3313350081, 0.1874585450, -0.2397718132, 0.0502000153, -0.3381247818, 0.0151134431, -0.3485126197, -0.2904728651, 0.0406396687, -0.0385329127, -0.0673590899, -0.1004101336, 0.0190165639, -0.2463100553, 0.1502141654, 0.0003126562, -0.2063763440, -0.2296684682, -0.3240451813, 0.2523455918, 0.2038686574, -0.1221953481, -0.1350431293, 0.1033753455, -0.0860537589, 0.0074554384, -0.2160798907, -0.0049291551, -0.2326308787, 0.1721382439, -0.2278418094, -0.3524999619, 0.3021522462, 0.1995970309, -0.1933335811, 0.2864403427, -0.1117373556, 0.0926416516, 0.0749163628, -0.2053885907, 0.2132308781, -0.2657345235, 0.1126402318, 0.2304289639, 0.0244826078, 0.1861351430, -0.2552723289, -0.0431680679, -0.1194522530, 0.1484715641, -0.0338370800, 0.2611546814, -0.3070992231, -0.1069100350, 0.0886633992, -0.1055363864, -0.2920034826, 0.3076080382, 0.0623235703, -0.1591702700, 0.2652751505, 0.2327668369, 0.0326506495, -0.3495071232, -0.2017550170, -0.3147802353, -0.0597256124, 0.0144264400, -0.3209062815, 0.0751461387, -0.1128112674, -0.1978781819, 0.2890134156, -0.2863400280, -0.0341001749, -0.3328914940, 0.2770535648, 0.2997204959, -0.1577824503, 0.0649192929, 0.1549009383, -0.2546662688, 0.0934955180, 0.2874326408, 0.0660888851, 0.2617536485, 0.2178303301, 0.0496521890, -0.0221074522, 0.0447048247 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w6.h b/model/AE_model/hls4ml_prj/firmware/weights/w6.h deleted file mode 100644 index ec7d943..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w6.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [16, 2] -//Min -0.557236135006 -//Max 0.508355736732 -//Number of zeros 0 - -#ifndef W6_H_ -#define W6_H_ - -#ifndef __SYNTHESIS__ -model_default_t w6[32]; -#else -model_default_t w6[32] = {-0.4038675725, 0.2404698730, -0.1218281686, -0.0074202418, -0.1704593301, -0.2667911053, 0.5009108782, 0.3440188169, 0.4337642193, -0.5572361350, 0.0451787114, 0.4587002993, -0.4319011569, -0.4903026223, -0.1909177005, 0.5083557367, -0.0084991455, -0.1081170440, -0.3155334592, -0.2123660743, -0.1109238863, 0.2597898841, -0.2424691319, -0.0677482486, -0.3102618456, -0.1593949497, 0.2158386111, -0.1289134920, 0.2065508962, -0.0858883262, 0.2135418653, 0.0607247353}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w6.txt b/model/AE_model/hls4ml_prj/firmware/weights/w6.txt deleted file mode 100644 index 93a8bbd..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w6.txt +++ /dev/null @@ -1 +0,0 @@ --0.4038675725, 0.2404698730, -0.1218281686, -0.0074202418, -0.1704593301, -0.2667911053, 0.5009108782, 0.3440188169, 0.4337642193, -0.5572361350, 0.0451787114, 0.4587002993, -0.4319011569, -0.4903026223, -0.1909177005, 0.5083557367, -0.0084991455, -0.1081170440, -0.3155334592, -0.2123660743, -0.1109238863, 0.2597898841, -0.2424691319, -0.0677482486, -0.3102618456, -0.1593949497, 0.2158386111, -0.1289134920, 0.2065508962, -0.0858883262, 0.2135418653, 0.0607247353 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w8.h b/model/AE_model/hls4ml_prj/firmware/weights/w8.h deleted file mode 100644 index fd43b50..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w8.h +++ /dev/null @@ -1,15 +0,0 @@ -//Numpy array shape [2, 16] -//Min -0.574827373028 -//Max 0.545287370682 -//Number of zeros 0 - -#ifndef W8_H_ -#define W8_H_ - -#ifndef __SYNTHESIS__ -model_default_t w8[32]; -#else -model_default_t w8[32] = {0.3605225086, -0.5578687787, -0.5385512710, 0.4892086983, -0.1193599701, -0.0803663135, 0.4994674921, -0.2543119192, 0.2277546525, -0.5748273730, 0.0225696564, -0.2307680845, -0.4053993523, -0.5072304010, 0.4933290482, -0.2219669521, 0.4366440773, 0.0725066066, -0.0992689729, 0.2645081282, 0.3069063425, -0.4200416803, -0.3117905855, 0.4161803126, 0.5297801495, 0.0625678897, 0.2084921598, -0.1386280656, 0.1418884993, -0.2884309292, 0.5452873707, 0.1661161780}; -#endif - -#endif diff --git a/model/AE_model/hls4ml_prj/firmware/weights/w8.txt b/model/AE_model/hls4ml_prj/firmware/weights/w8.txt deleted file mode 100644 index 1f85106..0000000 --- a/model/AE_model/hls4ml_prj/firmware/weights/w8.txt +++ /dev/null @@ -1 +0,0 @@ -0.3605225086, -0.5578687787, -0.5385512710, 0.4892086983, -0.1193599701, -0.0803663135, 0.4994674921, -0.2543119192, 0.2277546525, -0.5748273730, 0.0225696564, -0.2307680845, -0.4053993523, -0.5072304010, 0.4933290482, -0.2219669521, 0.4366440773, 0.0725066066, -0.0992689729, 0.2645081282, 0.3069063425, -0.4200416803, -0.3117905855, 0.4161803126, 0.5297801495, 0.0625678897, 0.2084921598, -0.1386280656, 0.1418884993, -0.2884309292, 0.5452873707, 0.1661161780 \ No newline at end of file diff --git a/model/AE_model/hls4ml_prj/hls4ml_config.yml b/model/AE_model/hls4ml_prj/hls4ml_config.yml deleted file mode 100644 index e52d990..0000000 --- a/model/AE_model/hls4ml_prj/hls4ml_config.yml +++ /dev/null @@ -1,16 +0,0 @@ -Backend: Vivado -Board: null -ClockPeriod: 5 -HLSConfig: - Model: - Precision: ap_fixed<16,6> - ReuseFactor: 1 - Strategy: Latency -IOType: io_parallel -InputData: null -KerasModel: !keras_model 'model/AE_model/hls4ml_prj/keras_model.h5' -OutputDir: model/AE_model/hls4ml_prj -OutputPredictions: null -ProjectName: myproject -Stamp: fEe86a0b -XilinxPart: xcu250-figd2104-2L-e diff --git a/model/AE_model/hls4ml_prj/keras_model.h5 b/model/AE_model/hls4ml_prj/keras_model.h5 deleted file mode 100644 index 49f7d6a..0000000 Binary files a/model/AE_model/hls4ml_prj/keras_model.h5 and /dev/null differ diff --git a/model/AE_model/hls4ml_prj/myproject_bridge.cpp b/model/AE_model/hls4ml_prj/myproject_bridge.cpp deleted file mode 100644 index f801d2d..0000000 --- a/model/AE_model/hls4ml_prj/myproject_bridge.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef MYPROJECT_BRIDGE_H_ -#define MYPROJECT_BRIDGE_H_ - -#include "firmware/myproject.h" -#include "firmware/nnet_utils/nnet_helpers.h" -#include -#include - -//hls-fpga-machine-learning insert bram - - -namespace nnet { - bool trace_enabled = false; - std::map *trace_outputs = NULL; - size_t trace_type_size = sizeof(double); -} - -extern "C" { - -struct trace_data { - const char *name; - void *data; -}; - -void allocate_trace_storage(size_t element_size) { - nnet::trace_enabled = true; - nnet::trace_outputs = new std::map; - nnet::trace_type_size = element_size; -} - -void free_trace_storage() { - for (std::map::iterator i = nnet::trace_outputs->begin(); i != nnet::trace_outputs->end(); i++) { - void *ptr = i->second; - free(ptr); - } - nnet::trace_outputs->clear(); - delete nnet::trace_outputs; - nnet::trace_outputs = NULL; - nnet::trace_enabled = false; -} - -void collect_trace_output(struct trace_data *c_trace_outputs) { - int ii = 0; - for (std::map::iterator i = nnet::trace_outputs->begin(); i != nnet::trace_outputs->end(); i++) { - c_trace_outputs[ii].name = i->first.c_str(); - c_trace_outputs[ii].data = i->second; - ii++; - } -} - -// Wrapper of top level function for Python bridge -void myproject_float( - float encoder_input[N_INPUT_1_1], - float layer13_out[N_LAYER_12], - unsigned short &const_size_in_1, - unsigned short &const_size_out_1 -) { - - input_t encoder_input_ap[N_INPUT_1_1]; - nnet::convert_data(encoder_input, encoder_input_ap); - - result_t layer13_out_ap[N_LAYER_12]; - - myproject(encoder_input_ap,layer13_out_ap,const_size_in_1,const_size_out_1); - - nnet::convert_data(layer13_out_ap, layer13_out); -} - -void myproject_double( - double encoder_input[N_INPUT_1_1], - double layer13_out[N_LAYER_12], - unsigned short &const_size_in_1, - unsigned short &const_size_out_1 -) { - input_t encoder_input_ap[N_INPUT_1_1]; - nnet::convert_data(encoder_input, encoder_input_ap); - - result_t layer13_out_ap[N_LAYER_12]; - - myproject(encoder_input_ap,layer13_out_ap,const_size_in_1,const_size_out_1); - - nnet::convert_data(layer13_out_ap, layer13_out); -} - -} - -#endif diff --git a/model/AE_model/hls4ml_prj/myproject_test.cpp b/model/AE_model/hls4ml_prj/myproject_test.cpp deleted file mode 100644 index 15ec41e..0000000 --- a/model/AE_model/hls4ml_prj/myproject_test.cpp +++ /dev/null @@ -1,130 +0,0 @@ -// -// rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks -// -// Copyright (C) 2017 EJ Kreinar -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -#include -#include -#include -#include -#include -#include -#include -#include - -#include "firmware/myproject.h" -#include "firmware/nnet_utils/nnet_helpers.h" - -//hls-fpga-machine-learning insert bram - -#define CHECKPOINT 5000 - -namespace nnet { - bool trace_enabled = true; - std::map *trace_outputs = NULL; - size_t trace_type_size = sizeof(double); -} - -int main(int argc, char **argv) -{ - //load input data from text file - std::ifstream fin("tb_data/tb_input_features.dat"); - //load predictions from text file - std::ifstream fpr("tb_data/tb_output_predictions.dat"); - -#ifdef RTL_SIM - std::string RESULTS_LOG = "tb_data/rtl_cosim_results.log"; -#else - std::string RESULTS_LOG = "tb_data/csim_results.log"; -#endif - std::ofstream fout(RESULTS_LOG); - - std::string iline; - std::string pline; - int e = 0; - - if (fin.is_open() && fpr.is_open()) { - while ( std::getline(fin,iline) && std::getline (fpr,pline) ) { - if (e % CHECKPOINT == 0) std::cout << "Processing input " << e << std::endl; - char* cstr=const_cast(iline.c_str()); - char* current; - std::vector in; - current=strtok(cstr," "); - while(current!=NULL) { - in.push_back(atof(current)); - current=strtok(NULL," "); - } - cstr=const_cast(pline.c_str()); - std::vector pr; - current=strtok(cstr," "); - while(current!=NULL) { - pr.push_back(atof(current)); - current=strtok(NULL," "); - } - - //hls-fpga-machine-learning insert data - input_t encoder_input[N_INPUT_1_1]; - nnet::copy_data(in, encoder_input); - result_t layer13_out[N_LAYER_12]; - - //hls-fpga-machine-learning insert top-level-function - unsigned short size_in1,size_out1; - myproject(encoder_input,layer13_out,size_in1,size_out1); - - if (e % CHECKPOINT == 0) { - std::cout << "Predictions" << std::endl; - //hls-fpga-machine-learning insert predictions - for(int i = 0; i < N_LAYER_12; i++) { - std::cout << pr[i] << " "; - } - std::cout << std::endl; - std::cout << "Quantized predictions" << std::endl; - //hls-fpga-machine-learning insert quantized - nnet::print_result(layer13_out, std::cout, true); - } - e++; - - //hls-fpga-machine-learning insert tb-output - nnet::print_result(layer13_out, fout); - - } - fin.close(); - fpr.close(); - } else { - std::cout << "INFO: Unable to open input/predictions file, using default input." << std::endl; - - //hls-fpga-machine-learning insert zero - input_t encoder_input[N_INPUT_1_1]; - nnet::fill_zero(encoder_input); - result_t layer13_out[N_LAYER_12]; - - //hls-fpga-machine-learning insert top-level-function - unsigned short size_in1,size_out1; - myproject(encoder_input,layer13_out,size_in1,size_out1); - - //hls-fpga-machine-learning insert output - nnet::print_result(layer13_out, std::cout, true); - - //hls-fpga-machine-learning insert tb-output - nnet::print_result(layer13_out, fout); - - } - - fout.close(); - std::cout << "INFO: Saved inference results to file: " << RESULTS_LOG << std::endl; - - return 0; -} diff --git a/model/AE_model/hls4ml_prj/vivado_synth.tcl b/model/AE_model/hls4ml_prj/vivado_synth.tcl deleted file mode 100644 index 920c9a4..0000000 --- a/model/AE_model/hls4ml_prj/vivado_synth.tcl +++ /dev/null @@ -1,3 +0,0 @@ -add_files myproject_prj/solution1/syn/vhdl -synth_design -top myproject -part xcu250-figd2104-2L-e -report_utilization -file vivado_synth.rpt \ No newline at end of file diff --git a/part3_compression.ipynb b/part3_compression.ipynb new file mode 100644 index 0000000..a0e34c4 --- /dev/null +++ b/part3_compression.ipynb @@ -0,0 +1,307 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Part 3: Compression" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from tensorflow.keras.utils import to_categorical\n", + "from sklearn.datasets import fetch_openml\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.preprocessing import LabelEncoder, StandardScaler\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "%matplotlib inline\n", + "seed = 0\n", + "np.random.seed(seed)\n", + "import tensorflow as tf\n", + "tf.random.set_seed(seed)\n", + "import os\n", + "os.environ['PATH'] = '/opt/Xilinx/Vivado/2019.2/bin:' + os.environ['PATH']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fetch the jet tagging dataset from Open ML" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X_train_val = np.load('X_train_val.npy')\n", + "X_test = np.load('X_test.npy')\n", + "y_train_val = np.load('y_train_val.npy')\n", + "y_test = np.load('y_test.npy')\n", + "classes = np.load('classes.npy', allow_pickle=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Now construct a model\n", + "We'll use the same architecture as in part 1: 3 hidden layers with 64, then 32, then 32 neurons. Each layer will use `relu` activation.\n", + "Add an output layer with 5 neurons (one for each class), then finish with Softmax activation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from tensorflow.keras.models import Sequential\n", + "from tensorflow.keras.layers import Dense, Activation, BatchNormalization\n", + "from tensorflow.keras.optimizers import Adam\n", + "from tensorflow.keras.regularizers import l1\n", + "from callbacks import all_callbacks" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model = Sequential()\n", + "model.add(Dense(64, input_shape=(16,), name='fc1', kernel_initializer='lecun_uniform', kernel_regularizer=l1(0.0001)))\n", + "model.add(Activation(activation='relu', name='relu1'))\n", + "model.add(Dense(32, name='fc2', kernel_initializer='lecun_uniform', kernel_regularizer=l1(0.0001)))\n", + "model.add(Activation(activation='relu', name='relu2'))\n", + "model.add(Dense(32, name='fc3', kernel_initializer='lecun_uniform', kernel_regularizer=l1(0.0001)))\n", + "model.add(Activation(activation='relu', name='relu3'))\n", + "model.add(Dense(5, name='output', kernel_initializer='lecun_uniform', kernel_regularizer=l1(0.0001)))\n", + "model.add(Activation(activation='softmax', name='softmax'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Train sparse\n", + "This time we'll use the Tensorflow model optimization sparsity to train a sparse model (forcing many weights to '0'). In this instance, the target sparsity is 75%" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from tensorflow_model_optimization.python.core.sparsity.keras import prune, pruning_callbacks, pruning_schedule\n", + "from tensorflow_model_optimization.sparsity.keras import strip_pruning\n", + "pruning_params = {\"pruning_schedule\" : pruning_schedule.ConstantSparsity(0.75, begin_step=2000, frequency=100)}\n", + "model = prune.prune_low_magnitude(model, **pruning_params)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Train the model\n", + "We'll use the same settings as the model for part 1: Adam optimizer with categorical crossentropy loss.\n", + "The callbacks will decay the learning rate and save the model into a directory 'model_2'\n", + "The model isn't very complex, so this should just take a few minutes even on the CPU.\n", + "If you've restarted the notebook kernel after training once, set `train = False` to load the trained model rather than training again." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train = True\n", + "if train:\n", + " adam = Adam(lr=0.0001)\n", + " model.compile(optimizer=adam, loss=['categorical_crossentropy'], metrics=['accuracy'])\n", + " callbacks = all_callbacks(stop_patience = 1000,\n", + " lr_factor = 0.5,\n", + " lr_patience = 10,\n", + " lr_epsilon = 0.000001,\n", + " lr_cooldown = 2,\n", + " lr_minimum = 0.0000001,\n", + " outputDir = 'model_2')\n", + " callbacks.callbacks.append(pruning_callbacks.UpdatePruningStep())\n", + " model.fit(X_train_val, y_train_val, batch_size=1024,\n", + " epochs=30, validation_split=0.25, shuffle=True,\n", + " callbacks = callbacks.callbacks)\n", + " # Save the model again but with the pruning 'stripped' to use the regular layer types\n", + " model = strip_pruning(model)\n", + " model.save('model_2/KERAS_check_best_model.h5')\n", + "else:\n", + " from tensorflow.keras.models import load_model\n", + " model = load_model('model_2/KERAS_check_best_model.h5')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Check sparsity\n", + "Make a quick check that the model was indeed trained sparse. We'll just make a histogram of the weights of the 1st layer, and hopefully observe a large peak in the bin containing '0'. Note logarithmic y axis." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "w = model.layers[0].weights[0].numpy()\n", + "h, b = np.histogram(w, bins=100)\n", + "plt.figure(figsize=(7,7))\n", + "plt.bar(b[:-1], h, width=b[1]-b[0])\n", + "plt.semilogy()\n", + "print('% of zeros = {}'.format(np.sum(w==0)/np.size(w)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Check performance\n", + "How does this 75% sparse model compare against the unpruned model? Let's report the accuracy and make a ROC curve. The pruned model is shown with solid lines, the unpruned model from part 1 is shown with dashed lines.\n", + "**Make sure you've trained the model from part 1**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import plotting\n", + "import matplotlib.pyplot as plt\n", + "from sklearn.metrics import accuracy_score\n", + "from tensorflow.keras.models import load_model\n", + "model_ref = load_model('model_1/KERAS_check_best_model.h5')\n", + "\n", + "y_ref = model_ref.predict(X_test)\n", + "y_prune = model.predict(X_test)\n", + "\n", + "print(\"Accuracy unpruned: {}\".format(accuracy_score(np.argmax(y_test, axis=1), np.argmax(y_ref, axis=1))))\n", + "print(\"Accuracy pruned: {}\".format(accuracy_score(np.argmax(y_test, axis=1), np.argmax(y_prune, axis=1))))\n", + "\n", + "fig, ax = plt.subplots(figsize=(9, 9))\n", + "_ = plotting.makeRoc(y_test, y_ref, classes)\n", + "plt.gca().set_prop_cycle(None) # reset the colors\n", + "_ = plotting.makeRoc(y_test, y_prune, classes, linestyle='--')\n", + "\n", + "from matplotlib.lines import Line2D\n", + "lines = [Line2D([0], [0], ls='-'),\n", + " Line2D([0], [0], ls='--')]\n", + "from matplotlib.legend import Legend\n", + "leg = Legend(ax, lines, labels=['unpruned', 'pruned'],\n", + " loc='lower right', frameon=False)\n", + "ax.add_artist(leg)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Convert the model to FPGA firmware with hls4ml\n", + "Let's use the default configuration: `ap_fixed<16,6>` precision everywhere and `ReuseFactor=1`, so we can compare with the part 1 model. We need to use `strip_pruning` to change the layer types back to their originals.\n", + "\n", + "**The synthesis will take a while**\n", + "\n", + "While the C-Synthesis is running, we can monitor the progress looking at the log file by opening a terminal from the notebook home, and executing:\n", + "\n", + "`tail -f model_2/hls4ml_prj/vivado_hls.log`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import hls4ml\n", + "\n", + "config = hls4ml.utils.config_from_keras_model(model, granularity='model')\n", + "print(config)\n", + "hls_model = hls4ml.converters.convert_from_keras_model(model,\n", + " hls_config=config,\n", + " output_dir='model_2/hls4ml_prj',\n", + " part='xcu250-figd2104-2L-e')\n", + "hls_model.compile()\n", + "hls_model.build(csim=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Check the reports\n", + "Print out the reports generated by Vivado HLS. Pay attention to the Utilization Estimates' section in particular this time." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hls4ml.report.read_vivado_report('model_2/hls4ml_prj/')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Print the report for the model trained in part 1. Remember these models have the same architecture, but the model in this section was trained using the sparsity API from tensorflow_model_optimization. Notice how the resource usage had dramatically reduced (particularly the DSPs). When Vivado HLS notices an operation like `y = 0 * x` it can avoid placing a DSP for that operation. The impact of this is biggest when `ReuseFactor = 1`, but still applies at higher reuse as well. **Note you need to have trained and synthesized the model from part 1**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hls4ml.report.read_vivado_report('model_1/hls4ml_prj')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.8.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}