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
CFLAGS := -DmainCREATE_BRANCHLESS_DEMO=1
else
ifeq ($(INT_DEMO), 1)
SOURCE_FILES += main_micro_int.c
CFLAGS := -DmainCREATE_INT_DEMO=1
else
SOURCE_FILES += main_blinky.c
@ -111,6 +116,7 @@ endif
endif
endif
endif
endif
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 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 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 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)

View File

@ -95,8 +95,12 @@ int main()
{
main_branchless();
}
#elif ( mainCREATE_INT_DEMO == 1 )
{
main_micro_int();
}
#else
{
#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 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"
__attribute__((noinline)) static void trigger_Qemu_break( void )
@ -439,18 +439,21 @@ static void prvTask1129( void * pvParameters ) {
for( ;; ){
// if (--period_counter==0) {puts("End");}
// Actions --------------------------------------
// Exectime: f(x,y) = if !y ? 80000+x : x (<40k)
// Output: g(x) = x % 4
// Exectime: f(x,y) = if y && rng(x) ? c1+x : c2+x
// 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();
int y = ulTaskNotifyTake(pdFALSE, 0);
int do_short_run = y && CHANCE_1_IN_POWOF2(x, 3);
int torun = 0;
if (!y) {
torun = 80000 + x;
if (do_short_run) {
torun = 10000 + x;
} else {
torun = x;
torun = 80000 + x;
}
WCET_CLAMP(torun, 0, 145040, TASK_1129_MESSAGE)
xTaskNotify(xTask416, x % 4, eSetValueWithOverwrite);
xTaskNotify(xTask416, do_short_run, eSetValueWithOverwrite);
// ---------------------------------------------
vTaskDelayUntil( &xLastWakeTime, xFrequency );}
}
@ -461,16 +464,17 @@ static void prvTask416( void * pvParameters ) {
const TickType_t xFrequency = 10 / portTICK_PERIOD_MS;
for( ;; ){
// 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();
int y = ulTaskNotifyTake(pdFALSE, 0);
int torun = 0;
if (y==3) {
torun = 70000 + x;
if (y) {
torun = x*3;
} 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 );}
}