Selaa lähdekoodia

Add basic adaptive checkpoint strategy

Youngbin Kim 1 vuosi sitten
vanhempi
sitoutus
1b5eb8ed7d

+ 17 - 0
Core/Inc/ImC/imc_extension.h

@@ -17,6 +17,14 @@
     #define imcENABLE_STATIC_LOOP_PASS_COUNT 0
     #define imcENABLE_STATIC_LOOP_PASS_COUNT 0
 #endif
 #endif
 
 
+#ifndef imcENABLE_ADAPTIVE_LOOP_PASS_COUNT
+    #define imcENABLE_ADAPTIVE_LOOP_PASS_COUNT 0
+#endif
+
+#ifndef imcMAX_LOOP_IDS
+    #define imcMAX_LOOP_IDS 1
+#endif
+
 #ifndef imcLOOP_PASS_COUNT
 #ifndef imcLOOP_PASS_COUNT
     #define imcLOOP_PASS_COUNT 10
     #define imcLOOP_PASS_COUNT 10
 #endif 
 #endif 
@@ -25,6 +33,15 @@
     #define imcBENCH_REPEAT_COUNT 1
     #define imcBENCH_REPEAT_COUNT 1
 #endif
 #endif
 
 
+#define imcCAP_VOL_HIGH 4800
+#define imcCAP_VOL_LOW 3500
+#define imcENERGY_TOTAL (imcCAP_VOL_HIGH*imcCAP_VOL_HIGH - imcCAP_VOL_LOW*imcCAP_VOL_LOW)
+
 int __imc_get_loop_pass_count(int loop_id);
 int __imc_get_loop_pass_count(int loop_id);
+void __imc_finish_loop_skipping();
+
+void imc_init_energy_estimation();
+
+extern int imc_is_passing_loops;
 
 
 #endif
 #endif

+ 1 - 1
Core/Inc/ImC/imc_kernel.h

@@ -18,7 +18,7 @@
 #endif
 #endif
 
 
 #ifndef imcCHECKPOINT_VOLTAGE
 #ifndef imcCHECKPOINT_VOLTAGE
-    #define imcCHECKPOINT_VOLTAGE 4100 //in mV
+    #define imcCHECKPOINT_VOLTAGE 3800 //in mV
 #endif
 #endif
 
 
 #define imcSTM32_CUBE_IDE 0
 #define imcSTM32_CUBE_IDE 0

+ 7 - 4
Core/Src/ImC/imc_api.c

@@ -261,23 +261,26 @@ int medianCalc(int* input, int arr_size){
 
 
 }
 }
 
 
