add micro bench for interrupt times

This commit is contained in:
Alwin Berger 2023-02-26 22:44:59 +01:00
parent 99fc3ddfd2
commit 1e37657385
5 changed files with 237 additions and 14 deletions

View File

@ -98,6 +98,11 @@ ifeq ($(BRANCHLESS_DEMO), 1)
SOURCE_FILES += main_micro_branchless.c SOURCE_FILES += main_micro_branchless.c
CFLAGS := -DmainCREATE_BRANCHLESS_DEMO=1 CFLAGS := -DmainCREATE_BRANCHLESS_DEMO=1
else
ifeq ($(INT_DEMO), 1)
SOURCE_FILES += main_micro_int.c
CFLAGS := -DmainCREATE_INT_DEMO=1
else else
SOURCE_FILES += main_blinky.c SOURCE_FILES += main_blinky.c
@ -111,6 +116,7 @@ endif
endif endif
endif endif
endif endif
endif
DEFINES := -DQEMU_SOC_MPS2 -DHEAP3 DEFINES := -DQEMU_SOC_MPS2 -DHEAP3

View File

@ -6,7 +6,9 @@ volatile long _NONSENSE_VAR = 0;
#define NS_PER_INS (1000000000 / configCPU_CLOCK_HZ) // 20MHz #define NS_PER_INS (1000000000 / configCPU_CLOCK_HZ) // 20MHz
#define INS_PER_LOOP 5 // got this multiplier by testing with the goal of getting a 100 ms or 100 tick period #define INS_PER_LOOP 5 // got this multiplier by testing with the goal of getting a 100 ms or 100 tick period
#define INS_PER_PRINT 117 // got this multiplier by testing with the goal of getting a 100 ms or 100 tick period, 2 digits #define INS_PER_PRINT 117 // got this multiplier by testing with the goal of getting a 100 ms or 100 tick period, 2 digits
#define GLOBAL_WCET_MULT 16 // Multiplier to increase all waiting periods to make the schedule more tight an force preemptions #ifndef GLOBAL_WCET_MULT
#define GLOBAL_WCET_MULT 1 // Multiplier to increase all waiting periods to make the schedule more tight an force preemptions
#endif
#define WASTE_TIME(X) for (int i=0; i<=((X*GLOBAL_WCET_MULT)/(NS_PER_INS*INS_PER_LOOP)); i++) {_NONSENSE_VAR+=i;} #define WASTE_TIME(X) for (int i=0; i<=((X*GLOBAL_WCET_MULT)/(NS_PER_INS*INS_PER_LOOP)); i++) {_NONSENSE_VAR+=i;}
#define PRINT_TIME(X,Y) for (int i=0; i<=((X*GLOBAL_WCET_MULT)/((NS_PER_INS*INS_PER_PRINT))); i++) {puts(Y);} #define PRINT_TIME(X,Y) for (int i=0; i<=((X*GLOBAL_WCET_MULT)/((NS_PER_INS*INS_PER_PRINT))); i++) {puts(Y);}
// #define PRINT_TIME(X,Y) WASTE_TIME(X) // #define PRINT_TIME(X,Y) WASTE_TIME(X)

View File

@ -95,8 +95,12 @@ int main()
{ {
main_branchless(); main_branchless();
} }
#elif ( mainCREATE_INT_DEMO == 1 )
{
main_micro_int();
}
#else #else
{ {
#error "Invalid Selection...\nPlease Select a Demo application from the main command" #error "Invalid Selection...\nPlease Select a Demo application from the main command"
} }

View File

