From a1393d2e1400f1024a71e5b731ca16aba758117b Mon Sep 17 00:00:00 2001 From: Alwin Berger Date: Wed, 15 Mar 2023 13:56:55 +0100 Subject: [PATCH] fine-tune waters + simulate worst-case --- .../CORTEX_M3_MPS2_QEMU_GCC/main_waters.c | 76 ++++++++++++------- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_waters.c b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_waters.c index 542d7558..d4d1b030 100644 --- a/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_waters.c +++ b/FreeRTOS/Demo/CORTEX_M3_MPS2_QEMU_GCC/main_waters.c @@ -51,14 +51,18 @@ __attribute__((noinline)) static void trigger_Qemu_break( void ) while (1) { } } -// #define DEBUG_WCET(A) {A} +// if this macro is set, the code will be modified to produce the worst case +#define DEBUG_WCET(A) {A} // #define WCET_END(A) #define WCET_END(A) {A} #ifdef DEBUG_WCET - #define WCET_CLAMP(X, LB, UB, LABEL) PRINT_TIME(UB,LABEL) + #define DEBUG_VAL(X,D) (D) + // #define WCET_CLAMP(X, LB, UB, LABEL) PRINT_TIME(UB,LABEL) + #define WCET_CLAMP(X, LB, UB, LABEL) PRINT_TIME(CLAMP(X,LB,UB),LABEL) #else + #define DEBUG_VAL(X,D) (X) #define WCET_CLAMP(X, LB, UB, LABEL) PRINT_TIME(CLAMP(X,LB,UB),LABEL) #define DEBUG_WCET(A) #endif @@ -279,10 +283,11 @@ static void prvTask31( void * pvParameters ) { // Actions -------------------------------------- // Exectime: f(x) = x // Output: g(x) = x % 2 - uint16_t x = fuzz_short_next(); + volatile uint16_t x = fuzz_short_next(); + DEBUG_WCET(x=48940;) WCET_CLAMP(x, 0, 48940, TASK_31_MESSAGE) WCET_END({trigger_Qemu_break();}) - xTaskNotify(xTask78, x % 2, eSetValueWithOverwrite); + xTaskNotify(xTask78, DEBUG_VAL(x % 2, 1), eSetValueWithOverwrite); // --------------------------------------------- vTaskDelayUntil( &xLastWakeTime, xFrequency );}// Wait for the next cycle. } @@ -297,15 +302,15 @@ static void prvTask78( void * pvParameters ) { // Output: g(x,y) = y * (x % 4) uint16_t x = fuzz_short_next(); int y = ulTaskNotifyTake(pdFALSE, 0); - int torun = 6035; + volatile int torun = 6035; if (y > 0) { torun += 20000; } - if (CHANCE_1_IN_POWOF2(x, 5)) { + if (DEBUG_VAL(CHANCE_1_IN_POWOF2(x, 5), 1)) { torun += 50000; } WCET_CLAMP(torun, 0, 76035, TASK_78_MESSAGE) - xTaskNotify(xTask400, y * (x % 4), eSetValueWithOverwrite); + xTaskNotify(xTask400, DEBUG_VAL(y * (x % 4), 2), eSetValueWithOverwrite); // --------------------------------------------- vTaskDelayUntil( &xLastWakeTime, xFrequency );} } @@ -319,11 +324,12 @@ static void prvTask400( void * pvParameters ) { // Exectime: f(x,y) = rng(x)*y*c or (rng(x) % 1000) uint32_t x = fuzz_long_next(); int y = ulTaskNotifyTake(pdFALSE, 0); - int torun = 0; - if (y == 2 && CHANCE_1_IN_POWOF2(x, 2)) { + volatile int torun = 0; + if (y == 2 && DEBUG_VAL(CHANCE_1_IN_POWOF2(x, 2), 1)) { torun = 1765; } else { torun = RNG_FROM(x) % 1000; + DEBUG_WCET(torun=999;) } WCET_CLAMP(torun, 0, 1765, TASK_400_MESSAGE) // --------------------------------------------- @@ -339,14 +345,15 @@ static void prvTask397( void * pvParameters ) { for( ;; ){ // Exectime: f(x) = x // Output: g(x) = x % 2 - uint16_t x = fuzz_short_next(); + volatile uint16_t x = fuzz_short_next(); + DEBUG_WCET(x=5830;) WCET_CLAMP(x, 0, 5830, TASK_397_MESSAGE); - xTaskNotify(xTask90, x & 0x1, eSetValueWithOverwrite); + xTaskNotify(xTask90, DEBUG_VAL(x & 0x1, 0), eSetValueWithOverwrite); // 3 different activation strategies ------------- // activate sporadically from interrupts - ulTaskNotifyTake(pdTRUE,portMAX_DELAY); + // ulTaskNotifyTake(pdTRUE,portMAX_DELAY); // activate with worst possible frequency (700us, but tick resolution is too low) - // vTaskDelayUntil( &xLastWakeTime, xFrequency ); + vTaskDelayUntil( &xLastWakeTime, xFrequency ); // wait pseudo random many ticks // vTaskDelayUntil( &xLastWakeTime, CLAMP(RNG, 1, 100) / portTICK_PERIOD_MS ); } @@ -361,7 +368,8 @@ static void prvTask90( void * pvParameters ) { // Exectime: f(x) = c + x // Output: g(x) = x % 4 int y = ulTaskNotifyTake(pdFALSE, 0); - uint16_t x = fuzz_short_next(); + volatile uint16_t x = fuzz_short_next(); + DEBUG_WCET(x=20048;) int torun = 0; if (y) { torun = CLAMP(x, 5000, 10000); @@ -369,7 +377,7 @@ static void prvTask90( void * pvParameters ) { torun = CLAMP(x, 0, 20045); } WCET_CLAMP(torun, 0, 20045, TASK_90_MESSAGE) - xTaskNotify(xTask1107, x % 4, eSetValueWithOverwrite); + xTaskNotify(xTask1107, DEBUG_VAL(x % 4, 0), eSetValueWithOverwrite); // --------------------------------------------- vTaskDelayUntil( &xLastWakeTime, xFrequency );} } @@ -381,7 +389,8 @@ static void prvTask1107( void * pvParameters ) { for( ;; ){ // Actions -------------------------------------- // Exectime: f(x) = c - x*y - uint16_t x = fuzz_short_next(); + volatile uint16_t x = fuzz_short_next(); + DEBUG_WCET(x=0;) int y = ulTaskNotifyTake(pdFALSE, 0); int torun = 76865-((int)x)*y; WCET_CLAMP(torun, 10000, 76865, TASK_1107_MESSAGE) @@ -402,9 +411,10 @@ static void prvTask579( void * pvParameters ) { // Exectime: f(x) = x>>8 & 0x0fff // Output: g(x) = x % 8 uint32_t x = fuzz_long_next(); - int torun = (x>>8) & 0x0fff; + volatile int torun = (x>>8) & 0x0fff; + DEBUG_WCET(torun = 0x0fff;) WCET_CLAMP(torun, 500, 2460, TASK_579_MESSAGE) - xTaskNotify(xTask1009, x % 8, eSetValueWithOverwrite); + xTaskNotify(xTask1009, DEBUG_VAL(x % 8, 0), eSetValueWithOverwrite); // --------------------------------------------- vTaskDelayUntil( &xLastWakeTime, xFrequency );} } @@ -419,14 +429,15 @@ static void prvTask1009( void * pvParameters ) { // Output: g(x) = x % 8 == y uint16_t x = fuzz_short_next(); int y = ulTaskNotifyTake(pdFALSE, 0); - int torun = 0; + volatile int torun = 0; if (x % 8 == y) { torun = 40000 + x; } else { torun = CLAMP(x, 0, 40000); } + DEBUG_WCET(torun = 51485;) WCET_CLAMP(torun, 0, 51485, TASK_1009_MESSAGE) - xTaskNotify(xTask1129, x % 8 == y, eSetValueWithOverwrite); + xTaskNotify(xTask1129, DEBUG_VAL(x % 8 == y, 1), eSetValueWithOverwrite); // --------------------------------------------- vTaskDelayUntil( &xLastWakeTime, xFrequency );} } @@ -441,14 +452,19 @@ static void prvTask1129( void * pvParameters ) { // Actions -------------------------------------- // Exectime: f(x,y) = if y && rng(x) ? c1+x : c2+x // Output: g(x) = y && rng(x) - // longmax - shortmax: 69505 + // longmax - shortmax: 39505 // most likely long case, which causes a short case in next task - uint32_t x = (uint32_t)fuzz_short_next(); + volatile uint32_t x = (uint32_t)fuzz_short_next(); int y = ulTaskNotifyTake(pdFALSE, 0); - int do_short_run = y && CHANCE_1_IN_POWOF2(x, 3); + DEBUG_WCET( + static char flag=0; + if (flag++ == 0 | flag == 5 | flag == 8 | flag == 9) {x = 65529;} + else {x = 0xffff;} + ) + volatile int do_short_run = (y + CHANCE_1_IN_POWOF2(x, 5)) == 1; // XOR int torun = 0; - if (do_short_run) { - torun = 10000 + x; + if (do_short_run > 0) { + torun = 40000 + x; } else { torun = 80000 + x; } @@ -465,14 +481,16 @@ static void prvTask416( void * pvParameters ) { for( ;; ){ // Actions -------------------------------------- // Exectime: f(x,y) = if y ? c1+2*x : c2-x - // longmax - shortmax: 86955 - uint32_t x = (uint32_t)fuzz_short_next(); + // longmax - shortmax: 76955 + volatile uint32_t x = (uint32_t)fuzz_short_next(); int y = ulTaskNotifyTake(pdFALSE, 0); - int torun = 0; + volatile int torun = 0; if (y) { + DEBUG_WCET(x=0xffff;) torun = x*3; } else { - torun = 40000 - CLAMP_CEILING(x, 40000); + DEBUG_WCET(x=0;) + torun = 50000 - CLAMP_CEILING(x, 50000); } WCET_CLAMP(torun, 10000, 126955, TASK_416_MESSAGE) // ---------------------------------------------