-uint16_t MEAS_COEF[2] = {812, 782};	// for EPS CAP ch0 and ch1
+// uint16_t MEAS_COEF[2] = {812, 782};	// for EPS CAP ch0 and ch1
+uint16_t MEAS_COEF[2] = {700, 782};	// imc, 10mF
 int measure_voltage(ADC_HandleTypeDef hadc, uint8_t ch){
 int measure_voltage(ADC_HandleTypeDef hadc, uint8_t ch){
-	int res_value[5];
+	int n_evals = 1;
+	int res_value[n_evals];
 
 
 /* UCR ref.
 /* UCR ref.
 	#define MEAS_COEF 3051	// UCR 2790, ETRI 3051
 	#define MEAS_COEF 3051	// UCR 2790, ETRI 3051
 	int v_value = ((uint32_t)medianCalc(res_value, 5))*5000/MEAS_COEF; // in milliVolt
 	int v_value = ((uint32_t)medianCalc(res_value, 5))*5000/MEAS_COEF; // in milliVolt
 */
 */
-	for (int i=0; i<5; i++)
+	for (int i=0; i<n_evals; i++)
 	{
 	{
 		HAL_ADC_Start(&hadc);
 		HAL_ADC_Start(&hadc);
 		// Poll ADC Peripheral & TimeOut = 1mSec
 		// Poll ADC Peripheral & TimeOut = 1mSec
 		HAL_ADC_PollForConversion(&hadc, 1);
 		HAL_ADC_PollForConversion(&hadc, 1);
 		res_value[i] = HAL_ADC_GetValue(&hadc);
 		res_value[i] = HAL_ADC_GetValue(&hadc);
+		HAL_ADC_Stop(&hadc);
 	}
 	}
 
 
-	int v_value = ((uint32_t)medianCalc(res_value, 5)) * MEAS_COEF[ch] / 500; //
+	int v_value = ((uint32_t)medianCalc(res_value, n_evals)) * MEAS_COEF[ch] / 500; //
 //	int voltage_d = v_value/1000;
 //	int voltage_d = v_value/1000;
 //	int voltage_f = v_value%1000;
 //	int voltage_f = v_value%1000;
 //	printf("ADC Value:     %d.%03d \r\n", voltage_d, voltage_f);
 //	printf("ADC Value:     %d.%03d \r\n", voltage_d, voltage_f);

+ 47 - 0
Core/Src/ImC/imc_extension.c

@@ -1,11 +1,58 @@
 #include <stdio.h>
 #include <stdio.h>
 
 
+#include "ImC/imc_kernel.h"
 #include "ImC/imc_extension.h"
 #include "ImC/imc_extension.h"
+#include "ImC/imc_api.h"
+
+extern ADC_HandleTypeDef ADC_HANDLER_SBC;
+
+float loop_energy_estimation[imcMAX_LOOP_IDS] IMC_GLOBAL;
+int imc_is_passing_loops IMC_GLOBAL;
+int imc_energy_estimation_initialized IMC_GLOBAL;
+
+void imc_init_energy_estimation() {
+    if(!imc_energy_estimation_initialized) {
+        for(int i=0; i<imcMAX_LOOP_IDS; i++) {
+            loop_energy_estimation[i] = 0.1;
+        }
+        imc_energy_estimation_initialized = 1;
+    }
+    if(imc_is_passing_loops != -1) {
+        float current_estimation = loop_energy_estimation[imc_is_passing_loops];
+        current_estimation *= 2;
+        if(current_estimation > 1) current_estimation = 1;
+        loop_energy_estimation[imc_is_passing_loops] = current_estimation;
+        // printf("estimation for loop%d is updated to %f\r\n", imc_is_passing_loops, current_estimation);
+    }
+    imc_is_passing_loops = -1;
+}
+
+void __imc_finish_loop_skipping() {
+    if(imc_is_passing_loops >= 0) {
+        int volt = measure_voltage(ADC_HANDLER_SBC, EPS_CAP_ID_SBC);
+        float energy_available = (float)(volt * volt - imcCAP_VOL_LOW * imcCAP_VOL_LOW) / imcENERGY_TOTAL;
+        if(energy_available > 0.2) {
+            float current_estimation = loop_energy_estimation[imc_is_passing_loops];
+            current_estimation /= 2;
+            loop_energy_estimation[imc_is_passing_loops] = current_estimation;
+            // printf("estimation for loop%d is updated to %f\r\n", imc_is_passing_loops, current_estimation);
+        }
+    }
+    imc_is_passing_loops = -1;
+}
 
 
 int __imc_get_loop_pass_count(int loop_id) {
 int __imc_get_loop_pass_count(int loop_id) {
     // printf("__imc_get_loop_pass_count() called\r\n");
     // printf("__imc_get_loop_pass_count() called\r\n");
     #if(imcENABLE_STATIC_LOOP_PASS_COUNT)
     #if(imcENABLE_STATIC_LOOP_PASS_COUNT)
         return imcLOOP_PASS_COUNT;
         return imcLOOP_PASS_COUNT;
+    #elif(imcENABLE_ADAPTIVE_LOOP_PASS_COUNT)
+        int volt = measure_voltage(ADC_HANDLER_SBC, EPS_CAP_ID_SBC);
+        float energy_available = (float)(volt*volt - imcCAP_VOL_LOW*imcCAP_VOL_LOW) / imcENERGY_TOTAL;
+        imc_is_passing_loops = loop_id;
+        // printf("energy available: %f\r\n", energy_available);
+        if(energy_available > 1) return (int)(energy_available / loop_energy_estimation[loop_id]);
+        else if(energy_available < 0) return 0;
+        else return (int)(energy_available / loop_energy_estimation[loop_id]);
     #else
     #else
         return 0;
         return 0;
     #endif
     #endif

+ 7 - 0
Core/Src/ImC/imc_kernel.c

@@ -5,6 +5,10 @@
 #include "stm32l5xx.h"
 #include "stm32l5xx.h"
 #include "cmsis_os.h"
 #include "cmsis_os.h"
 
 
+#if(imcUSE_IMC_EXTENSION)
+    #include "ImC/imc_extension.h"
+#endif
+
 #if(imcUSE_CHECKPOINT_VOLTAGE_CHECK)
 #if(imcUSE_CHECKPOINT_VOLTAGE_CHECK)
     extern ADC_HandleTypeDef ADC_HANDLER_SBC;
     extern ADC_HandleTypeDef ADC_HANDLER_SBC;
 #endif
 #endif
@@ -17,6 +21,9 @@
 void imcInit()
 void imcInit()
 {
 {
     FPU->FPCCR &= ~(FPU_FPCCR_LSPEN_Msk); // turn off lazy stacking
     FPU->FPCCR &= ~(FPU_FPCCR_LSPEN_Msk); // turn off lazy stacking
+    #if(imcUSE_IMC_EXTENSION)
+        imc_init_energy_estimation();
+    #endif
 }
 }
 
 
 int needCheckpointExecution() {
 int needCheckpointExecution() {

+ 5 - 0
Core/Src/benchmarks/adc_demo/adc_demo.c

@@ -9,6 +9,11 @@ void adc_demo()
 {
 {
     while(1) {
     while(1) {
         int volt = measure_voltage(ADC_HANDLER_SBC, EPS_CAP_ID_SBC);
         int volt = measure_voltage(ADC_HANDLER_SBC, EPS_CAP_ID_SBC);
+        // HAL_ADC_Start(&ADC_HANDLER_SBC);
+        // HAL_ADC_PollForConversion(&ADC_HANDLER_SBC, HAL_MAX_DELAY);
+        // int volt = HAL_ADC_GetValue(&ADC_HANDLER_SBC);
+        // printf("capacitor voltage: %d\r\n", volt);
+        // HAL_ADC_Stop(&ADC_HANDLER_SBC);
         printf("capacitor voltage: %d.%03d\r\n", volt/1000, volt%1000);
         printf("capacitor voltage: %d.%03d\r\n", volt/1000, volt%1000);
         osDelay(200);
         osDelay(200);
     }
     }

+ 9 - 2
Core/Src/main.c

@@ -239,8 +239,9 @@ int main(void)
   /* USER CODE BEGIN 2 */
   /* USER CODE BEGIN 2 */
 
 
   #if (imcUSE_IMC_KERNEL == 1)
   #if (imcUSE_IMC_KERNEL == 1)
+    HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
     imcInit();
     imcInit();
-  #endif
+#endif
 
 
   // printf("\r\n\r\n\r\n");
   // printf("\r\n\r\n\r\n");
   // printf("**************************\r\n");
   // printf("**************************\r\n");
@@ -409,6 +410,11 @@ static void MX_ADC1_Init(void)
   hadc1.Init.DMAContinuousRequests = DISABLE;
   hadc1.Init.DMAContinuousRequests = DISABLE;
   hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
   hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
   hadc1.Init.OversamplingMode = DISABLE;
   hadc1.Init.OversamplingMode = DISABLE;
+  // hadc1.Init.OversamplingMode = ENABLE;
+  // hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
+  // hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_NONE;
+  // hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
+  // hadc1.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
   if (HAL_ADC_Init(&hadc1) != HAL_OK)
   if (HAL_ADC_Init(&hadc1) != HAL_OK)
   {
   {
     Error_Handler();
     Error_Handler();
@@ -426,7 +432,8 @@ static void MX_ADC1_Init(void)
   */
   */
   sConfig.Channel = ADC_CHANNEL_1;
   sConfig.Channel = ADC_CHANNEL_1;
   sConfig.Rank = ADC_REGULAR_RANK_1;
   sConfig.Rank = ADC_REGULAR_RANK_1;
-  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
+  // sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
+  sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
   sConfig.SingleDiff = ADC_SINGLE_ENDED;
   sConfig.SingleDiff = ADC_SINGLE_ENDED;
   sConfig.OffsetNumber = ADC_OFFSET_NONE;
   sConfig.OffsetNumber = ADC_OFFSET_NONE;
   sConfig.Offset = 0;
   sConfig.Offset = 0;

+ 92 - 0
imc/exprs/date2025/3_adaptive/run_expr_3.py

@@ -0,0 +1,92 @@
+import tempfile
+import time
+import pickle
+import pandas as pd
+
+from imc_utils.pps_e36311a import PPS_E36311A
+from imc_utils.build_config.cortex_m33 import BuildConfigM33
+from imc_utils.build_config.test_env import TestEnv
+from imc_utils.serial_watch import SerialWatcher
+
+WORKSPACE_ROOT = "/home/ybkim/workspace/imc/imc_freertos_app_m33"
+NVM_RESET_BIN = f"{WORKSPACE_ROOT}/imc/utils/nvm_reset.elf"
+OPENOCD_SCRIPT = f"{WORKSPACE_ROOT}/imc_freertos_app_m33.cfg"
+
+def main():
+    pps = PPS_E36311A()
+    config = get_default_build_config()
+
+    benchmarks = [
+        "vBasicMath",
+        "vCrc",
+        "vFFT",
+        "vSha",
+        "vStringSearch",
+        "vMatMul",
+        "vConv2d",
+        "vAes",
+    ]
+    benchmarks = ["vSha"]
+
+    for benchmark in benchmarks:
+        all_records = []
+        bench_repeat_count = config.bench_repeat_count_small[benchmark]
+
+        config.bench_name = benchmark
+        config.bench_repeat_count = bench_repeat_count
+
+        pps.set_voltage(3.3, 1)
+        pps.set_current(0.1, 1)
+        pps.output_on(1)
+
+        env = TestEnv(WORKSPACE_ROOT, NVM_RESET_BIN, OPENOCD_SCRIPT)
+
+        with tempfile.TemporaryDirectory() as build_dir:
+            binary = env.build_binary(config, build_dir)
+            env.clear_nvm_and_load_binary(binary, resume=False)
+
+        pps.set_current(0.015, 1)
+        time.sleep(1)
+
+        env.resume_board(terminate=True)
+        total_iterations = 10
+        watcher = SerialWatcher(benchmark, total_iterations)
+        records = watcher.run()
+        for record in records:
+            record.update(
+                {
+                    # "loop_pass_count": loop_pass_count,
+                }
+            )
+            all_records.append(record)
+        df = pd.DataFrame(all_records)
+        print(df)
+        save_records(benchmark, df)
+    pps.output_off(1)
+
+
+def get_default_build_config():
+    config = BuildConfigM33()
+    config.bench_name = "vBasicMath"
+    config.insert_compiler_checkpoints = True
+    config.enable_extension = True
+    config.use_checkpoint_pass_counter = False
+    config.checkpoint_pass_count = 100
+    config.use_checkpoint_voltage_check = True
+    config.bench_infinite_loop = True
+    config.split_loop = False
+    config.enable_static_loop_pass_count = False
+    config.loop_pass_count = 0
+    config.enable_adaptive_loop_pass_count = False
+    config.max_loop_ids = 30
+    config.print_recovery_message = True
+    return config
+
+
+def save_records(bench_name, df):
+    with open(f"output/{bench_name}.pickle", "wb") as f:
+        pickle.dump(df, f)
+
+
+if __name__ == "__main__":
+    main()

+ 8 - 0
imc_extension.cmake

@@ -2,6 +2,8 @@ set(IMC_BENCH_NAME "vAes" CACHE STRING "")
 set(IMC_BENCH_INFINITE_LOOP 0 CACHE BOOL "")
 set(IMC_BENCH_INFINITE_LOOP 0 CACHE BOOL "")
 set(IMC_PRINT_RECOVERY_MESSAGE 0 CACHE BOOL "")
 set(IMC_PRINT_RECOVERY_MESSAGE 0 CACHE BOOL "")
 set(IMC_ENABLE_STATIC_LOOP_PASS_COUNT 1 CACHE BOOL "")
 set(IMC_ENABLE_STATIC_LOOP_PASS_COUNT 1 CACHE BOOL "")
+set(IMC_ENABLE_ADAPTIVE_LOOP_PASS_COUNT 0 CACHE BOOL "")
+set(IMC_MAX_LOOP_IDS 1 CACHE STRING "")
 set(IMC_LOOP_PASS_COUNT 10 CACHE BOOL "")
 set(IMC_LOOP_PASS_COUNT 10 CACHE BOOL "")
 set(IMC_BENCH_REPEAT_COUNT 1 CACHE BOOL "")
 set(IMC_BENCH_REPEAT_COUNT 1 CACHE BOOL "")
 
 
@@ -10,6 +12,10 @@ if(NOT IMC_BENCH_NAME IN_LIST AVAILABLE_BENCHES)
     message( FATAL_ERROR "incorrect benchmark name: ${IMC_BENCH_NAME}")
     message( FATAL_ERROR "incorrect benchmark name: ${IMC_BENCH_NAME}")
 endif()
 endif()
 
 
+if(IMC_ENABLE_STATIC_LOOP_PASS_COUNT AND IMC_ENABLE_ADAPTIVE_LOOP_PASS_COUNT)
+    mesage( FATAL_ERROR "static and adaptive loop pass count are enalbed simultaneously")
+endif()
+
 add_compile_definitions(imcBENCH_NAME=${IMC_BENCH_NAME})
 add_compile_definitions(imcBENCH_NAME=${IMC_BENCH_NAME})
 add_compile_definitions(imcBENCH_REPEAT_COUNT=${IMC_BENCH_REPEAT_COUNT})
 add_compile_definitions(imcBENCH_REPEAT_COUNT=${IMC_BENCH_REPEAT_COUNT})
 if(IMC_BENCH_INFINITE_LOOP)
 if(IMC_BENCH_INFINITE_LOOP)
@@ -155,6 +161,8 @@ function(compile_imc_files)
         list(APPEND IMC_OPT_PASSES "imc-loop-opt")
         list(APPEND IMC_OPT_PASSES "imc-loop-opt")
         list(APPEND PLUGINS /home/ybkim/workspace/imc/loop_duplication/build/lib/libImcLoopOpt.so)
         list(APPEND PLUGINS /home/ybkim/workspace/imc/loop_duplication/build/lib/libImcLoopOpt.so)
         add_compile_definitions(imcENABLE_STATIC_LOOP_PASS_COUNT=${IMC_ENABLE_STATIC_LOOP_PASS_COUNT})
         add_compile_definitions(imcENABLE_STATIC_LOOP_PASS_COUNT=${IMC_ENABLE_STATIC_LOOP_PASS_COUNT})
+        add_compile_definitions(imcENABLE_ADAPTIVE_LOOP_PASS_COUNT=${IMC_ENABLE_ADAPTIVE_LOOP_PASS_COUNT})
+        add_compile_definitions(imcMAX_LOOP_IDS=${IMC_MAX_LOOP_IDS})
         add_compile_definitions(imcLOOP_PASS_COUNT=${IMC_LOOP_PASS_COUNT})
         add_compile_definitions(imcLOOP_PASS_COUNT=${IMC_LOOP_PASS_COUNT})
     endif()
     endif()
 
 

+ 4 - 1
setup_build_dir.py

@@ -17,7 +17,10 @@ config.use_checkpoint_pass_counter = False
 config.use_checkpoint_voltage_check = True
 config.use_checkpoint_voltage_check = True
 config.bench_infinite_loop = True
 config.bench_infinite_loop = True
 config.split_loop = True
 config.split_loop = True
-config.loop_pass_count = 10
+config.loop_pass_count = 30
+config.enable_static_loop_pass_count = False
+config.enable_adaptive_loop_pass_count = True
+config.max_loop_ids = 30
 config.bench_repeat_count = config.bench_repeat_count_small[config.bench_name]
 config.bench_repeat_count = config.bench_repeat_count_small[config.bench_name]
 
 
 env = TestEnv(WORKSPACE_ROOT, NVM_RESET_BIN, OPENOCD_SCRIPT)
 env = TestEnv(WORKSPACE_ROOT, NVM_RESET_BIN, OPENOCD_SCRIPT)