@ -0,0 +1,207 @@
/*
* FreeRTOS V202111.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#include <FreeRTOS.h>
#include <task.h>
#include <queue.h>
#include <stdio.h>
#include <semphr.h>
#include "arbitrary_loads.c"
/*
Interrupt Demo without priority inheritance
Async | I
A | RxxP xxxVD
B | RxxxD
C RxxxPx xx xxxV xxxD
*/
// #undef PRINT_TIME
// #define PRINT_TIME(X,Y) WASTE_TIME(X)
#define WCET_CLAMP(X, LB, UB, LABEL) PRINT_TIME(UB,LABEL)
__attribute__((noinline)) static void trigger_Qemu_break( void )
{
puts("Trigger");
}
// Begin Input Stuff
volatile unsigned char FUZZ_INPUT[4096] = {0xa,0xb,0xc,0xd,0xe,0xf};
volatile uint32_t FUZZ_LENGTH = 32;
volatile uint32_t FUZZ_POINTER = 0;
static unsigned char fuzz_char_next(void) {
// printf("Get next Input from %lx \n",FUZZ_INPUT);
if (FUZZ_POINTER < FUZZ_LENGTH) {
FUZZ_POINTER++;
// printf("Input no. %d %x\n",FUZZ_POINTER-1,FUZZ_INPUT[FUZZ_POINTER-1]);
return FUZZ_INPUT[FUZZ_POINTER-1];
} else {
// puts("End of Input");
// Exausted inputs early
trigger_Qemu_break();
}
}
static uint16_t fuzz_short_next(void) {
unsigned char field[2];
field[0]=fuzz_char_next();
field[1]=fuzz_char_next();
uint16_t* sf = (uint16_t*) field;
return *sf;
}
static uint32_t fuzz_long_next(void) {
unsigned char field[4];
field[0]=fuzz_char_next();
field[1]=fuzz_char_next();
field[2]=fuzz_char_next();
field[3]=fuzz_char_next();
uint32_t* sf = (uint32_t*) field;
return *sf;
}
// End Input Stuff
static void prvReplicaA( void * pvParameters );
static void prvReplicaB( void * pvParameters );
static void prvReplicaC( void * pvParameters );
static void prvSpor( void * pvParameters );
#define mainREPLICA_SPOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 6 )
#define mainREPLICA_A_TASK_PRIORITY ( tskIDLE_PRIORITY + 5 )
#define mainREPLICA_B_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
#define mainREPLICA_C_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
// Handles for direct messages
static TaskHandle_t xReplA = NULL;
static TaskHandle_t xReplB = NULL;
static TaskHandle_t xReplC = NULL;
static SemaphoreHandle_t xSemaphoreAC;
void main_micro_int( void )
{
xSemaphoreAC = xSemaphoreCreateBinary();
xSemaphoreGive(xSemaphoreAC);
if( xSemaphoreAC != NULL )
{
/* Start the two tasks as described in the comments at the top of this
* file. */
xTaskCreate( prvReplicaA, /* The function that implements the task. */
"ReplA", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
NULL, /* The parameter passed to the task - not used in this case. */
mainREPLICA_A_TASK_PRIORITY, /* The priority assigned to the task. */
&xReplA ); /* The task handle is not required, so NULL is passed. */
xTaskCreate( prvReplicaB, /* The function that implements the task. */
"ReplB", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
NULL, /* The parameter passed to the task - not used in this case. */
mainREPLICA_B_TASK_PRIORITY, /* The priority assigned to the task. */
&xReplB ); /* The task handle is not required, so NULL is passed. */
xTaskCreate( prvReplicaC, /* The function that implements the task. */
"ReplC", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
NULL, /* The parameter passed to the task - not used in this case. */
mainREPLICA_C_TASK_PRIORITY, /* The priority assigned to the task. */
&xReplC ); /* The task handle is not required, so NULL is passed. */
xTaskCreate( prvSpor, /* The function that implements the task. */
"Spor", /* The text name assigned to the task - for debug only as it is not used by the kernel. */
configMINIMAL_STACK_SIZE, /* The size of the stack to allocate to the task. */
NULL, /* The parameter passed to the task - not used in this case. */
mainREPLICA_SPOR_TASK_PRIORITY, /* The priority assigned to the task. */
NULL ); /* The task handle is not required, so NULL is passed. */
/* Start the tasks and timer running. */
vTaskStartScheduler();
}
/* If all is well, the scheduler will now be running, and the following
* line will never be reached. If the following line does execute, then
* there was insufficient FreeRTOS heap memory available for the Idle and/or
* timer tasks to be created. See the memory management section on the
* FreeRTOS web site for more details on the FreeRTOS heap
* http://www.freertos.org/a00111.html. */
for( ; ; )
{
}
}
static void prvReplicaA( void * pvParameters )
{
TickType_t xLastWakeTime = xTaskGetTickCount();
vTaskDelayUntil( &xLastWakeTime, 5 / portTICK_PERIOD_MS );
puts("A Ready");
while (1)
{
xSemaphoreTake(xSemaphoreAC, portMAX_DELAY);
uint32_t x = fuzz_long_next();
WCET_CLAMP(x>>5,0, 5 * 1000 * 1000, "A ")
xSemaphoreGive(xSemaphoreAC);
trigger_Qemu_break();
while (1) {
}
}
}
static void prvReplicaB( void * pvParameters )
{
while (1)
{
ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
uint32_t x = fuzz_long_next();
WCET_CLAMP(x>>5,0, 5 * 1000 * 1000, "B ")
}
}
static void prvReplicaC( void * pvParameters )
{
while (1)
{
xSemaphoreTake(xSemaphoreAC, portMAX_DELAY);
uint32_t x = fuzz_long_next();
WCET_CLAMP(x>>5, 6 * 1000 * 1000, 10 * 1000 * 1000, "C ")
xSemaphoreGive(xSemaphoreAC);
}
}
static void prvSpor( void * pvParameters )
{
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = 7 / portTICK_PERIOD_MS;
vTaskDelayUntil( &xLastWakeTime, xFrequency );
while (1)
{
puts("Fire");
xTaskNotifyGive(xReplB);
vTaskDelayUntil( &xLastWakeTime, xFrequency * 10000 );
}
}
void isr_starter( void )
{
puts("Fire");
xTaskNotifyGive(xReplB);
}
/*-----------------------------------------------------------*/

