public void Adjust_opt_target ()
		{
			

			// First epoch only set the initial UF target
			if (m_opt_counter == 1) {
				m_uf_target = m_currunfairness;
				m_opt_state = OPT_STATE.FAIR_OPT;
				return;
			}

			// if uf target meets
			if (m_currunfairness - m_uf_target < 0) {
				Console.WriteLine ("Meet unfairness target.");
				if (++m_succ_meet_counter > Config.succ_meet_fair) {
					m_uf_target = m_currunfairness - Config.uf_adjust;
					m_opt_state = OPT_STATE.PERFORMANCE_OPT;
					m_fair_opt_counter = 0;
					m_action = THROTTLE_ACTION.UP;
				} else {
					m_opt_state = OPT_STATE.FAIR_OPT;
					m_fair_opt_counter++;
					m_action = THROTTLE_ACTION.NO_OP;
				}
			} else {
			// uf target miss
				Console.WriteLine ("Miss unfairness target.");
				if (m_fair_opt_counter > Config.fair_keep_trying) { 
					m_uf_target = m_currunfairness - Config.uf_adjust;
					m_opt_state = OPT_STATE.PERFORMANCE_OPT;
					m_action = THROTTLE_ACTION.RESET;
					m_fair_opt_counter = 0;
					Console.WriteLine ("FAIR_OPT_COUNT reaches max value.");
				} else {
					m_fair_opt_counter++;
					m_action = THROTTLE_ACTION.DOWN;
					m_opt_state = OPT_STATE.FAIR_OPT;			
				}
				m_succ_meet_counter = 0;
			}

			Console.WriteLine ("Next state is {0}", m_opt_state.ToString());
			Console.WriteLine ("New UF target is {0:0.00}", m_uf_target);
		}
		public void throttle_stc ()
		{
			m_currunfairness = m_est_sd [m_slowest_core];	
			ComputePerformance ();
			RankBySD (); // use to mark unthrottled core
			RankBySTC (); 
			if (m_epoch_counter == 0)
				m_init_perf = m_currperf;
			if (m_opt_state == OPT_STATE.PERFORMANCE_OPT) {
				//if (m_perf_opt_counter == Config.opt_perf_bound || m_currunfairness >= m_budget_unfairness) {
				if (m_perf_opt_counter == Config.opt_perf_bound) {
					//m_init_unfairness = m_currunfairness;
					//m_budget_perf = m_currperf + (m_init_perf - m_currperf) * Config.perf_budget_factor;
					//m_budget_perf = m_currperf * 1.05;
					//throttle_reset ();
					//if (m_budget_perf < m_currperf)
					//	m_opt_state = OPT_STATE.IDLE;
					//else
						m_opt_state = OPT_STATE.FAIR_OPT;
					m_perf_opt_counter = 0;
				} else {
					Optimize ();
					Simulator.stats.opt_perf.Add(1);
					Console.WriteLine ("Optimize Performance epoch: {0}", Simulator.stats.opt_perf.Count);
					m_perf_opt_counter++;
				}	
			} else if (m_opt_state == OPT_STATE.FAIR_OPT) {
				//if (m_fair_opt_counter == Config.opt_fair_bound || m_currperf >= m_budget_perf) {
				if (m_fair_opt_counter == Config.opt_fair_bound) {
					//m_init_perf = m_currperf;
					//m_budget_unfairness = m_currunfairness + (m_init_unfairness - m_currunfairness) * Config.fair_budget_factor;
					//throttle_reset ();
					//if (m_budget_unfairness < m_currunfairness)
					//	m_opt_state = OPT_STATE.IDLE;
					//else
						m_opt_state = OPT_STATE.PERFORMANCE_OPT;
					m_fair_opt_counter = 0;
				} else {
					Optimize ();
					Simulator.stats.opt_fair.Add(1);
					Console.WriteLine ("Optimize Fairness epoch: {0}", Simulator.stats.opt_fair.Count);
					m_fair_opt_counter++;
				}
				
			} else if (m_opt_state == OPT_STATE.IDLE) {
				if (m_currperf - m_init_perf > Config.th_init_perf_loss) {
					m_opt_state = OPT_STATE.PERFORMANCE_OPT;
					m_init_perf = m_currperf;
				} else if (m_currunfairness - m_init_unfairness > Config.th_init_fair_loss) {
					m_opt_state = OPT_STATE.FAIR_OPT;
					m_init_unfairness = m_currunfairness;
				}
				m_idle_counter++;
				Console.WriteLine("Stay idle epoch: {0}", m_idle_counter);
			}

			m_epoch_counter++;
			unfairness_old = m_currunfairness;
			m_oldperf = m_currperf;
			// just log the mshr quota
			for (int i = 0; i < Config.N; i++)
				Simulator.stats.mshrs_credit [i].Add (Controller_QoSThrottle.mshr_quota [i]);
			
		}
		public Controller_QoSThrottle()
		{
			Console.WriteLine("init Controller_QoSThrottle");
			for (int i = 0; i < Config.N; i++)
			{
				throttle_rate [i] = 0;

				throttle_node [i] = "1";
				m_est_sd [i] = 1;
				m_stc [i] = 0;
				m_stc_unsort[i] = 0;
				m_est_sd_unsort [i] = 0;

				// assign initial mshr quota
				mshr_quota [i] = Config.mshrs;
				mshr_best_sol [i] = Config.mshrs;
				app_rank [i] = 0;
				app_type [i] = APP_TYPE.LATENCY_SEN;
				fast_app_type [i] = APP_TYPE.STC;
				most_mem_inten [i] = false;
				pre_throt  [i] = false;
				bad_decision_counter [i] = 0;
				m_actionQ [i] = THROTTLE_ACTION.NO_OP;
				m_uf_target = 0;
			}

			m_opt_state = OPT_STATE.PERFORMANCE_OPT;

			max_rank = 0;
			m_slowest_core = 0;
            m_fastest_core = 0;
			m_perf_opt_counter = 0;
			m_fair_opt_counter = 0;
			m_succ_meet_counter = 0;
			m_init_unfairness = 0;
			m_init_perf = 0;
			m_epoch_counter = 0;
			m_idle_counter = 0;
			m_oldperf = 0;
			m_oldunfairness = 0;
			m_opt_counter = 0;
			m_throttle_enable = Config.throttle_enable;
			m_l1miss_avg = 0;
			m_sd_avg = 0;
			unthrottable_count = 0;
			m_action = THROTTLE_ACTION.NO_OP;
		}