diff --git a/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/hpvm-rt-controller.h b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/hpvm-rt-controller.h
index fbe350adb98f815c99452c67a3d02dfbc6806272..f7d1018c9a2c7f25df642c8593b9612ae92dfa98 100644
--- a/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/hpvm-rt-controller.h
+++ b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/hpvm-rt-controller.h
@@ -7,6 +7,7 @@
 #include <vector>
 #include <cstring>
 #include <cstdlib>
+#include <random>
 
 #include "configuration.h"
 
@@ -124,6 +125,8 @@ class ProfileInfo {
 
   void readIterationFrequency();
 
+  unsigned long getIterationFrequency();
+
   void set_out_file_name(std::string &str);
 
   void printToFile();
@@ -177,6 +180,13 @@ class RuntimeController {
   Slowdowns *slowdowns;
 
   float pseudo_rd = 0.0;
+  std::mt19937 generator;
+  std::uniform_real_distribution<> distr;
+
+  // Stored frequency and speedup for a running iteration.
+  // To be changed for a new frequency point
+  unsigned long g_freq = 0;
+  double g_speedup = 1.0;
 
   /*** Objects used to gather timing and energy information for execution ***/
   ProfileInfo *PI;
@@ -210,11 +220,21 @@ class RuntimeController {
   // For testing purposes only - do not use widely
   unsigned getConfigurationIdx();
 
+  double getCurrentConfigurationSpeedup();
+  double getCurrentConfigurationEnergy();
+  double getCurrentConfigurationAccuracy();
+  double getCurrentConfigurationAccuracyLoss();
+
   std::vector<float> &getQuantizationRanges(const char *data);
 
   NodeConfiguration *getNodeConfiguration(const char *data);
 
   // Functions for runtime control
+  unsigned long getLastFrequency();
+  void setLastFrequency(unsigned long);
+  double getLastSpeedup();
+  void setLastSpeedup(double);
+
   void findNextConfiguration();
   void findTargetConfiguration(float, enum SEARCH_KIND);
   void adjustTargetConfiguration(float);
@@ -245,6 +265,8 @@ class RuntimeController {
 
   void readIterationFrequency();
 
+  unsigned long getIterationFrequency();
+
   void updateFrequency();
 
   void writeProfileInfo();
diff --git a/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/hpvm-rt-controller.cpp b/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/hpvm-rt-controller.cpp
index 813d77c46a51ede56dcc509495308637eb2ce862..9dba9ca15b2c267b505e6a3a72620b37e44c93e1 100644
--- a/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/hpvm-rt-controller.cpp
+++ b/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/hpvm-rt-controller.cpp
@@ -1,16 +1,38 @@
+
 #include "hpvm-rt-controller.h"
 #include "img_tensor_utils.h"
 #include "global_data.h"
+#include <fstream>
 
 //-------- Functionality to read and update frequency on Jetson board -------//
-const char* available_freqs[] = {"140250000", "229500000", "318750000",
+/*const char* available_freqs[] = {"140250000", "229500000", "318750000",
                                  "408000000", "497250000", "586500000", 
                                  "675750000", "765000000", "854250000",
                                  "943500000", "1032750000", "1122000000",
                                  "1211250000", "1300500000"};
 
+*/
+
+
+const int available_freqs[] = {
+140250000, // 0
+229500000, // 1
+318750000, // 2
+408000000, // 3
+497250000, // 4
+586500000, // 5
+675750000, // 6
+765000000, // 7
+854250000, // 8
+943500000, // 9
+1032750000,// 10
+1122000000,// 11
+1211250000,// 12
+1300500000 // 13
+};
+
 
-void updateJetsonGPUFreq(int freq_level) {
+/*void updateJetsonGPUFreq(int freq_level) {
 
   if (freq_level < 0 || freq_level > 13) {
     printf("ERROR: Provide freq level between {0, 13}  \n\n\n");
@@ -55,6 +77,51 @@ unsigned long int readJetsonGPUFreq() {
   return cur_freq;
 }
 
+*/
+
+
+// Sets frequency
+void setFreq(unsigned freq_index) {
+
+  unsigned target_freq = available_freqs[freq_index];
+  
+  const char * const min_freq_file = "/sys/devices/17000000.gp10b/devfreq/17000000.gp10b/min_freq";
+  const char * const max_freq_file = "/sys/devices/17000000.gp10b/devfreq/17000000.gp10b/max_freq";
+
+  std::ofstream min_stream;
+  std::ofstream max_stream;
+
+  min_stream.open(min_freq_file, std::ofstream::out);
+  max_stream.open(max_freq_file, std::ofstream::out);
+
+  min_stream << target_freq << std::flush;
+  max_stream << target_freq << std::flush;
+
+  min_stream.close();
+  max_stream.close();
+}
+
+// Records frequency
+unsigned recordFreq() {
+
+  // Current frequency file
+  const char * const cur_freq_file = "/sys/devices/17000000.gp10b/devfreq/17000000.gp10b/cur_freq";
+  std::ifstream cur_stream;
+  cur_stream.open(cur_freq_file, std::ifstream::in);
+
+  // Get starting frequency
+  unsigned cur_freq;
+  cur_stream >> cur_freq;
+  std::cout << "Starting frequency = " << cur_freq << "\n";
+  cur_stream.close();
+
+  return cur_freq;
+}
+
+
+
+
+
 //---------------------------------------------------------------------------//
 
 /*
@@ -137,12 +204,17 @@ void ProfileInfo::end_iteration() {
 
 void ProfileInfo::readIterationFrequency() {
 #ifdef JETSON_EXECUTION
-  frequency_current_iteration = readJetsonGPUFreq();
+  //----- frequency_current_iteration = readJetsonGPUFreq();
+  frequency_current_iteration = recordFreq();
 #else
   frequency_current_iteration = 0;
 #endif //JETSON_EXECUTION
 }
 
+unsigned long ProfileInfo::getIterationFrequency() {
+  return frequency_current_iteration;
+}
+
 void ProfileInfo::addToCurrentIterationComputeTime(const char *s, double t) {
   start_iteration();
   time_compute_current_iteration += t;
@@ -321,6 +393,22 @@ getThreeDCurveConfigurations() {
 // For testing purposes only - do not use widely
 unsigned RuntimeController::getConfigurationIdx() { return configurationIdx; }
 
+double RuntimeController::getCurrentConfigurationSpeedup() {
+  return (double) (*Configurations)[configurationIdx]->speedup;
+}
+
+double RuntimeController::getCurrentConfigurationEnergy() {
+  return (double) (*Configurations)[configurationIdx]->energy;
+}
+
+double RuntimeController::getCurrentConfigurationAccuracy() {
+  return (double) (*Configurations)[configurationIdx]->accuracy;
+}
+
+double RuntimeController::getCurrentConfigurationAccuracyLoss() {
+  return (double) (*Configurations)[configurationIdx]->accuracyLoss;
+}
+
 std::vector<float> &RuntimeController::getQuantizationRanges(const char *data) {
   std::string s(data);
   // All nodes are expected to have quantization ranges
@@ -356,7 +444,16 @@ void RuntimeController::init(const char *Cstr, const char *Qstr) {
   // Initializations for different runtime control strategies
   srand(static_cast<unsigned>(time(0)));
   slowdowns = new Slowdowns();
+
+  // Pseudo random variable (when we did few experiments)
+  // or true random numbers for probabilistic control
   pseudo_rd = 0.0;
+  std::random_device rd;  //Will be used to obtain a seed for the random number engine
+  generator = std::mt19937 (rd()); //Standard mersenne_twister_engine seeded with rd()
+  distr = std::uniform_real_distribution<>(0.0, 1.0);
+
+  g_freq = available_freqs[13];
+  g_speedup = 1.0;
 
   // Initialize utility objects for knob reading
   perfParamSet = new PerfParamSet();
@@ -419,10 +516,17 @@ void RuntimeController::readIterationFrequency() {
     PI->readIterationFrequency();
 }
 
+unsigned long RuntimeController::getIterationFrequency() {
+  return (PI ? PI->getIterationFrequency() : 0);
+}
+
 void RuntimeController::updateFrequency() {
 #ifdef JETSON_EXECUTION
   unsigned freq_idx = FIL->getNextIndex();
-  updateJetsonGPUFreq(freq_idx);
+  //--- updateJetsonGPUFreq(freq_idx);
+
+  setFreq(freq_idx);
+  
 #endif //JETSON_EXECUTION
 }
 
@@ -1076,6 +1180,22 @@ void RuntimeController::printConfigurations(
   }
 }
 
+unsigned long RuntimeController::getLastFrequency() {
+  return g_freq;
+}
+
+void RuntimeController::setLastFrequency(unsigned long f) {
+  g_freq = f;
+}
+
+double RuntimeController::getLastSpeedup() {
+  return g_speedup;
+}
+
+void RuntimeController::setLastSpeedup(double s) {
+  g_speedup = s;
+}
+
 void RuntimeController::findNextConfiguration() {
   configurationIdx = (configurationIdx + 1) % Configurations->size();
   DEBUG(
@@ -1157,6 +1277,41 @@ void RuntimeController::adjustTargetConfiguration(float goal) {
   } else {
     high_pb = low_range / sp_diff;
     low_pb = high_range / sp_diff;
+
+    //***--- Probability adjustment strategy 1 ---***//
+    // No big adjustments at edges of probability range
+//    float adjust_val = 0.0;
+//    if (low_pb < high_pb) {
+//      adjust_val = low_pb * 0.2;
+//    } else {
+//      adjust_val = high_pb * 0.2;
+//    }
+//    low_pb -= adjust_val;
+//    high_pb += adjust_val;
+    //***---                                   ---***//
+
+    //***--- Probability adjustment strategy 2 ---***//
+    // No big adjustment at high edge of probability range
+//    float adjust_val = high_pb * 0.2 > 0.1 ? 0.1 : high_pb * 0.2;
+//    low_pb -= adjust_val;
+//    high_pb += adjust_val;
+    //***---                                   ---***//
+
+    //***--- Probability adjustment strategy 3 ---***//
+    //Similar to 2, but higher always increases, more significantly
+//    float adjust_val = low_pb * 0.5 > 0.1 ? 0.1 : low_pb * 0.5;
+//    low_pb -= adjust_val;
+//    high_pb += adjust_val;
+    //***---                                   ---***//
+
+    //***--- Probability adjustment strategy 4 ---***//
+    //Similar to 2, but higher always increases, more significantly
+    // Low end, high end a bit less aggressive than total range
+    float adjust_val = low_pb * 0.6 > 0.2 ? 0.2 : low_pb * 0.6;
+    adjust_val = adjust_val > high_pb ? high_pb : adjust_val;
+    low_pb -= adjust_val;
+    high_pb += adjust_val;
+    //***---                                   ---***//
   }
 
   DEBUG(
@@ -1171,8 +1326,9 @@ void RuntimeController::adjustTargetConfiguration(float goal) {
   // Select a random number from 0 to 1
   // We assign the (0..low_pb) to the lower configuration, and the (low_pb..1)
   // to the upper
-  //  float rd = static_cast <float> (rand()) / static_cast <float> (RAND_MAX) ;
-  float rd = pseudo_rd;
+  // float rd = static_cast <float> (rand()) / static_cast <float> (RAND_MAX) ;
+  //float rd = pseudo_rd;
+  float rd = distr(generator);
   if (rd < low_pb) {
     // If the probability is in the low range
     configurationIdx = prev_conf_idx;
@@ -1293,7 +1449,9 @@ float hpvm_rt_computeAccuracy3(uint32_t *labels, void *result_ptr) {
 }
 
 
+//#define llvm_hpvm_invokeRtControl_BASE llvm_hpvm_invokeRtControl
 #define llvm_hpvm_invokeRtControl_ADJUST_PR llvm_hpvm_invokeRtControl
+//#define llvm_hpvm_invokeRtControl_ADJUST llvm_hpvm_invokeRtControl
 
 extern "C" void llvm_hpvm_invokeRtControl_BASE(
     void *result, const char *str, int start, int end) {
@@ -1366,8 +1524,18 @@ extern "C" void llvm_hpvm_invokeRtControl_ADJUST(
 
   RC->resume_profiler();
   double current_iteration_time = RC->getCurrentIterationComputeTime();
-  double baseline_time = RC->getBaselineTime();
-  double target_speedup = current_iteration_time / baseline_time;
+  double target_speedup;
+  if (RC->getLastFrequency() == RC->getIterationFrequency()) {
+    target_speedup = RC->getLastSpeedup();
+  } else {
+    double baseline_time = RC->getBaselineTime();
+    // Relative to current configuration
+    target_speedup = current_iteration_time / baseline_time;
+    // Adjust to baseline
+    target_speedup *= RC->getCurrentConfigurationSpeedup();
+    RC->setLastFrequency(RC->getIterationFrequency());
+    RC->setLastSpeedup(target_speedup);
+  }
   RC->findTargetConfiguration(target_speedup, SPEEDUP);
   RC->pause_profiler();
 
@@ -1409,8 +1577,18 @@ extern "C" void llvm_hpvm_invokeRtControl_ADJUST_PR(
 
   RC->resume_profiler();
   double current_iteration_time = RC->getCurrentIterationComputeTime();
-  double baseline_time = RC->getBaselineTime();
-  double target_speedup = current_iteration_time / baseline_time;
+  double target_speedup;
+  if (RC->getLastFrequency() == RC->getIterationFrequency()) {
+    target_speedup = RC->getLastSpeedup();
+  } else {
+    double baseline_time = RC->getBaselineTime();
+    // Relative to current configuration
+    target_speedup = current_iteration_time / baseline_time;
+    // Adjust to baseline
+    target_speedup *= RC->getCurrentConfigurationSpeedup();
+    RC->setLastFrequency(RC->getIterationFrequency());
+    RC->setLastSpeedup(target_speedup);
+  }
   RC->findTargetConfiguration(target_speedup, SPEEDUP);
   RC->adjustTargetConfiguration(target_speedup);
   RC->pause_profiler();