View File

@ -41,8 +41,8 @@ prvVoterTask will wait on ReplicateA&B
If they disagree ReplicateC will be started by mutex. If they disagree ReplicateC will be started by mutex.
If all the Replicates disagree now the sampler will be engaged once more If all the Replicates disagree now the sampler will be engaged once more
*/ */
// include tacle benches
#define GLOBAL_WCET_MULT 16 // Multiplier to increase all waiting periods to make the schedule more tight an force preemptions
#include "arbitrary_loads.c" #include "arbitrary_loads.c"
__attribute__((noinline)) static void trigger_Qemu_break( void ) __attribute__((noinline)) static void trigger_Qemu_break( void )
@ -439,18 +439,21 @@ static void prvTask1129( void * pvParameters ) {
for( ;; ){ for( ;; ){
// if (--period_counter==0) {puts("End");} // if (--period_counter==0) {puts("End");}
// Actions -------------------------------------- // Actions --------------------------------------
// Exectime: f(x,y) = if !y ? 80000+x : x (<40k) // Exectime: f(x,y) = if y && rng(x) ? c1+x : c2+x
// Output: g(x) = x % 4 // Output: g(x) = y && rng(x)
// longmax - shortmax: 69505
// most likely long case, which causes a short case in next task
uint32_t x = (uint32_t)fuzz_short_next(); uint32_t x = (uint32_t)fuzz_short_next();
int y = ulTaskNotifyTake(pdFALSE, 0); int y = ulTaskNotifyTake(pdFALSE, 0);
int do_short_run = y && CHANCE_1_IN_POWOF2(x, 3);
int torun = 0; int torun = 0;
if (!y) { if (do_short_run) {
torun = 80000 + x; torun = 10000 + x;
} else { } else {
torun = x; torun = 80000 + x;
} }
WCET_CLAMP(torun, 0, 145040, TASK_1129_MESSAGE) WCET_CLAMP(torun, 0, 145040, TASK_1129_MESSAGE)
xTaskNotify(xTask416, x % 4, eSetValueWithOverwrite); xTaskNotify(xTask416, do_short_run, eSetValueWithOverwrite);
// --------------------------------------------- // ---------------------------------------------
vTaskDelayUntil( &xLastWakeTime, xFrequency );} vTaskDelayUntil( &xLastWakeTime, xFrequency );}
} }
@ -461,16 +464,17 @@ static void prvTask416( void * pvParameters ) {
const TickType_t xFrequency = 10 / portTICK_PERIOD_MS; const TickType_t xFrequency = 10 / portTICK_PERIOD_MS;
for( ;; ){ for( ;; ){
// Actions -------------------------------------- // Actions --------------------------------------
// Exectime: f(x,y) = if y == 3 ? c-x : c+x // Exectime: f(x,y) = if y ? c1+2*x : c2-x
// longmax - shortmax: 86955
uint32_t x = (uint32_t)fuzz_short_next(); uint32_t x = (uint32_t)fuzz_short_next();
int y = ulTaskNotifyTake(pdFALSE, 0); int y = ulTaskNotifyTake(pdFALSE, 0);
int torun = 0; int torun = 0;
if (y==3) { if (y) {
torun = 70000 + x; torun = x*3;
} else { } else {
torun = 70000 - x; torun = 40000 - CLAMP_CEILING(x, 40000);
} }
PRINT_TIME(126955, TASK_416_MESSAGE) WCET_CLAMP(torun, 10000, 126955, TASK_416_MESSAGE)
// --------------------------------------------- // ---------------------------------------------
vTaskDelayUntil( &xLastWakeTime, xFrequency );} vTaskDelayUntil( &xLastWakeTime, xFrequency );}
} }