{
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  },
  "name": "",
  "signature": "sha256:59ef0b9fe2847e77f9df55deeb6df1f94f4fe2a3a0f99e13cba99854e8bf66ed"
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "Configuration"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import trappy\n",
      "import numpy\n",
      "\n",
      "config = {}\n",
      "\n",
      "# TRAPpy Events\n",
      "config[\"THERMAL\"] = trappy.thermal.Thermal\n",
      "config[\"OUT\"] = trappy.cpu_power.CpuOutPower\n",
      "config[\"IN\"] = trappy.cpu_power.CpuInPower\n",
      "config[\"PID\"] = trappy.pid_controller.PIDController\n",
      "config[\"GOVERNOR\"] = trappy.thermal.ThermalGovernor\n",
      "\n",
      "# Control Temperature\n",
      "config[\"CONTROL_TEMP\"] = 77000\n",
      "\n",
      "# A temperature margin of 2.5 degrees Celsius\n",
      "config[\"TEMP_MARGIN\"] = 2500\n",
      "\n",
      "# The Sustainable power at the control Temperature\n",
      "config[\"SUSTAINABLE_POWER\"] = 2500\n",
      "\n",
      "# Expected percentile of CONTROL_TEMP + TEMP_MARGIN\n",
      "config[\"EXPECTED_TEMP_QRT\"] = 95\n",
      "\n",
      "# Maximum expected Standard Deviation as a percentage\n",
      "# of mean temperature\n",
      "config[\"EXPECTED_STD_PCT\"] = 5\n"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 1
    },
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "Get the Trace"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import urllib\n",
      "import os\n",
      "\n",
      "TRACE_DIR = \"example_trace_dat_thermal\"\n",
      "TRACE_FILE = os.path.join(TRACE_DIR, 'bart_thermal_trace.dat')\n",
      "TRACE_URL = 'http://cdn.rawgit.com/sinkap/4e0a69cbff732b57e36f/raw/7dd0ed74bfc17a34a3bd5ea6b9eb3a75a42ddbae/bart_thermal_trace.dat'\n",
      "\n",
      "if not os.path.isdir(TRACE_DIR):\n",
      "    os.mkdir(TRACE_DIR)\n",
      "\n",
      "if not os.path.isfile(TRACE_FILE):\n",
      "    print \"Fetching trace file..\"\n",
      "    urllib.urlretrieve(TRACE_URL, filename=TRACE_FILE)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 2
    },
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "FTrace Object"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "# Create a Trace object\n",
      "\n",
      "ftrace = trappy.FTrace(TRACE_FILE, \"SomeBenchMark\")"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 3
    },
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "Assertions"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "# Create an Assertion Object\n",
      "\n",
      "from bart.common.Analyzer import Analyzer\n",
      "t = Analyzer(ftrace, config)\n",
      "\n",
      "BIG = '000000f0'\n",
      "LITTLE = '0000000f'"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 4
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Assertion: Load and Dynamic Power"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "<html>\n",
      "This assertion makes sure that the dynamic power for the each cluster is zero when the sum of the \"loads\" of each CPU is 0\n",
      "\n",
      "    $$\\forall\\ t\\ |\\ Load(t) = \\sum\\limits_{i=0}^{cpus} Load_i(t) = 0 \\implies dynamic\\ power(t)=0 $$\n",
      "    \n",
      "</html>"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "result = t.getStatement(\"((IN:load0 + IN:load1 + IN:load2 + IN:load3) == 0) \\\n",
      "                & (IN:dynamic_power > 0)\",reference=True, select=BIG)\n",
      "if len(result):\n",
      "    print \"FAIL: Dynamic Power is NOT Zero when load is Zero for the BIG cluster\"\n",
      "else:\n",
      "    print \"PASS: Dynamic Power is Zero when load is Zero for the BIG cluster\"\n",
      "\n",
      "    \n",
      "result = t.getStatement(\"((IN:load0 + IN:load1 + IN:load2 + IN:load3) == 0) \\\n",
      "                & (IN:dynamic_power > 0)\",reference=True, select=LITTLE)\n",
      "if len(result):\n",
      "    print \"FAIL: Dynamic Power is NOT Zero when load is Zero for the LITTLE cluster\"\n",
      "else:\n",
      "    print \"PASS: Dynamic Power is Zero when load is Zero for the LITTLE cluster\""
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "PASS: Dynamic Power is Zero when load is Zero for the BIG cluster\n",
        "PASS: Dynamic Power is Zero when load is Zero for the LITTLE cluster\n"
       ]
      }
     ],
     "prompt_number": 5
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Assertion: Control Temperature and Sustainable Power"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "<html>\n",
      "\n",
      "When the temperature is greater than the control temperature, the total power granted to all cooling devices should be less than sustainable_power\n",
      "\n",
      "$$\\forall\\ t\\ |\\ Temperature(t) > control\\_temp \\implies Total\\ Granted\\ Power(t) < sustainable\\_power$$\n",
      "\n",
      "<html/>"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "result = t.getStatement(\"(GOVERNOR:current_temperature > CONTROL_TEMP) &\\\n",
      "            (PID:output > SUSTAINABLE_POWER)\", reference=True, select=0)\n",
      "\n",
      "if len(result):\n",
      "    print \"FAIL: The Governor is allocating power > sustainable when T > CONTROL_TEMP\"\n",
      "else:\n",
      "    print \"PASS: The Governor is allocating power <= sustainable when T > CONTROL_TEMP\"    "
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "PASS: The Governor is allocating power <= sustainable when T > CONTROL_TEMP\n"
       ]
      }
     ],
     "prompt_number": 6
    },
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "Statistics"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Check if 95% of the temperature readings are below CONTROL_TEMP + MARGIN"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "t.assertStatement(\"numpy.percentile(THERMAL:temp, 95) < (CONTROL_TEMP + TEMP_MARGIN)\")"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 7,
       "text": [
        "True"
       ]
      }
     ],
     "prompt_number": 7
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Check if the mean temperauture is less than CONTROL_TEMP"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "t.assertStatement(\"numpy.mean(THERMAL:temp) <= CONTROL_TEMP\",  select=0)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 8,
       "text": [
        "True"
       ]
      }
     ],
     "prompt_number": 8
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "We can also use getStatement to get the absolute values. Here we are getting the standard deviation expressed as a percentage of the mean"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "t.getStatement(\"(numpy.std(THERMAL:temp) * 100.0) / numpy.mean(THERMAL:temp)\", select=0)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 9,
       "text": [
        "2.2390646863105119"
       ]
      }
     ],
     "prompt_number": 9
    },
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {},
     "source": [
      "Thermal Residency"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from bart.thermal.ThermalAssert import ThermalAssert\n",
      "\n",
      "t_assert = ThermalAssert(ftrace)\n",
      "end = ftrace.get_duration()\n",
      "\n",
      "LOW = 0\n",
      "HIGH = 78000\n",
      "\n",
      "# The thermal residency gives the percentage (or absolute time) spent in the\n",
      "# specified temperature range. \n",
      "\n",
      "result = t_assert.getThermalResidency(temp_range=(0, 78000),\n",
      "                                              window=(0, end),\n",
      "                                              percent=True)\n",
      "\n",
      "for tz_id in result:\n",
      "    print \"Thermal Zone: {} spends {:.2f}% time in the temperature range [{}, {}]\".format(tz_id, \n",
      "                                                                                          result[tz_id],\n",
      "                                                                                          LOW/1000,\n",
      "                                                                                          HIGH/1000)\n",
      "    pct_temp = numpy.percentile(t.getStatement(\"THERMAL:temp\")[tz_id], result[tz_id])\n",
      "    \n",
      "    print \"The {:.2f}th percentile temperature is {:.2f}\".format(result[tz_id], pct_temp / 1000.0)\n",
      "    "
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "Thermal Zone: 0 spends 86.58% time in the temperature range [0, 78]\n",
        "The 86.58th percentile temperature is 78.28\n"
       ]
      }
     ],
     "prompt_number": 10
    }
   ],
   "metadata": {}
  }
 ]
}