From 71cf99b48798f3eb85ec0fc92d599b4740459098 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Mon, 22 Jul 2024 08:57:07 +0200 Subject: [PATCH 01/67] correction of Python interpreter in findpackage() not supported by later versions of Cmake --- src/wmc_tool/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wmc_tool/CMakeLists.txt b/src/wmc_tool/CMakeLists.txt index 858ee70..465c5e1 100644 --- a/src/wmc_tool/CMakeLists.txt +++ b/src/wmc_tool/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.5) project(wmc_tool) include(CTest) @@ -10,8 +10,8 @@ if(WIN32) ) endif() -add_executable(wmc_tool c_parser.cpp output.cpp text_utils.cpp wmc_tool.cpp) -find_package(PythonInterp) +add_executable(wmc_tool parsing_defs.h c_parser.h c_parser.cpp output.h output.cpp text_utils.h text_utils.cpp constants.h wmc_tool.h wmc_tool.cpp) +find_package (Python COMPONENTS Interpreter) # Testing file(TO_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/test_data TEST_DIR) From d915d2c1077f637cc0ea8ed933aea7ee26d78668 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Mon, 22 Jul 2024 08:59:13 +0200 Subject: [PATCH 02/67] addition of --skip-cmplx-instrumentation command-line option allowing skipping complexity instrumentation in function bodies --- src/wmc_tool/HISTORY.md | 4 +++ src/wmc_tool/c_parser.cpp | 64 ++++++++++++++++++++++++--------------- src/wmc_tool/c_parser.h | 2 +- src/wmc_tool/wmc_tool.cpp | 19 ++++++++++-- src/wmc_tool/wmc_tool.h | 2 +- 5 files changed, 61 insertions(+), 30 deletions(-) diff --git a/src/wmc_tool/HISTORY.md b/src/wmc_tool/HISTORY.md index 456511f..988cc26 100644 --- a/src/wmc_tool/HISTORY.md +++ b/src/wmc_tool/HISTORY.md @@ -66,4 +66,8 @@ * export information about all dynamic allocations/de-allocations occuring during the runtime of the codec to a `.csv` file * added an exemplary Python script `mem_analysis.py` for graphical analysis and profiling of dynamic memory alloations based on the generated `.csv` file * added support for counting complexity and PROM size of BASOP operations and BASOP functions within floating-point source code + +## v1.5.1 + + * added the -s (--skip_cmplx_instrumentation) command-line option, which avoids the instrumentation of function bodies. The func_start_ and return_ keywords, along with the remaining functionality, remain unchanged. \ No newline at end of file diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 79f1101..95ccf5e 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -4667,7 +4667,8 @@ static TOOL_ERROR Instrument_Switch( * Instrument_Keywords *-------------------------------------------------------------------*/ static TOOL_ERROR Instrument_Keywords( - Parse_Context_def *ParseCtx_ptr ) + Parse_Context_def *ParseCtx_ptr, + bool skip_cmplx_instrum) { TOOL_ERROR ErrCode = NO_ERR; @@ -4696,7 +4697,7 @@ static TOOL_ERROR Instrument_Keywords( item_type = ParseRec_ptr->item_type; /* Skipped? */ - unless( item_type & ITEM_SKIPPED ) + if( !(item_type & ITEM_SKIPPED) ) { /* No */ /* In Skipped or Non-Instrumented Region? */ if ( Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED | ITEM_INSTRUMENTATION_OFF ) < 0 @@ -4704,13 +4705,21 @@ static TOOL_ERROR Instrument_Keywords( || ( item_type == ITEM_KEYWORD_RETURN /* 'return not' Instrumented in Skipped Regions */ && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED ) < 0 - && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_FUNC_BLOCK ) < 0 && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_FUNC_BLOCK | ITEM_FUNC_MATH ) < 0 && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_FUNC_BLOCK | ITEM_FUNC_SYSTEM ) < 0 ) ) + && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_FUNC_BLOCK ) < 0 + && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_FUNC_BLOCK | ITEM_FUNC_MATH ) < 0 + && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_FUNC_BLOCK | ITEM_FUNC_SYSTEM ) < 0 ) ) { /* No */ /* Instrument After (by default) */ ptr = ParseRec_ptr->item_end; - /* Is it a 'while' that is part of a 'do' Block? */ - /* Insert Instrumentation Character */ + if (skip_cmplx_instrum && item_type != ITEM_KEYWORD_RETURN) + { + /* skip the instrumentation if the user specified so on the command-line */ + /* with the exception of the 'return' keywords */ + continue; + } + + /* Insert Instrumentation Character '_' */ if ( ( ErrCode = Add_Insertion( &ParseCtx_ptr->InsertTbl, ptr, WORD_INSTRUMENT_STRING ) ) != NO_ERR ) { goto ret; @@ -4719,29 +4728,28 @@ static TOOL_ERROR Instrument_Keywords( /* Is it a 'while'? Auto Instrumentation Macro for 'while' in a 'do' Block can handle multiple Condition. */ - if ( item_type == ITEM_KEYWORD_WHILE - /* 'while' from 'do/while' now Needs Extra () for Multiple Condition*/ - || item_type == ITEM_KEYWORD_WHILE2 - ) + if (item_type == ITEM_KEYWORD_WHILE + /* 'while' from 'do/while' now Needs Extra () for Multiple Condition*/ + || item_type == ITEM_KEYWORD_WHILE2 ) { /* Yes */ /* Advance to Parameters Record */ ParseRec_ptr++; /* More than one Condition? */ - if ( Count_Args( ParseRec_ptr->item_start, - ParseRec_ptr->item_end - 1, - ParseTbl_ptr ) > 1 ) + if (Count_Args(ParseRec_ptr->item_start, + ParseRec_ptr->item_end - 1, + ParseTbl_ptr) > 1) { /* Yes */ /* Must Add Extra () */ - if ( ( ErrCode = Add_Insertion( &ParseCtx_ptr->InsertTbl, - ParseRec_ptr->item_start, - "(" ) ) != NO_ERR ) + if ((ErrCode = Add_Insertion(&ParseCtx_ptr->InsertTbl, + ParseRec_ptr->item_start, + "(")) != NO_ERR) { goto ret; } - if ( ( ErrCode = Add_Insertion( &ParseCtx_ptr->InsertTbl, - ParseRec_ptr->item_end, - ")" ) ) != NO_ERR ) + if ((ErrCode = Add_Insertion(&ParseCtx_ptr->InsertTbl, + ParseRec_ptr->item_end, + ")")) != NO_ERR) { goto ret; } @@ -8112,7 +8120,9 @@ TOOL_ERROR Include_Header( TOOL_ERROR Instrument( Parse_Context_def *ParseCtx_ptr, - bool instrument_ROM ) + bool instrument_ROM, + bool skip_cmplx_instrum +) { TOOL_ERROR ErrCode = NO_ERR; @@ -8122,6 +8132,7 @@ TOOL_ERROR Instrument( ErrCode = Internal_Error( __FUNCTION__ ); goto ret; } + /* Set State Failure (by default) */ ParseCtx_ptr->State = INS_FAILED; @@ -8149,7 +8160,7 @@ TOOL_ERROR Instrument( /* Erase Function Call Table */ ParseCtx_ptr->FctCallTbl.Size = 0; - if ( ( ErrCode = Instrument_Calls( ParseCtx_ptr ) ) != NO_ERR ) + if ((ErrCode = Instrument_Calls(ParseCtx_ptr)) != NO_ERR) { goto ret; } @@ -8170,7 +8181,7 @@ TOOL_ERROR Instrument( } is_function_present = 0; - if (idx > 0) + if ( idx > 0 ) { is_function_present = 1; } @@ -8263,17 +8274,20 @@ TOOL_ERROR Instrument( /* $(...) inserted on same Line as #pragma message for Skipped Region */ } - if ( ( ErrCode = Instrument_Operators( ParseCtx_ptr ) ) != NO_ERR ) + if (!skip_cmplx_instrum) { - goto ret; + if ((ErrCode = Instrument_Operators(ParseCtx_ptr)) != NO_ERR) + { + goto ret; + } } - if ( ( ErrCode = Instrument_Keywords( ParseCtx_ptr ) ) != NO_ERR ) + if ((ErrCode = Instrument_Keywords(ParseCtx_ptr, skip_cmplx_instrum)) != NO_ERR) { goto ret; } - if ( instrument_ROM && is_cnst_data_present) + if ( instrument_ROM && is_cnst_data_present ) { if ( ( ErrCode = Instrument_ROM( ParseCtx_ptr) ) != NO_ERR ) { diff --git a/src/wmc_tool/c_parser.h b/src/wmc_tool/c_parser.h index fcdf810..4c51e94 100644 --- a/src/wmc_tool/c_parser.h +++ b/src/wmc_tool/c_parser.h @@ -31,7 +31,7 @@ void Free_Pointer_Table_Memory( Pointer_Tbl_def *PointerTable_ptr ); TOOL_ERROR Setup_Regions( Parse_Context_def *ParseContext_ptr, bool verbose ); TOOL_ERROR DesInstrument( Parse_Context_def *ParseContext_ptr, bool keep_manual ); TOOL_ERROR DesInstrument_ROM(Parse_Context_def* ParseCtx_ptr); -TOOL_ERROR Instrument(Parse_Context_def* ParseContext_ptr, bool instr_const); +TOOL_ERROR Instrument(Parse_Context_def* ParseContext_ptr, bool instr_const, bool skip_cmplx_instrum); TOOL_ERROR Instrument_Const_Data_PROM_Table( Parse_Context_def *ParseContext_ptr, T_FILE_BOOK file_book[], int nRecords ); TOOL_ERROR Finalize( Parse_Context_def *ParseContext_ptr ); TOOL_ERROR Include_Header(Parse_Context_def* ParseContext_ptr, char** ptr_end_preproc_block ); diff --git a/src/wmc_tool/wmc_tool.cpp b/src/wmc_tool/wmc_tool.cpp index dac4c48..097d8d4 100644 --- a/src/wmc_tool/wmc_tool.cpp +++ b/src/wmc_tool/wmc_tool.cpp @@ -54,10 +54,11 @@ #define DESINSTRUMENT_ONLY 0x001 #define REMOVE_MANUAL_INSTR 0x002 #define VERBOSE 0x004 +#define SKIP_CMPLX_INSTRUM 0x010 #define NO_BACKUP 0x020 #define INSTR_INFO_ONLY 0x040 -#define OUTPUT_WMOPS_FILES 0x080 #define INSTRUMENT_ROM 0x100 +#define OUTPUT_WMOPS_FILES 0x200 /* Other Constants */ #define BACKUP_SUFFIX ".bak" @@ -77,6 +78,7 @@ static void usage() "Options:\n" " -h [--help]: print help\n" " -v [--verbose]: print warnings and other information messages\n" + " -s [--skip-cmplx-instrumentation]: skip complexity instrumentation\n" " -i [--info-only]: only print instrumentation information\n" " -d [--desinstrument]: desintrument only\n" " -m filename [--rom filename]: add statistics about ROM and RAM consumption\n" @@ -191,6 +193,10 @@ static TOOL_ERROR Parse_Command_Line( { *Operation |= INSTR_INFO_ONLY; } + else if (_stricmp(arg_name, "s") == 0 || _stricmp(arg_name, "skip-cmplx-instrumentation") == 0) + { + *Operation |= SKIP_CMPLX_INSTRUM; + } else if (_stricmp(arg_name, "c") == 0 || _stricmp(arg_name, "generate-wmc-files") == 0) { /* get the next argument - must be an existing direectory */ @@ -993,7 +999,7 @@ static TOOL_ERROR Process_File( if ( !( Operation & DESINSTRUMENT_ONLY ) ) { /* Yes */ /* Instrument */ - if ((ErrCode = Instrument(ParseCtx_ptr, (Operation & INSTRUMENT_ROM) != 0)) != NO_ERR) + if ((ErrCode = Instrument(ParseCtx_ptr, (Operation & INSTRUMENT_ROM) != 0, (Operation & SKIP_CMPLX_INSTRUM) != 0)) != NO_ERR) { fprintf(stdout, "\n"); return ErrCode; @@ -1238,7 +1244,14 @@ int main( int argc, char *argv[] ) if (!(Operation & DESINSTRUMENT_ONLY)) { - fprintf(stdout, "- instrumenting all functions and table (const) data memory\n"); + if (Operation & SKIP_CMPLX_INSTRUM) + { + fprintf(stdout, "- skipping instrumentation of functions\n"); + } + else + { + fprintf(stdout, "- instrumenting all functions and table (const) data memory\n"); + } } if (Operation & OUTPUT_WMOPS_FILES) diff --git a/src/wmc_tool/wmc_tool.h b/src/wmc_tool/wmc_tool.h index 95d961e..ff7fd05 100644 --- a/src/wmc_tool/wmc_tool.h +++ b/src/wmc_tool/wmc_tool.h @@ -19,7 +19,7 @@ * Switches *-------------------------------------------------------------------*/ -#define WMC_TOOL_VERSION_NO "1.5" /* Current version */ +#define WMC_TOOL_VERSION_NO "1.5.1" /* Current version */ /*#define DEBUG_PRINT*/ /* For debugging purposes */ /*-------------------------------------------------------------------* From 3e7607d243a87c2abc913a1e4e663b32984c9d9c Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Mon, 22 Jul 2024 13:31:21 +0200 Subject: [PATCH 03/67] relax 70% upper char condition checking for local macros --- src/wmc_tool/c_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 95ccf5e..394b877 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -1657,7 +1657,7 @@ static bool Is_Constant( UpperChar = Total = 0; do { - if ( IS_UPPER_CHAR( *ptr ) ) + if ( !IS_LOWER_CHAR( *ptr ) ) UpperChar += 100; Total++; ptr++; From ccb343b1b4641ab443d6dc866b2743c9ef0c449d Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 23 Jul 2024 14:32:54 +0200 Subject: [PATCH 04/67] fix bug when WMC tool does not instrument malloc() calls in IF(...) statements due to INSTRUMENTATION_OFF --- src/wmc_tool/c_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 394b877..c76ca96 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -5897,7 +5897,7 @@ static TOOL_ERROR Instrument_Calls( } /* System Allocation Function */ /* !! VM: Added && Find_Region(.) to avoid instrumentation of malloc() calls within WMC_TOOL_SKIP segments */ - if ( (item_type & ITEM_FUNC_SYSTEM) && Find_Region(ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED | ITEM_INSTRUMENTATION_OFF) < 0 ) + if ((item_type & ITEM_FUNC_SYSTEM) && Find_Region(ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED) < 0) { /* Yes */ /* Insert Instrumentation */ if ( ( ErrCode = Add_Insertion( &ParseCtx_ptr->InsertTbl, end, WORD_INSTRUMENT_STRING ) ) != NO_ERR ) From 57ed22b9fe622a6995c6f7770e1250bdc257f579 Mon Sep 17 00:00:00 2001 From: malenov Date: Fri, 26 Jul 2024 09:43:31 +0200 Subject: [PATCH 05/67] fixing des-instrumentation of a file that contains print_mem() function plus some instrumented code, e.g. encoder.c --- src/wmc_tool/c_parser.cpp | 158 ++++++++++++++------------------------ src/wmc_tool/wmc_tool.h | 2 +- 2 files changed, 60 insertions(+), 100 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index c76ca96..4f4bb3a 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -7343,7 +7343,6 @@ TOOL_ERROR DesInstrument( } - /*-------------------------------------------------------------------* * DesInstrument_ROM *-------------------------------------------------------------------*/ @@ -7384,121 +7383,82 @@ TOOL_ERROR DesInstrument_ROM( start = ParseRec_ptr->item_start; tmp = ParseRec_ptr->item_end; - /* Instrumentation Code? E.g. 'AddedByWMC_Tool' */ - if (ParseRec_ptr->item_type & ITEM_FUNC_COUNTERS_AUTO && ((ParseRec_ptr->item_type & ITEM_FUNC_COUNTERS_MAN) == 0 || - Find_Region(start, ParseTbl_ptr, ITEM_INSTRUMENTATION_OFF) < 0)) - { /* Yes */ - if (!(ParseRec_ptr->item_type & ITEM_PREPROC_LINE)) - { - /* Delete it */ - Delete(start, tmp); - } - } - - /* 'Const_Data_PROM_Table' Declaration? */ - else if (ParseRec_ptr->item_type & ITEM_DATA_DECL) + /* Data Declaration? */ + if (ParseRec_ptr->item_type & ITEM_DATA_DECL) { /* Yes */ - /* Check if this ROM_Size_Lookup_Table declaration */ + /* Check if this is ROM_Size_Lookup_Table declaration */ if (strnistr(start, "ROM_Size_Lookup_Table", strlen("ROM_Size_Lookup_Table")) != NULL) { - /* Save the pointers - will be used later to check, if it was enclosed in #ifdef WMOPS .. #endif pair */ - start_const_data_prom_table = start; - end_const_data_prom_table = tmp; - } - - /* Delete it */ - Delete(start, tmp); - - } - - /* One of the ROM counting functions, e.g. 'Const_Data_Size_Func(...)'? */ - else if (ParseRec_ptr->item_type & ITEM_FUNC_DEF) - { /* Yes */ - /* Is function prototype or block followed by some blank chars? -> delete them as well */ - if (ParseRec_ptr->item_type & (ITEM_FUNC_PROTO | ITEM_FUNC_BLOCK)) - { - tmp = Skip_Chars(tmp, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_COMMENT, FORWARD); - } + /* Go back to the beginning of the line */ + start = Goto_Chars(start, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + start++; - /* Delete it */ - Delete(start, tmp); - - /* Desintrumenting Function Name? -> Check if it's preceded by 'extern int' or 'static int' return type */ - if (ParseRec_ptr->item_type & ITEM_FUNC_NAME) - { - /* Find the end of the preceding keyword */ - while ((tmp = Skip_Chars(start - 1, SPACE_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_MOVED_OVER, BACKWARDS)) != NULL && IS_IDENTIFIER_CHAR(*tmp)) + /* Check, if line starts with "AddedByWMC_Tool */ + while (strncmp(start, ADDED_TOOL_INFO_STRING, strlen(ADDED_TOOL_INFO_STRING)) == 0) { - /* Find the beginning of the preceding keyword */ - start = Skip_Identifier(tmp, BACKWARDS) + 1; - - /* Check if the found keyword matches one of 'extern', 'static' or 'int' */ - if (memwordcmp(start, STORAGE_STRING) || memwordcmp(start, INT_STRING)) - { /* Yes */ - /* Delete it */ - Delete(start, tmp + 2); + /* check, if line continues with "#ifdef WMOPS" */ + if (strncmp(start + strlen(ADDED_TOOL_INFO_STRING), "#ifdef WMOPS", strlen("#ifdef WMOPS")) == 0) + { + start_const_data_prom_table = start; + break; + } + else + { + /* Go back to the beginning of the previous line */ + start = Skip_Chars(start - 1, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + start = Goto_Chars(start, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + start++; } } - } - - /* Item is no Longer a Function Name/Proto/Block */ - ParseRec_ptr->item_type &= ~ITEM_FUNC_DEF; - } - - /* Item is no Longer Instrumentation */ - ParseRec_ptr->item_type ^= ITEM_INSTRUMENTATION; - } - /* Check, if Const_Data_PROM_Table[] was enclosed in #ifdef WMOPS .. #endif pair */ - if (start_const_data_prom_table != NULL && end_const_data_prom_table != NULL) - { - /* Go back to the first word preceding Const_Data_PROM_Table[] */ - start = Skip_Chars(start_const_data_prom_table - 1, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); - - /* Proceed to the beginning of the line */ - while (!IS_EOL_CHAR(PREV_CHAR(start))) - { - start--; - } + if (!IS_EOL_CHAR(PREV_CHAR(tmp))) + { + /* Go to the beginning of the next line */ + tmp = Goto_Chars(tmp, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, FORWARD); + tmp = Skip_Chars(tmp, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, FORWARD); + } - /* Check if line contains "#ifdef WMOPS" */ - if ( (tmp = stristr(memstr(start, start_const_data_prom_table), "#ifdef")) != NULL) - { - tmp = Skip_Identifier(tmp, FORWARD); - tmp = Skip_Chars(tmp + 1, SPACE_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE); - if (strncmp(tmp, "WMOPS", strlen("WMOPS")) == 0) - { - /* Delete the whole line */ - Delete(start, start_const_data_prom_table); - } - } + /* Check, if line starts with "AddedByWMC_Tool */ + while (strncmp(tmp, ADDED_TOOL_INFO_STRING, strlen(ADDED_TOOL_INFO_STRING)) == 0) + { + /* check, if line continues with "#endif" */ + if (strncmp(tmp + strlen(ADDED_TOOL_INFO_STRING), "#endif", strlen("#endif")) == 0) + { + /* Go to the end this line */ + tmp = Goto_Chars(tmp, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, FORWARD); - /* Go to the first word after Const_Data_PROM_Table[] */ - end = Skip_Chars(end_const_data_prom_table, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE); + /* Go past the EOL */ + if (IS_EOL_SEQ(tmp)) + { + /* One Extra step, if it's CR+LF */ + tmp++; + } + tmp++; - /* Check if line contains "#endif" */ - while (!IS_EOL_CHAR(NEXT_CHAR(end))) - { - if (*end == '#') - { - /* Found '#' */ - if (strncmp(end, "#endif", strlen("#endif")) == 0) - { - /* Go to EOL */ - while (*end != LF_CHAR) + end_const_data_prom_table = tmp; + break; + } + else { - end++; + /* Go to the beginning of the next line */ + tmp = Goto_Chars(tmp, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, FORWARD); + tmp = Skip_Chars(tmp, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, FORWARD); } + } - /* Delete the whole line */ - Delete(end_const_data_prom_table, end); - - break; + if (start_const_data_prom_table != NULL && end_const_data_prom_table != NULL) + { + /* Delete the whole segment */ + Delete(start, tmp); } - } - end++; + /* Item is no Longer a Declaration */ + ParseRec_ptr->item_type ^= ITEM_DATA_DECL; + + /* Item is no Longer Instrumentation */ + ParseRec_ptr->item_type ^= ITEM_INSTRUMENTATION; + } } } diff --git a/src/wmc_tool/wmc_tool.h b/src/wmc_tool/wmc_tool.h index ff7fd05..f081798 100644 --- a/src/wmc_tool/wmc_tool.h +++ b/src/wmc_tool/wmc_tool.h @@ -19,7 +19,7 @@ * Switches *-------------------------------------------------------------------*/ -#define WMC_TOOL_VERSION_NO "1.5.1" /* Current version */ +#define WMC_TOOL_VERSION_NO "1.5.2" /* Current version */ /*#define DEBUG_PRINT*/ /* For debugging purposes */ /*-------------------------------------------------------------------* From 5496cfd3777787bb4834691c96ac946172978bf2 Mon Sep 17 00:00:00 2001 From: malenov Date: Mon, 29 Jul 2024 15:16:01 +0200 Subject: [PATCH 06/67] update to version v1.6 --- src/wmc_tool/wmc_tool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmc_tool/wmc_tool.h b/src/wmc_tool/wmc_tool.h index f081798..891d69b 100644 --- a/src/wmc_tool/wmc_tool.h +++ b/src/wmc_tool/wmc_tool.h @@ -19,7 +19,7 @@ * Switches *-------------------------------------------------------------------*/ -#define WMC_TOOL_VERSION_NO "1.5.2" /* Current version */ +#define WMC_TOOL_VERSION_NO "1.6" /* Current version */ /*#define DEBUG_PRINT*/ /* For debugging purposes */ /*-------------------------------------------------------------------* From 5b310546d0de60ecad3551eada9d99928397b5f9 Mon Sep 17 00:00:00 2001 From: malenov Date: Mon, 29 Jul 2024 15:17:05 +0200 Subject: [PATCH 07/67] when #undef WMC_TOOL_SKIP is missing, automatically assume end of file but before the last automatically instrumented segment --- src/wmc_tool/c_parser.cpp | 166 +++++++++++++++++++++++++++++++++----- 1 file changed, 147 insertions(+), 19 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 4f4bb3a..0ea8eae 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -3549,6 +3549,46 @@ static TOOL_ERROR Find_Preproc_Instrumentation( } } + /* Mark all lines preceded by AddedByWMC_Tool as Instrumentation */ + + /* Start at Beginning */ + ptr = ParseCtx_ptr->File.Data; + + /* Search for AddedBy_WMC_Tool string which has not been marked as instrumentation yet */ + while ((ptr = Find_Identifier(ptr, ADDED_TOOL_INFO_STRING, ParseTbl_ptr, ITEM_COMMENT, ITEM_INSTRUMENTATION, &idx)) != NULL) + { + /* Get Record */ + ParseRec_ptr = &ParseTbl_ptr->Data[idx]; + + /* Mark as Instrumentation */ + ParseRec_ptr->item_type |= ITEM_INSTRUMENTATION; + + ptr = ParseRec_ptr->item_end; + + /* check, if is followed by #ifdef or #endif statement */ + if ((idx = Find_Region(ptr, ParseTbl_ptr, ITEM_PREPROC_CMD | ITEM_PREPROC_COND)) > 0) + { + /* Get Record */ + ParseRec_ptr = &ParseTbl_ptr->Data[idx]; + + /* Mark as Instrumentation */ + ParseRec_ptr->item_type |= ITEM_INSTRUMENTATION; + + if (memwordcmp(ptr, "#if #ifdef #ifndef #elif") != NULL) + { + /* Get the next record - should be Preprocessor Directive Arguments */ + ParseRec_ptr = &ParseTbl_ptr->Data[idx + 1]; + + /* Mark as Instrumentation */ + ParseRec_ptr->item_type |= ITEM_INSTRUMENTATION; + } + + /* Advance pointer to the end of Preprocessor Arguments (Skip Spaces and Comments Only) */ + ptr = Skip_Chars(ParseRec_ptr->item_end, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_COMMENT); + } + } + + return ErrCode; } @@ -4769,7 +4809,7 @@ static TOOL_ERROR Instrument_Keywords( } } - /* Count Program Memory */ + ///* Count Program Memory */ //if ( item_type == ITEM_KEYWORD_FOR ) // loops++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->loop; //else if ( item_type == ITEM_KEYWORD_WHILE ) @@ -4779,7 +4819,8 @@ static TOOL_ERROR Instrument_Keywords( } /* Count Program Memory */ /* !!! VM: Moved to this place to count PROM size even for non-instrumented keywords */ - if ( Find_Region(ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED) < 0 ) + //if ( Find_Region(ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED) < 0 ) + if (!IS_RESERVED_CHAR(*(ParseRec_ptr->item_start))) { if (item_type == ITEM_KEYWORD_FOR) loops++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->loop; @@ -6462,13 +6503,46 @@ TOOL_ERROR Setup_Regions( ITEM_PREPROC_ARGS | ITEM_PREPROC_UNDEF, ITEM_ENCLOSED, &idx ) ) == NULL ) { /* No */ - /* Error - #undef WMC_TOOL_SKIP missing ! */ - ErrCode = ERR_EXPECTED_EOS; - Error("Unable to find matching #undef %s!", ErrCode, WMC_TOOL_SKIP_STRING); - goto ret; + ///* Error - #undef WMC_TOOL_SKIP missing ! */ + //ErrCode = ERR_EXPECTED_EOS; + //Error("Unable to find matching #undef %s!", ErrCode, WMC_TOOL_SKIP_STRING); + //goto ret; + + /* Go to EOF */ + end = file_ptr->Data + file_ptr->Size; + + /* Go back by skipping all lines preceded by AddedByWMC_Tool */ - /* Skipped Region will End at EOF */ - //end = file_ptr->Data + file_ptr->Size; + /* Go back to the beginning of the line */ + end = Skip_Chars(end, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + end = Goto_Chars(end, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + end++; + + /* Check, if line starts with "AddedByWMC_Tool */ + while (strncmp(end, ADDED_TOOL_INFO_STRING, strlen(ADDED_TOOL_INFO_STRING)) == 0) + { + /* Go back to the beginning of the previous line */ + end = Skip_Chars(end - 1, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + end = Goto_Chars(end, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + end++; + } + + /* Go to the end of the current line */ + end = Goto_Chars(end, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, FORWARD); + + if (end == NULL) + { + /* reached the end of file */ + end = file_ptr->Data + file_ptr->Size; + } + else if (IS_EOL_SEQ(end)) + { + end += 2; + } + else + { + end++; + } } else { /* Yes */ @@ -6483,7 +6557,7 @@ TOOL_ERROR Setup_Regions( } /* Add Non-Instrumented Region */ - if ( ( ErrCode = Add_Region( ParseTbl_ptr, ITEM_INSTRUMENTATION_OFF, ptr, end ) ) != NO_ERR ) + if ( ( ErrCode = Add_Region( ParseTbl_ptr, ITEM_SKIPPED | ITEM_INSTRUMENTATION_OFF, ptr, end ) ) != NO_ERR ) { goto ret; } @@ -7348,7 +7422,8 @@ TOOL_ERROR DesInstrument( *-------------------------------------------------------------------*/ TOOL_ERROR DesInstrument_ROM( - Parse_Context_def* ParseCtx_ptr) + Parse_Context_def* ParseCtx_ptr +) { TOOL_ERROR ErrCode = NO_ERR; @@ -7360,13 +7435,6 @@ TOOL_ERROR DesInstrument_ROM( start_const_data_prom_table = NULL; end_const_data_prom_table = NULL; - /* Check Previous State */ - if (ParseCtx_ptr->State != SETUP_OK) - { - ErrCode = Internal_Error(__FUNCTION__); - goto ret; - } - /* Set State Failure (by default) */ ParseCtx_ptr->State = DI_FAILED; @@ -7383,8 +7451,18 @@ TOOL_ERROR DesInstrument_ROM( start = ParseRec_ptr->item_start; tmp = ParseRec_ptr->item_end; + /* Instrumentation Code? E.g. 'AddedByWMC_Tool' */ + if (ParseRec_ptr->item_type & ITEM_FUNC_COUNTERS_AUTO && ((ParseRec_ptr->item_type & ITEM_FUNC_COUNTERS_MAN) == 0 || + Find_Region(start, ParseTbl_ptr, ITEM_INSTRUMENTATION_OFF) < 0)) + { /* Yes */ + if (!(ParseRec_ptr->item_type & ITEM_PREPROC_LINE)) + { + /* Delete it */ + Delete(start, tmp); + } + } /* Data Declaration? */ - if (ParseRec_ptr->item_type & ITEM_DATA_DECL) + else if (ParseRec_ptr->item_type & ITEM_DATA_DECL) { /* Yes */ /* Check if this is ROM_Size_Lookup_Table declaration */ @@ -7460,6 +7538,56 @@ TOOL_ERROR DesInstrument_ROM( ParseRec_ptr->item_type ^= ITEM_INSTRUMENTATION; } } + /* One of the 'Const_Data_Size_Func(...)' counting functions? */ + else if (ParseRec_ptr->item_type & ITEM_FUNC_DEF) + { /* Yes */ + /* Is function prototype or block followed by some blank chars? -> delete them as well */ + if (ParseRec_ptr->item_type & (ITEM_FUNC_PROTO | ITEM_FUNC_BLOCK)) + { + /* Skip all SPACE chars, if any */ + tmp = Skip_Chars(tmp, SPACE_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_COMMENT, FORWARD); + + /* Go past the EOL, if present */ + if (IS_EOL_SEQ(tmp)) + { + /* Two chars, in case of CR+LF */ + tmp += 2; + } + else if (IS_EOL_CHAR(*tmp)) + { + /* One char, if only LF */ + tmp++; + } + } + + /* Delete it */ + Delete(start, tmp); + + /* Desintrumenting Function Name? -> Check if it's preceded by 'extern int' or 'static int' return type */ + if (ParseRec_ptr->item_type & ITEM_FUNC_NAME) + { + /* Find the end of the preceding keyword */ + while ((tmp = Skip_Chars(start - 1, SPACE_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_MOVED_OVER, BACKWARDS)) != NULL && IS_IDENTIFIER_CHAR(*tmp)) + { + /* Find the beginning of the preceding keyword */ + start = Skip_Identifier(tmp, BACKWARDS) + 1; + + /* Check if the found keyword matches one of 'extern', 'static' or 'int' */ + if (memwordcmp(start, STORAGE_STRING) || memwordcmp(start, INT_STRING)) + { /* Yes */ + /* Delete it */ + Delete(start, tmp + 2); + } + } + } + + /* Item is no Longer a Function Name/Proto/Block */ + ParseRec_ptr->item_type &= ~ITEM_FUNC_DEF; + + /* Item is no Longer Instrumentation */ + ParseRec_ptr->item_type ^= ITEM_INSTRUMENTATION; + } + } /* Find the print_mem() function */ @@ -7489,7 +7617,7 @@ TOOL_ERROR DesInstrument_ROM( /* Set State Success */ ParseCtx_ptr->State = DESINSTRUMENTED; -ret: +//ret: return ErrCode; } From ecf2918382ebab8e72082a580513b32c80412fa7 Mon Sep 17 00:00:00 2001 From: malenov Date: Mon, 29 Jul 2024 15:17:19 +0200 Subject: [PATCH 08/67] call DesInstrument_ROM() for regular files as well --- src/wmc_tool/wmc_tool.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/wmc_tool/wmc_tool.cpp b/src/wmc_tool/wmc_tool.cpp index 097d8d4..59ef6fa 100644 --- a/src/wmc_tool/wmc_tool.cpp +++ b/src/wmc_tool/wmc_tool.cpp @@ -995,6 +995,13 @@ static TOOL_ERROR Process_File( return ErrCode; } + /* DesInstrument Const_Data_Size_XXX Functions */ + if ( ( ErrCode = DesInstrument_ROM( ParseCtx_ptr ) ) != NO_ERR ) + { + fprintf(stdout, "\n"); + return ErrCode; + } + /* Instrument */ if ( !( Operation & DESINSTRUMENT_ONLY ) ) { /* Yes */ @@ -1160,6 +1167,7 @@ int main( int argc, char *argv[] ) char Const_Data_PROM_File[MAX_PATH] = ""; char wmops_output_dir[MAX_PATH]; float frames_per_sec; + bool Const_Data_PROM_File_already_reinstrumented = 0; T_FILE_BOOK file_book[MAX_RECORDS]; struct stat s; Parse_Context_def ParseContext; @@ -1434,6 +1442,12 @@ int main( int argc, char *argv[] ) /* Process File */ ErrCode = Process_File(LongFileName, Operation, &ParseContext, MaxFnLength, (Operation & NO_BACKUP) == 0, j * 100.0f / file_book[i].nFiles); + /* Check if the processed file is the same as */ + if (strcmp(LongFileName, Const_Data_PROM_File) == 0) + { + Const_Data_PROM_File_already_reinstrumented = 1; + } + /* Update # of Bytes Processed */ nBytesProcessed += ParseContext.File.Size; @@ -1526,10 +1540,13 @@ int main( int argc, char *argv[] ) goto ret; } - /* DesInstrument Const_Data_Size_XXX Functions */ - if ((ErrCode = DesInstrument_ROM(&ParseContext)) != NO_ERR) + /* DesInstrument Const_Data_PROM_Table[] */ + if (!Const_Data_PROM_File_already_reinstrumented) { - goto ret; + if ((ErrCode = DesInstrument_ROM(&ParseContext)) != NO_ERR) + { + goto ret; + } } /* Check, if "wmc_auto.h" is included */ From 479d991ec4fe8dfd5b17c566f14c420a9d59cedd Mon Sep 17 00:00:00 2001 From: malenov Date: Mon, 29 Jul 2024 15:30:20 +0200 Subject: [PATCH 09/67] add documentation of changes for v1.6 --- src/wmc_tool/HISTORY.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/wmc_tool/HISTORY.md b/src/wmc_tool/HISTORY.md index 988cc26..f2f43e3 100644 --- a/src/wmc_tool/HISTORY.md +++ b/src/wmc_tool/HISTORY.md @@ -70,4 +70,10 @@ ## v1.5.1 * added the -s (--skip_cmplx_instrumentation) command-line option, which avoids the instrumentation of function bodies. The func_start_ and return_ keywords, along with the remaining functionality, remain unchanged. + +## v1.6 + + * fixed instrumentation issues in encoder.c of the 3GPP EVS codec where malloc() is instrumented and print_mem() is present as well + * when #undef WMC_TOOL_SKIP is missing, automatically assume end of file, but before the last automatically instrumented segment + * the function DesInstrument_ROM() is called in all regular files as well as the file pointed to with the -m command-line argument \ No newline at end of file From 5e36e14768d5e31eb52d80673cf3160314bdb820 Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 13 Sep 2023 13:37:32 +0200 Subject: [PATCH 10/67] remove push_indice(), set_indice(), get_indice(), exist_indice(), reset_indices(), write_indices(), read_indices(), read_bitstream_info(), reset_stack() and push_stack() from the list of reserved function names --- src/wmc_tool/c_parser.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index e204942..b775d4b 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -141,10 +141,7 @@ "printf fprintf " \ "fopen fclose fwrite fread " \ "exit " \ - "assert " \ - "push_indice set_indice get_indice exist_indice " \ - "reset_indices write_indices read_indices " \ - "read_bitstream_info reset_stack push_stack " + "assert " #define MATH_FUNCTS_STRING \ "abs fabs labs " \ From 2fce427d73df044af19f68039d8e7f3340b116c7 Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 13 Sep 2023 13:38:52 +0200 Subject: [PATCH 11/67] fix the arguments of the itos() function --- src/wmc_tool/text_utils.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wmc_tool/text_utils.cpp b/src/wmc_tool/text_utils.cpp index f2738c6..5d2cdfc 100644 --- a/src/wmc_tool/text_utils.cpp +++ b/src/wmc_tool/text_utils.cpp @@ -454,10 +454,11 @@ char *mempwordicmp( const char *mem, const char *words ) /*-------------------------------------------------------------------* * itos (Integer to String) *-------------------------------------------------------------------*/ -char *itos( char *str, int value, int digits ) +char *itos( char *str, int value ) { size_t i, n; char *str2; + int digits = 3; /* Convert Value to String */ sprintf(str, "%d", value); From 8063685a658424d5ca484f1b15947e6252630f21 Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 13 Sep 2023 13:39:21 +0200 Subject: [PATCH 12/67] fix the declaration of the itos() function --- src/wmc_tool/text_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmc_tool/text_utils.h b/src/wmc_tool/text_utils.h index b15a1b6..3b99685 100644 --- a/src/wmc_tool/text_utils.h +++ b/src/wmc_tool/text_utils.h @@ -109,7 +109,7 @@ char *memwordicmp( const char *mem, const char *words ); char *strwordistr( const char *mem, const char *words ); char *mempwordicmp( const char *mem, const char *words ); -char *itos( char *str, int value, int digits = 3 ); +char *itos( char *str, int value ); char *Fix_FileName( char *ptr ); From 4b228da0d7bc297ff6d1befbe7d8ce11982da93a Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 13 Sep 2023 13:41:25 +0200 Subject: [PATCH 13/67] - fix NaN printed in the complexity printout for a non-instrumented function - update of memory consumption counters is part of update_wmops() - replace the code updating the worst-case intra-frame and inter-frame heap memory consumption - support for per-frame and per-block memory consumption exported to a .csv file - fix incorrect calculation of the worst-case heap size for memory blocks allocated and de-allocated multiple times in a single frame --- src/wmc_tool/wmc_auto_c.txt | 190 +++++++++++++++++++----------------- src/wmc_tool/wmc_auto_h.txt | 4 - 2 files changed, 102 insertions(+), 92 deletions(-) diff --git a/src/wmc_tool/wmc_auto_c.txt b/src/wmc_tool/wmc_auto_c.txt index ec1726b..58f024f 100644 --- a/src/wmc_tool/wmc_auto_c.txt +++ b/src/wmc_tool/wmc_auto_c.txt @@ -340,12 +340,6 @@ "\r\n" " start_cnt = ops_cnt;\r\n" "\r\n" -" if ( heap_allocation_call_tree_size > 0 )\r\n" -" {\r\n" -" /* update intra-frame heap memory and inter-frame heap memory*/\r\n" -" update_mem();\r\n" -" }\r\n" -"\r\n" " /* increment frame counter */\r\n" " update_cnt++;\r\n" "\r\n" @@ -386,7 +380,7 @@ " }\r\n" "\r\n" " fprintf( stdout, sfmts, \"---------------\", \"------\", \"------\", \"------\", \"------\" );\r\n" -" fprintf( stdout, dfmts, \"total\", (float) update_cnt, FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt );\r\n" +" fprintf( stdout, dfmts, \"total\", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt );\r\n" " fprintf( stdout, \"\\n\" );\r\n" "\r\n" "#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" @@ -553,6 +547,11 @@ "#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) )\r\n" "#define IS_CALLOC( str ) ( str[0] == 'c' )\r\n" "\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +"const char *csv_filename = \"mem_analysis.csv\";\r\n" +"static FILE *fid_csv_filename = NULL;\r\n" +"#endif\r\n" +"\r\n" "typedef struct\r\n" "{\r\n" " char function_name[MAX_FUNCTION_NAME_LENGTH + 1];\r\n" @@ -687,6 +686,25 @@ " size_wc_inter_frame_heap = 0;\r\n" " location_wc_inter_frame_heap = -1;\r\n" "\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +" /* Check, if the .csv file has already been opened */\r\n" +" if ( fid_csv_filename == NULL )\r\n" +" {\r\n" +" fid_csv_filename = fopen( csv_filename, \"wb\" );\r\n" +"\r\n" +" if ( fid_csv_filename == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", csv_filename );\r\n" +" exit( -1 );\r\n" +" }\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" /* reset file */\r\n" +" rewind( fid_csv_filename );\r\n" +" }\r\n" +"#endif\r\n" +"\r\n" " return;\r\n" "}\r\n" "\r\n" @@ -959,6 +977,11 @@ " ptr_record->block_size = size;\r\n" " ptr_record->total_block_size += size;\r\n" "\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +" /* Export heap memory allocation record to the .csv file */\r\n" +" fprintf( fid_csv_filename, \"A,%d,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n" +"#endif\r\n" +"\r\n" " if ( ptr_record->frame_allocated != -1 )\r\n" " {\r\n" " fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Attempt to Allocate the Same Memory Block with Freeing it First!\" );\r\n" @@ -1294,6 +1317,11 @@ " /* Check, if Out-Of-Bounds Access has been Detected */\r\n" " ptr_record->OOB_Flag = mem_check_OOB( ptr_record );\r\n" "\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +" /* Export heap memory de-allocation record to the .csv file */\r\n" +" fprintf( fid_csv_filename, \"D,%d,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n" +"#endif\r\n" +"\r\n" " /* De-Allocate Memory Block */\r\n" " tmp_ptr = (char *) ptr;\r\n" " tmp_ptr -= BLOCK_ROUNDING;\r\n" @@ -1332,11 +1360,11 @@ "void update_mem( void )\r\n" "{\r\n" " int i, j, flag_alloc = -1, i_record;\r\n" -" int32_t size_current_intra_frame_heap;\r\n" +" int size_current_intra_frame_heap;\r\n" " int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap;\r\n" " allocator_record *ptr_record;\r\n" "\r\n" -" /* process the heap allocation call tree */\r\n" +" /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */\r\n" " n_items_current_intra_frame_heap = 0;\r\n" " size_current_intra_frame_heap = 0;\r\n" " for ( i = 0; i < heap_allocation_call_tree_size; i++ )\r\n" @@ -1364,7 +1392,7 @@ " memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) );\r\n" " }\r\n" "\r\n" -" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n" +" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n" " if ( i_record == 0 )\r\n" " {\r\n" " flag_alloc = 1;\r\n" @@ -1384,23 +1412,7 @@ " list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record;\r\n" " size_current_intra_frame_heap += ptr_record->block_size;\r\n" "\r\n" -" /* check, if this is the new worst-case */\r\n" -" if ( size_current_intra_frame_heap > size_wc_intra_frame_heap )\r\n" -" {\r\n" -" if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap )\r\n" -" {\r\n" -" /* resize list, if needed */\r\n" -" max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" /* save to wc list */\r\n" -" memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) );\r\n" -" n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap;\r\n" -" size_wc_intra_frame_heap = size_current_intra_frame_heap;\r\n" -" location_wc_intra_frame_heap = update_cnt;\r\n" -" ptr_record->wc_heap_size_intra_frame = ptr_record->block_size;\r\n" -" }\r\n" +" /* no need to re-size the list -> the initially allocated size should be large enough */\r\n" " }\r\n" " else\r\n" " {\r\n" @@ -1451,23 +1463,6 @@ "\r\n" " list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record;\r\n" " size_current_inter_frame_heap += ptr_record->block_size;\r\n" -"\r\n" -" /* check, if this is the new worst-case */\r\n" -" if ( size_current_inter_frame_heap > size_wc_inter_frame_heap )\r\n" -" {\r\n" -" if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap )\r\n" -" {\r\n" -" /* resize list, if needed */\r\n" -" max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) );\r\n" -" n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap;\r\n" -" size_wc_inter_frame_heap = size_current_inter_frame_heap;\r\n" -" location_wc_inter_frame_heap = update_cnt;\r\n" -" ptr_record->wc_heap_size_inter_frame = ptr_record->block_size;\r\n" -" }\r\n" " }\r\n" " else\r\n" " {\r\n" @@ -1490,9 +1485,60 @@ " }\r\n" " }\r\n" "\r\n" +" /* check, if this is the new worst-case for intra-frame heap memory */\r\n" +" if ( size_current_intra_frame_heap > size_wc_intra_frame_heap )\r\n" +" {\r\n" +" if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap )\r\n" +" {\r\n" +" /* resize the list, if needed */\r\n" +" max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n" +" }\r\n" +"\r\n" +" /* copy current-frame list to worst-case list */\r\n" +" memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) );\r\n" +" n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap;\r\n" +" size_wc_intra_frame_heap = size_current_intra_frame_heap;\r\n" +" location_wc_intra_frame_heap = update_cnt;\r\n" +"\r\n" +" /* update the wc numbers in all individual records */\r\n" +" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n" +" {\r\n" +" i_record = list_wc_intra_frame_heap[i];\r\n" +" ptr_record = &( allocation_list[i_record] );\r\n" +" ptr_record->wc_heap_size_intra_frame = ptr_record->block_size;\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* check, if this is the new worst-case for inter-frame heap memory */\r\n" +" if ( size_current_inter_frame_heap > size_wc_inter_frame_heap )\r\n" +" {\r\n" +" if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap )\r\n" +" {\r\n" +" /* resize list, if needed */\r\n" +" max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n" +" }\r\n" +"\r\n" +" /* copy current-frame list to worst-case list */\r\n" +" memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) );\r\n" +" n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap;\r\n" +" size_wc_inter_frame_heap = size_current_inter_frame_heap;\r\n" +" location_wc_inter_frame_heap = update_cnt;\r\n" +"\r\n" +" /* update the wc numbers in all individual records */\r\n" +" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n" +" {\r\n" +" i_record = list_wc_inter_frame_heap[i];\r\n" +" ptr_record = &( allocation_list[i_record] );\r\n" +" ptr_record->wc_heap_size_inter_frame = ptr_record->block_size;\r\n" +" }\r\n" +" }\r\n" +"\r\n" " /* reset heap allocation call tree */\r\n" " heap_allocation_call_tree_size = 0;\r\n" "\r\n" +" /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */\r\n" " if ( list_current_intra_frame_heap )\r\n" " {\r\n" " free( list_current_intra_frame_heap );\r\n" @@ -1607,7 +1653,7 @@ "\r\n" " if ( ptr_record->noccurances > 1 )\r\n" " {\r\n" -" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ( ptr_record->noccurances * ptr_record->wc_heap_size_intra_frame ) >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" +" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" " }\r\n" " else\r\n" " {\r\n" @@ -1636,7 +1682,7 @@ " continue;\r\n" " }\r\n" " ptr_record = &( allocation_list[index_record] );\r\n" -" ptr_record->noccurances = 1; /* reset the counter because som blocks may be both, intra-frame and inter-frame */\r\n" +" ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */\r\n" " for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ )\r\n" " {\r\n" " index = list_wc_inter_frame_heap[j];\r\n" @@ -1655,7 +1701,7 @@ " }\r\n" "\r\n" " /* Print Header */\r\n" -" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Maximum Size\", \"Usage\" );\r\n" +" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Memory Size\", \"Usage\" );\r\n" " puts( buf );\r\n" " length = strlen( buf );\r\n" " sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n" @@ -1690,11 +1736,11 @@ " sprintf( line_str, \"%d\", ptr_record->lineno );\r\n" "\r\n" " /* prepare average usage & memory size strings */\r\n" -" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) );\r\n" +" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) );\r\n" "\r\n" " if ( ptr_record->noccurances > 1 )\r\n" " {\r\n" -" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ( ptr_record->noccurances * ptr_record->wc_heap_size_inter_frame ) >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" +" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" " }\r\n" " else\r\n" " {\r\n" @@ -1712,45 +1758,6 @@ " return;\r\n" "}\r\n" "\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * export_mem()\r\n" -" *\r\n" -" * Export detailed (per-item) information about heap memory usage to a .csv file\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void export_mem( const char *csv_filename )\r\n" -"{\r\n" -" int i;\r\n" -" static FILE *fid = NULL;\r\n" -" allocator_record *record_ptr;\r\n" -"\r\n" -" if ( csv_filename == NULL || strcmp( csv_filename, \"\" ) == 0 )\r\n" -" {\r\n" -" return;\r\n" -" }\r\n" -"\r\n" -" /* Check, if the .csv file has already been opened */\r\n" -" if ( fid == NULL )\r\n" -" {\r\n" -" fid = fopen( csv_filename, \"wb\" );\r\n" -"\r\n" -" if ( fid == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", csv_filename );\r\n" -" exit( -1 );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Export individual heap memory records to a .csv file */\r\n" -" for ( i = 0; i < Num_Records; i++ )\r\n" -" {\r\n" -" record_ptr = &( allocation_list[i] );\r\n" -" fprintf( fid, \"%s:%d,%d;\", record_ptr->name, record_ptr->lineno, record_ptr->block_size );\r\n" -" }\r\n" -" fprintf( fid, \"\\n\" );\r\n" -"\r\n" -" return;\r\n" -"}\r\n" "#endif\r\n" "\r\n" "/*-------------------------------------------------------------------*\r\n" @@ -1901,6 +1908,13 @@ " free( list_wc_inter_frame_heap );\r\n" " }\r\n" "\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +" if ( fid_csv_filename != NULL )\r\n" +" {\r\n" +" fclose( fid_csv_filename );\r\n" +" }\r\n" +"#endif\r\n" +"\r\n" " return;\r\n" "}\r\n" "\r\n" diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index a5d54b3..6a36806 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -1007,9 +1007,6 @@ "\r\n" "void reset_mem( Counting_Size cnt_size );\r\n" "void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] );\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -"void export_mem( const char *csv_filename );\r\n" -"#endif\r\n" "\r\n" "int push_stack( const char *filename, const char *fctname );\r\n" "int pop_stack( const char *filename, const char *fctname );\r\n" @@ -1031,7 +1028,6 @@ "#define free_( ptr ) free( ptr )\r\n" "#define reset_mem( cnt_size )\r\n" "#define print_mem( Const_Data_PROM_Table )\r\n" -"#define export_mem( csv_filename )\r\n" "\r\n" "#define push_stack( file, fct )\r\n" "#define pop_stack( file, fct )\r\n" From 2db1ec657719a1ca6bce3506fa71a8ee11c1b915 Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 13 Sep 2023 14:27:58 +0200 Subject: [PATCH 14/67] update the reference files wmc_auto.h and wmc_auto.c used in ctest --- src/wmc_tool/test_data/ref/wmc_auto.c | 190 ++++++++++++++------------ src/wmc_tool/test_data/ref/wmc_auto.h | 4 - 2 files changed, 102 insertions(+), 92 deletions(-) diff --git a/src/wmc_tool/test_data/ref/wmc_auto.c b/src/wmc_tool/test_data/ref/wmc_auto.c index 69cf37a..b86bc25 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.c +++ b/src/wmc_tool/test_data/ref/wmc_auto.c @@ -340,12 +340,6 @@ void update_wmops( void ) start_cnt = ops_cnt; - if ( heap_allocation_call_tree_size > 0 ) - { - /* update intra-frame heap memory and inter-frame heap memory*/ - update_mem(); - } - /* increment frame counter */ update_cnt++; @@ -386,7 +380,7 @@ void print_wmops( void ) } fprintf( stdout, sfmts, "---------------", "------", "------", "------", "------" ); - fprintf( stdout, dfmts, "total", (float) update_cnt, FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt ); + fprintf( stdout, dfmts, "total", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt ); fprintf( stdout, "\n" ); #ifdef WMOPS_WC_FRAME_ANALYSIS @@ -553,6 +547,11 @@ void print_wmops( void ) #define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) ) #define IS_CALLOC( str ) ( str[0] == 'c' ) +#ifdef MEM_COUNT_DETAILS +const char *csv_filename = "mem_analysis.csv"; +static FILE *fid_csv_filename = NULL; +#endif + typedef struct { char function_name[MAX_FUNCTION_NAME_LENGTH + 1]; @@ -687,6 +686,25 @@ void reset_mem( Counting_Size cnt_size ) size_wc_inter_frame_heap = 0; location_wc_inter_frame_heap = -1; +#ifdef MEM_COUNT_DETAILS + /* Check, if the .csv file has already been opened */ + if ( fid_csv_filename == NULL ) + { + fid_csv_filename = fopen( csv_filename, "wb" ); + + if ( fid_csv_filename == NULL ) + { + fprintf( stderr, "\nCannot open %s!\n\n", csv_filename ); + exit( -1 ); + } + } + else + { + /* reset file */ + rewind( fid_csv_filename ); + } +#endif + return; } @@ -959,6 +977,11 @@ void *mem_alloc( ptr_record->block_size = size; ptr_record->total_block_size += size; +#ifdef MEM_COUNT_DETAILS + /* Export heap memory allocation record to the .csv file */ + fprintf( fid_csv_filename, "A,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); +#endif + if ( ptr_record->frame_allocated != -1 ) { fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Attempt to Allocate the Same Memory Block with Freeing it First!" ); @@ -1294,6 +1317,11 @@ void mem_free( const char *func_name, int func_lineno, void *ptr ) /* Check, if Out-Of-Bounds Access has been Detected */ ptr_record->OOB_Flag = mem_check_OOB( ptr_record ); +#ifdef MEM_COUNT_DETAILS + /* Export heap memory de-allocation record to the .csv file */ + fprintf( fid_csv_filename, "D,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); +#endif + /* De-Allocate Memory Block */ tmp_ptr = (char *) ptr; tmp_ptr -= BLOCK_ROUNDING; @@ -1332,11 +1360,11 @@ void mem_free( const char *func_name, int func_lineno, void *ptr ) void update_mem( void ) { int i, j, flag_alloc = -1, i_record; - int32_t size_current_intra_frame_heap; + int size_current_intra_frame_heap; int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap; allocator_record *ptr_record; - /* process the heap allocation call tree */ + /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */ n_items_current_intra_frame_heap = 0; size_current_intra_frame_heap = 0; for ( i = 0; i < heap_allocation_call_tree_size; i++ ) @@ -1364,7 +1392,7 @@ void update_mem( void ) memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) ); } - /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ + /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ if ( i_record == 0 ) { flag_alloc = 1; @@ -1384,23 +1412,7 @@ void update_mem( void ) list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record; size_current_intra_frame_heap += ptr_record->block_size; - /* check, if this is the new worst-case */ - if ( size_current_intra_frame_heap > size_wc_intra_frame_heap ) - { - if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap ) - { - /* resize list, if needed */ - max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; - list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) ); - } - - /* save to wc list */ - memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) ); - n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap; - size_wc_intra_frame_heap = size_current_intra_frame_heap; - location_wc_intra_frame_heap = update_cnt; - ptr_record->wc_heap_size_intra_frame = ptr_record->block_size; - } + /* no need to re-size the list -> the initially allocated size should be large enough */ } else { @@ -1451,23 +1463,6 @@ void update_mem( void ) list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record; size_current_inter_frame_heap += ptr_record->block_size; - - /* check, if this is the new worst-case */ - if ( size_current_inter_frame_heap > size_wc_inter_frame_heap ) - { - if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap ) - { - /* resize list, if needed */ - max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; - list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) ); - } - - memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) ); - n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap; - size_wc_inter_frame_heap = size_current_inter_frame_heap; - location_wc_inter_frame_heap = update_cnt; - ptr_record->wc_heap_size_inter_frame = ptr_record->block_size; - } } else { @@ -1490,9 +1485,60 @@ void update_mem( void ) } } + /* check, if this is the new worst-case for intra-frame heap memory */ + if ( size_current_intra_frame_heap > size_wc_intra_frame_heap ) + { + if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap ) + { + /* resize the list, if needed */ + max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) ); + } + + /* copy current-frame list to worst-case list */ + memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) ); + n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap; + size_wc_intra_frame_heap = size_current_intra_frame_heap; + location_wc_intra_frame_heap = update_cnt; + + /* update the wc numbers in all individual records */ + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + i_record = list_wc_intra_frame_heap[i]; + ptr_record = &( allocation_list[i_record] ); + ptr_record->wc_heap_size_intra_frame = ptr_record->block_size; + } + } + + /* check, if this is the new worst-case for inter-frame heap memory */ + if ( size_current_inter_frame_heap > size_wc_inter_frame_heap ) + { + if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap ) + { + /* resize list, if needed */ + max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) ); + } + + /* copy current-frame list to worst-case list */ + memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) ); + n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap; + size_wc_inter_frame_heap = size_current_inter_frame_heap; + location_wc_inter_frame_heap = update_cnt; + + /* update the wc numbers in all individual records */ + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + i_record = list_wc_inter_frame_heap[i]; + ptr_record = &( allocation_list[i_record] ); + ptr_record->wc_heap_size_inter_frame = ptr_record->block_size; + } + } + /* reset heap allocation call tree */ heap_allocation_call_tree_size = 0; + /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */ if ( list_current_intra_frame_heap ) { free( list_current_intra_frame_heap ); @@ -1607,7 +1653,7 @@ static void mem_count_summary( void ) if ( ptr_record->noccurances > 1 ) { - sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ( ptr_record->noccurances * ptr_record->wc_heap_size_intra_frame ) >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); } else { @@ -1636,7 +1682,7 @@ static void mem_count_summary( void ) continue; } ptr_record = &( allocation_list[index_record] ); - ptr_record->noccurances = 1; /* reset the counter because som blocks may be both, intra-frame and inter-frame */ + ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */ for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ ) { index = list_wc_inter_frame_heap[j]; @@ -1655,7 +1701,7 @@ static void mem_count_summary( void ) } /* Print Header */ - sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Maximum Size", "Usage" ); + sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Memory Size", "Usage" ); puts( buf ); length = strlen( buf ); sprintf( buf, "%0*d\n", (int) length - 1, 0 ); @@ -1690,11 +1736,11 @@ static void mem_count_summary( void ) sprintf( line_str, "%d", ptr_record->lineno ); /* prepare average usage & memory size strings */ - sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) ); + sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) ); if ( ptr_record->noccurances > 1 ) { - sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ( ptr_record->noccurances * ptr_record->wc_heap_size_inter_frame ) >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); } else { @@ -1712,45 +1758,6 @@ static void mem_count_summary( void ) return; } -/*-------------------------------------------------------------------* - * export_mem() - * - * Export detailed (per-item) information about heap memory usage to a .csv file - *--------------------------------------------------------------------*/ - -void export_mem( const char *csv_filename ) -{ - int i; - static FILE *fid = NULL; - allocator_record *record_ptr; - - if ( csv_filename == NULL || strcmp( csv_filename, "" ) == 0 ) - { - return; - } - - /* Check, if the .csv file has already been opened */ - if ( fid == NULL ) - { - fid = fopen( csv_filename, "wb" ); - - if ( fid == NULL ) - { - fprintf( stderr, "\nCannot open %s!\n\n", csv_filename ); - exit( -1 ); - } - } - - /* Export individual heap memory records to a .csv file */ - for ( i = 0; i < Num_Records; i++ ) - { - record_ptr = &( allocation_list[i] ); - fprintf( fid, "%s:%d,%d;", record_ptr->name, record_ptr->lineno, record_ptr->block_size ); - } - fprintf( fid, "\n" ); - - return; -} #endif /*-------------------------------------------------------------------* @@ -1901,6 +1908,13 @@ void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) free( list_wc_inter_frame_heap ); } +#ifdef MEM_COUNT_DETAILS + if ( fid_csv_filename != NULL ) + { + fclose( fid_csv_filename ); + } +#endif + return; } diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index 08597ad..989be87 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.h +++ b/src/wmc_tool/test_data/ref/wmc_auto.h @@ -1007,9 +1007,6 @@ void mem_free( const char *func_name, int func_lineno, void *ptr ); void reset_mem( Counting_Size cnt_size ); void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ); -#ifdef MEM_COUNT_DETAILS -void export_mem( const char *csv_filename ); -#endif int push_stack( const char *filename, const char *fctname ); int pop_stack( const char *filename, const char *fctname ); @@ -1031,7 +1028,6 @@ void reset_stack( void ); #define free_( ptr ) free( ptr ) #define reset_mem( cnt_size ) #define print_mem( Const_Data_PROM_Table ) -#define export_mem( csv_filename ) #define push_stack( file, fct ) #define pop_stack( file, fct ) From f4ff0980d4ac0bd40b2160df928dc37b128a866b Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 13 Sep 2023 15:00:07 +0200 Subject: [PATCH 15/67] fix crash when no #include is present in the .c file --- src/wmc_tool/c_parser.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index b775d4b..cf26b42 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -8056,6 +8056,12 @@ TOOL_ERROR Include_Header( /* Find the End of the Last Contiguous Preprocessor Directive Block (#include) */ ptr_end = Find_End_Preproc_Block(NULL, ParseTbl_ptr); + /* if no #include is present in the file set the pointer to the beginning of the file */ + if (ptr_end == NULL) + { + ptr_end = ParseCtx_ptr->File.Data; + } + /* store the pointer for later use */ if (ptr_end_preproc_block != NULL) { From 4df4658d09fb78cd30f1132480681400c366203a Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 13 Sep 2023 15:16:12 +0200 Subject: [PATCH 16/67] update version to 1.5 and year to 2023 --- src/wmc_tool/c_parser.cpp | 2 +- src/wmc_tool/c_parser.h | 2 +- src/wmc_tool/constants.h | 2 +- src/wmc_tool/output.cpp | 2 +- src/wmc_tool/output.h | 2 +- src/wmc_tool/parsing_defs.h | 2 +- src/wmc_tool/text_utils.cpp | 2 +- src/wmc_tool/text_utils.h | 2 +- src/wmc_tool/wmc_auto_c.txt | 2 +- src/wmc_tool/wmc_auto_h.txt | 2 +- src/wmc_tool/wmc_tool.cpp | 4 ++-- src/wmc_tool/wmc_tool.h | 4 ++-- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index cf26b42..f6bc28a 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -1,5 +1,5 @@ /* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file diff --git a/src/wmc_tool/c_parser.h b/src/wmc_tool/c_parser.h index db15eaf..fcdf810 100644 --- a/src/wmc_tool/c_parser.h +++ b/src/wmc_tool/c_parser.h @@ -1,5 +1,5 @@ /* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file diff --git a/src/wmc_tool/constants.h b/src/wmc_tool/constants.h index d75944b..1dbd913 100644 --- a/src/wmc_tool/constants.h +++ b/src/wmc_tool/constants.h @@ -1,5 +1,5 @@ /* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file diff --git a/src/wmc_tool/output.cpp b/src/wmc_tool/output.cpp index 685b905..ba43b4b 100644 --- a/src/wmc_tool/output.cpp +++ b/src/wmc_tool/output.cpp @@ -1,5 +1,5 @@ /* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file diff --git a/src/wmc_tool/output.h b/src/wmc_tool/output.h index 34ba4db..015dfd0 100644 --- a/src/wmc_tool/output.h +++ b/src/wmc_tool/output.h @@ -1,5 +1,5 @@ /* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file diff --git a/src/wmc_tool/parsing_defs.h b/src/wmc_tool/parsing_defs.h index d2863b2..ec2532d 100644 --- a/src/wmc_tool/parsing_defs.h +++ b/src/wmc_tool/parsing_defs.h @@ -1,5 +1,5 @@ /* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file diff --git a/src/wmc_tool/text_utils.cpp b/src/wmc_tool/text_utils.cpp index 5d2cdfc..b7d5596 100644 --- a/src/wmc_tool/text_utils.cpp +++ b/src/wmc_tool/text_utils.cpp @@ -1,5 +1,5 @@ /* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file diff --git a/src/wmc_tool/text_utils.h b/src/wmc_tool/text_utils.h index 3b99685..bfd1c44 100644 --- a/src/wmc_tool/text_utils.h +++ b/src/wmc_tool/text_utils.h @@ -1,5 +1,5 @@ /* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file diff --git a/src/wmc_tool/wmc_auto_c.txt b/src/wmc_tool/wmc_auto_c.txt index 58f024f..8851a0b 100644 --- a/src/wmc_tool/wmc_auto_c.txt +++ b/src/wmc_tool/wmc_auto_c.txt @@ -1,5 +1,5 @@ "/*\r\n" -" * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved.\r\n" +" * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved.\r\n" " *\r\n" " * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n" " * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n" diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index 6a36806..8284b88 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -1,5 +1,5 @@ "/*\r\n" -" * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved.\r\n" +" * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved.\r\n" " *\r\n" " * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n" " * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n" diff --git a/src/wmc_tool/wmc_tool.cpp b/src/wmc_tool/wmc_tool.cpp index fd10202..e9300e6 100644 --- a/src/wmc_tool/wmc_tool.cpp +++ b/src/wmc_tool/wmc_tool.cpp @@ -1,5 +1,5 @@ /* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file @@ -1139,7 +1139,7 @@ int main( int argc, char *argv[] ) Print("\n" "WMC Tool (WMOPS Automatic Instrumentation Tool) v%s - %s\n" "\n" - "(C) 2022 copyright VoiceAge Corporation. All Rights Reserved.\n" + "(C) 2023 copyright VoiceAge Corporation. All Rights Reserved.\n" "\n" "This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\n" "is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\n" diff --git a/src/wmc_tool/wmc_tool.h b/src/wmc_tool/wmc_tool.h index cda8782..95d961e 100644 --- a/src/wmc_tool/wmc_tool.h +++ b/src/wmc_tool/wmc_tool.h @@ -1,5 +1,5 @@ /* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file @@ -19,7 +19,7 @@ * Switches *-------------------------------------------------------------------*/ -#define WMC_TOOL_VERSION_NO "1.4" /* Current version */ +#define WMC_TOOL_VERSION_NO "1.5" /* Current version */ /*#define DEBUG_PRINT*/ /* For debugging purposes */ /*-------------------------------------------------------------------* From 0c6472c673889300ba43a5475186ad9dd29916ff Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Thu, 14 Sep 2023 14:23:55 +0200 Subject: [PATCH 17/67] introduce -f fps command-line option for setting the FRAMES_PER_SECOND constant --- src/wmc_tool/test_data/ref/wmc_auto.c | 3853 +++++++++++++------------ src/wmc_tool/test_data/ref/wmc_auto.h | Bin 42791 -> 43832 bytes src/wmc_tool/wmc_tool.cpp | 131 +- 3 files changed, 2009 insertions(+), 1975 deletions(-) diff --git a/src/wmc_tool/test_data/ref/wmc_auto.c b/src/wmc_tool/test_data/ref/wmc_auto.c index b86bc25..aefb696 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.c +++ b/src/wmc_tool/test_data/ref/wmc_auto.c @@ -1,1926 +1,1927 @@ -/* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. - * - * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, - * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file - * or refer to ITU-T Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS". - * - * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor - * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software - * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE. - * - * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca) - */ - -#include -#include -#include -#include -#include - -#ifndef _MSC_VER -#include -#include -#else -#include -#endif - -#include "wmc_auto.h" - - -#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */ - -#ifdef WMOPS - -/*-------------------------------------------------------------------* - * Complexity counting tool - *--------------------------------------------------------------------*/ - -#define MAX_RECORDS 1024 -#define MAX_CHAR 64 -#define MAX_STACK 64 -#define DOUBLE_MAX 0x80000000 - -struct wmops_record -{ - char label[MAX_CHAR]; - long call_number; - long update_cnt; - int call_tree[MAX_RECORDS]; - double start_selfcnt; - double current_selfcnt; - double max_selfcnt; - double min_selfcnt; - double tot_selfcnt; - double start_cnt; /* The following take into account the decendants */ - double current_cnt; - double max_cnt; - double min_cnt; - double tot_cnt; -#ifdef WMOPS_WC_FRAME_ANALYSIS - int32_t current_call_number; - double wc_cnt; - double wc_selfcnt; - int32_t wc_call_number; -#endif -}; - -double ops_cnt; -double prom_cnt; -double inst_cnt[NUM_INST]; - -static struct wmops_record wmops[MAX_RECORDS]; -static int stack[MAX_STACK]; -static int sptr; -static int num_records; -static int current_record; -static long update_cnt; -static double start_cnt; -static double max_cnt; -static double min_cnt; -static double inst_cnt_wc[NUM_INST]; -static long fnum_cnt_wc; - -static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0; - - -void reset_wmops( void ) -{ - int i, j; - - for ( i = 0; i < MAX_RECORDS; i++ ) - { - strcpy( &wmops[i].label[0], "\0" ); - wmops[i].call_number = 0; - wmops[i].update_cnt = 0; - for ( j = 0; j < MAX_RECORDS; j++ ) - { - wmops[i].call_tree[j] = -1; - } - wmops[i].start_selfcnt = 0.0; - wmops[i].current_selfcnt = 0.0; - wmops[i].max_selfcnt = 0.0; - wmops[i].min_selfcnt = DOUBLE_MAX; - wmops[i].tot_selfcnt = 0.0; - wmops[i].start_cnt = 0.0; - wmops[i].current_cnt = 0.0; - wmops[i].max_cnt = 0.0; - wmops[i].min_cnt = DOUBLE_MAX; - wmops[i].tot_cnt = 0.0; -#ifdef WMOPS_WC_FRAME_ANALYSIS - wmops[i].wc_cnt = 0.0; - wmops[i].wc_selfcnt = 0.0; - wmops[i].current_call_number = 0; -#endif - } - - for ( i = 0; i < MAX_STACK; i++ ) - { - stack[i] = -1; - } - sptr = 0; - num_records = 0; - current_record = -1; - update_cnt = 0; - - max_cnt = 0.0; - min_cnt = DOUBLE_MAX; - start_cnt = 0.0; - ops_cnt = 0.0; -} - - -void push_wmops( const char *label ) -{ - int new_flag; - int i, j; - - /* Check if new function record label */ - new_flag = 1; - for ( i = 0; i < num_records; i++ ) - { - if ( strcmp( wmops[i].label, label ) == 0 ) - { - new_flag = 0; - break; - } - } - - /* Configure new record */ - if ( new_flag ) - { - if ( num_records >= MAX_RECORDS ) - { - fprintf( stdout, "push_wmops(): exceeded MAX_RECORDS count.\n\n" ); - exit( -1 ); - } - strcpy( wmops[i].label, label ); - num_records++; - } - - /* Push current context onto stack */ - if ( current_record >= 0 ) - { - if ( sptr >= MAX_STACK ) - { - fprintf( stdout, "\r push_wmops(): stack exceeded, try inreasing MAX_STACK\n" ); - exit( -1 ); - } - stack[sptr++] = current_record; - - /* accumulate op counts */ - wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; - - /* update call tree */ - for ( j = 0; j < MAX_RECORDS; j++ ) - { - if ( wmops[i].call_tree[j] == current_record ) - { - break; - } - else if ( wmops[i].call_tree[j] == -1 ) - { - wmops[i].call_tree[j] = current_record; - break; - } - } - } - - /* init current record */ - current_record = i; - wmops[current_record].start_selfcnt = ops_cnt; - wmops[current_record].start_cnt = ops_cnt; - wmops[current_record].call_number++; -#ifdef WMOPS_WC_FRAME_ANALYSIS - wmops[current_record].current_call_number++; -#endif - - return; -} - - -void pop_wmops( void ) -{ - - /* Check for underflow */ - if ( current_record < 0 ) - { - fprintf( stdout, "\r pop_wmops(): stack underflow, too many calls to pop_wmops()\n" ); - exit( -1 ); - } - - /* update count of current record */ - wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; - wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt; - - /* Get back previous context from stack */ - if ( sptr > 0 ) - { - current_record = stack[--sptr]; - wmops[current_record].start_selfcnt = ops_cnt; - } - else - { - current_record = -1; - } - - return; -} - - -void update_wmops( void ) -{ - int i; - double current_cnt; -#ifdef WMOPS_PER_FRAME - static FILE *fid = NULL; - const char filename[] = "wmops_analysis"; - float tmpF; -#endif - - if ( sptr != 0 ) - { - fprintf( stdout, "update_wmops(): Stack must be empty!\n" ); - exit( -1 ); - } - -#ifdef WMOPS_PER_FRAME - /* Check, if the output file has already been opened */ - if ( fid == NULL ) - { - fid = fopen( filename, "wb" ); - - if ( fid == NULL ) - { - fprintf( stderr, "\nCannot open %s!\n\n", filename ); - exit( -1 ); - } - } - - /* Write current complexity to the external file */ - tmpF = (float) ( FAC * wmops[0].current_cnt ); - fwrite( &tmpF, sizeof( float ), 1, fid ); -#endif - -#ifdef WMOPS_WC_FRAME_ANALYSIS - if ( ops_cnt - start_cnt > max_cnt ) - { - for ( i = 0; i < num_records; i++ ) - { - wmops[i].wc_cnt = wmops[i].current_cnt; - wmops[i].wc_selfcnt = wmops[i].current_selfcnt; - wmops[i].wc_call_number = wmops[i].current_call_number; - } - } -#endif - - for ( i = 0; i < num_records; i++ ) - { - wmops[i].tot_selfcnt += wmops[i].current_selfcnt; - wmops[i].tot_cnt += wmops[i].current_cnt; - - if ( wmops[i].current_selfcnt > 0 ) - { - if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt ) - { - wmops[i].max_selfcnt = wmops[i].current_selfcnt; - } - - if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt ) - { - wmops[i].min_selfcnt = wmops[i].current_selfcnt; - } - } - - wmops[i].current_selfcnt = 0; - - if ( wmops[i].current_cnt > 0 ) - { - if ( wmops[i].current_cnt > wmops[i].max_cnt ) - { - wmops[i].max_cnt = wmops[i].current_cnt; - } - - if ( wmops[i].current_cnt < wmops[i].min_cnt ) - { - wmops[i].min_cnt = wmops[i].current_cnt; - } - - wmops[i].update_cnt++; - } - - wmops[i].current_cnt = 0; -#ifdef WMOPS_WC_FRAME_ANALYSIS - wmops[i].current_call_number = 0; -#endif - } - - current_cnt = ops_cnt - start_cnt; - if ( current_cnt > max_cnt ) - { - max_cnt = current_cnt; - - for ( i = 0; i < NUM_INST; i++ ) - { - inst_cnt_wc[i] = inst_cnt[i]; - } - - fnum_cnt_wc = update_cnt + 1; - } - - if ( current_cnt < min_cnt ) - { - min_cnt = current_cnt; - } - - for ( i = 0; i < NUM_INST; i++ ) - { - inst_cnt[i] = 0.0; - } - - start_cnt = ops_cnt; - - /* increment frame counter */ - update_cnt++; - - return; -} - - -void print_wmops( void ) -{ - int i; - - char *sfmts = "%20s %8s %8s %7s %7s\n"; - char *dfmts = "%20s %8.2f %8.3f %7.3f %7.3f\n"; - char *sfmt = "%20s %8s %8s %7s %7s %7s %7s %7s\n"; - char *dfmt = "%20s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n"; - -#ifdef WMOPS_WC_FRAME_ANALYSIS - int j, label_len, max_label_len; - char *sfmtt = "%20s %4s %15s\n"; - char *dfmtt = "%20s %4d "; -#endif - - fprintf( stdout, "\n\n --- Complexity analysis [WMOPS] --- \n\n" ); - - fprintf( stdout, "%54s %23s\n", "|------ SELF ------|", "|--- CUMULATIVE ---|" ); - fprintf( stdout, sfmt, " routine", " calls", " min ", " max ", " avg ", " min ", " max ", " avg " ); - fprintf( stdout, sfmt, "---------------", "------", "------", "------", "------", "------", "------", "------" ); - - for ( i = 0; i < num_records; i++ ) - { - fprintf( stdout, dfmt, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt, - wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt, - FAC * wmops[i].max_selfcnt, - wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt, - wmops[i].min_cnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_cnt, - FAC * wmops[i].max_cnt, - wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt ); - } - - fprintf( stdout, sfmts, "---------------", "------", "------", "------", "------" ); - fprintf( stdout, dfmts, "total", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt ); - fprintf( stdout, "\n" ); - -#ifdef WMOPS_WC_FRAME_ANALYSIS - /* calculate maximum label length for compact prinout */ - max_label_len = 0; - for ( i = 0; i < num_records; i++ ) - { - label_len = strlen( wmops[i].label ); - if ( label_len > max_label_len ) - { - max_label_len = label_len; - } - } - max_label_len += 4; - - fprintf( stdout, "\nComplexity analysis for the worst-case frame %ld:\n", fnum_cnt_wc ); - fprintf( stdout, "%*s %8s %10s %12s\n", max_label_len, " routine", " calls", " SELF", " CUMULATIVE" ); - fprintf( stdout, "%*s %8s %10s %10s\n", max_label_len, "---------------", "------", "------", "----------" ); - - for ( i = 0; i < num_records; i++ ) - { - fprintf( stdout, "%*s %8d %10.3f %12.3f\n", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt ); - } - - fprintf( stdout, "\nCall Tree:\n\n" ); - fprintf( stdout, sfmtt, " function", "num", "called by: " ); - fprintf( stdout, sfmtt, "---------------", "---", "--------------" ); - - for ( i = 0; i < num_records; i++ ) - { - fprintf( stdout, dfmtt, wmops[i].label, i ); - for ( j = 0; wmops[i].call_tree[j] != -1; j++ ) - { - if ( j != 0 ) - { - fprintf( stdout, ", " ); - } - fprintf( stdout, "%d", wmops[i].call_tree[j] ); - } - fprintf( stdout, "\n" ); - } - - fprintf( stdout, sfmtt, "---------------", "---", "--------------" ); - fprintf( stdout, "\n\n" ); - - fprintf( stdout, "\nInstruction type analysis for the worst-case frame %ld:\n\n", fnum_cnt_wc ); /* added -- JPA */ - for ( i = 0; i < NUM_INST; i++ ) - { - switch ( (enum instructions) i ) - { - case _ADD: - fprintf( stdout, "\tAdds: %12.1f\n", inst_cnt_wc[i] ); - break; - case _ABS: - fprintf( stdout, "\tAbsolutes: %12.1f\n", inst_cnt_wc[i] ); - break; - case _MULT: - fprintf( stdout, "\tMultiplies: %12.1f\n", inst_cnt_wc[i] ); - break; - case _MAC: - fprintf( stdout, "\tMACs: %12.1f\n", inst_cnt_wc[i] ); - break; - case _MOVE: - fprintf( stdout, "\tMoves: %12.1f\n", inst_cnt_wc[i] ); - break; - case _STORE: - fprintf( stdout, "\tStores: %12.1f\n", inst_cnt_wc[i] ); - break; - case _LOGIC: - fprintf( stdout, "\tLogicals: %12.1f\n", inst_cnt_wc[i] ); - break; - case _SHIFT: - fprintf( stdout, "\tShifts: %12.1f\n", inst_cnt_wc[i] ); - break; - case _BRANCH: - fprintf( stdout, "\tBranches: %12.1f\n", inst_cnt_wc[i] ); - break; - case _DIV: - fprintf( stdout, "\tDivisions: %12.1f\n", inst_cnt_wc[i] ); - break; - case _SQRT: - fprintf( stdout, "\tSquare Root: %12.1f\n", inst_cnt_wc[i] ); - break; - case _TRANS: - fprintf( stdout, "\tTrans: %12.1f\n", inst_cnt_wc[i] ); - break; - case _FUNC: - fprintf( stdout, "\tFunc Call: %12.1f\n", inst_cnt_wc[i] ); - break; - case _LOOP: - fprintf( stdout, "\tLoop Init: %12.1f\n", inst_cnt_wc[i] ); - break; - case _INDIRECT: - fprintf( stdout, "\tIndirect Addr: %12.1f\n", inst_cnt_wc[i] ); - break; - case _PTR_INIT: - fprintf( stdout, "\tPointer Init: %12.1f\n", inst_cnt_wc[i] ); - break; - case _TEST: - fprintf( stdout, "\tExtra condit.: %12.1f\n", inst_cnt_wc[i] ); - break; - case _POWER: - fprintf( stdout, "\tExponential: %12.1f\n", inst_cnt_wc[i] ); - break; - case _LOG: - fprintf( stdout, "\tLogarithm: %12.1f\n", inst_cnt_wc[i] ); - break; - case _MISC: - fprintf( stdout, "\tAll other op.: %12.1f\n", inst_cnt_wc[i] ); - break; - default: - fprintf( stdout, "\tERROR: Invalid instruction type: %d\n\n", i ); - } - } -#endif - - return; -} - - -/*-------------------------------------------------------------------* - * Memory counting tool measuring RAM usage (stack and heap) - * - * Maximum RAM is measured by monitoring the total allocated memory (stack and heap) in each frame. - * - * Maximum stack is measured by monitoring the difference between the 'top' and 'bottom' of the stack. The 'bottom' of the stack is updated in each function - * with a macro 'func_start_' which is inserted automatically to all functions during the instrumentation process. - * - * Maximum heap is measured by summing the sizes of all memory blocks allocated by malloc() or calloc() and deallocated by free(). The maximum heap size is - * updated each time when the macros malloc_() or calloc_() is invoked. The macros 'malloc_ and calloc_' are inserted automatically during the instrumentation process. - * As part of heap measurements, intra-frame heap and inter-frame heap are measured separately. Intra-frame heap refers to heap memory which is allocated and deallocated - * within a single frame. Inter-frame heap, on the contrary, refers to heap memory which is reserved for more than one frame. - * - * In order to run the memory counting tool the function reset_mem(cnt_size) must be called at the beginning of the encoding/decoding process. - * The unit in which memory consumption is reported is set via the parameter 'cnt_size'. It can be set to 0 (bytes), 1 (32b words) or 2 (64b words). - * At the end of the encoding/decoding process, 'print_mem()' function may be called to print basic information about memory consumption. If the macro 'MEM_COUNT_DETAILS' - * is activated, detailed information is printed - * - * The macro 'WMOPS' needs to be activated to enable memory counting. To avoid the instrumentation of malloc()/calloc()/free() calls, use - * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free(). - *--------------------------------------------------------------------*/ - -#define MAX_RECORDABLE_CALLS 100 -#define MAX_FUNCTION_NAME_LENGTH 35 /* Maximum length that the function string will be truncated to */ -#define MAX_PARAMS_LENGTH 50 /* Maximum length that the parameter string will be truncated to */ -#define MAX_NUM_RECORDS 300 /* Initial maximum number of memory records -> mightb be increased during runtime, if needed */ -#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of memory records, increase the number of records by this number */ - -/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using - a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */ -#ifdef MEM_ALIGN_64BITS -#define BLOCK_ROUNDING 8 /* Align on 64 Bits */ -#else -#define BLOCK_ROUNDING 4 /* Align on 32 Bits */ -#endif - -#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) ) - -#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */ -#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */ -#define OOB_START 0x1 /* Flag indicating out-of-bounds access before memory block */ -#define OOB_END 0x2 /* Flag indicating out-of-bounds access after memory block */ - -#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) ) -#define IS_CALLOC( str ) ( str[0] == 'c' ) - -#ifdef MEM_COUNT_DETAILS -const char *csv_filename = "mem_analysis.csv"; -static FILE *fid_csv_filename = NULL; -#endif - -typedef struct -{ - char function_name[MAX_FUNCTION_NAME_LENGTH + 1]; - int16_t *stack_ptr; -} caller_info; - -caller_info stack_callers[2][MAX_RECORDABLE_CALLS]; - -typedef struct -{ - char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */ - char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */ - unsigned long hash; - int lineno; - void *block_ptr; - int block_size; - unsigned long total_block_size; /* Cumulative sum of the allocated size in the session */ - unsigned long total_used_size; /* Cumulative sum of the used size in the session */ - int wc_heap_size_intra_frame; /* Worst-Case Intra-Frame Heap Size */ - int wc_heap_size_inter_frame; /* Worst-Case Inter-Frame Heap Size */ - int frame_allocated; /* Frame number in which the Memory Block has been allocated (-1 if not allocated at the moment) */ - int OOB_Flag; - int noccurances; /* Number of times that the memory block has been allocated in a frame */ -} allocator_record; - -allocator_record *allocation_list = NULL; - -static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */ -static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */ -static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */ -static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */ -static int32_t wc_ram_size, wc_ram_frame; -static int32_t current_heap_size; -static int current_calls = 0; -static char location_max_stack[256] = "undefined"; -static int Num_Records, Max_Num_Records; -static size_t Stat_Cnt_Size = USE_BYTES; -static const char *Count_Unit[] = { "bytes", "words", "words" }; - -static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap; -static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap; -static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap; - -/* Local Functions */ -static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str ); -allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record ); -static void *mem_alloc_block( size_t size, const char *size_str ); - -/*-------------------------------------------------------------------* - * reset_mem() - * - * Initialize/reset memory counting tool (stack and heap) - *--------------------------------------------------------------------*/ - -void reset_mem( Counting_Size cnt_size ) -{ - int16_t something; - size_t tmp_size; - - /* initialize stack pointers */ - ptr_base_stack = &something; - ptr_max_stack = ptr_base_stack; - ptr_current_stack = ptr_base_stack; - - Stat_Cnt_Size = cnt_size; - - /* Check, if sizeof(int32_t) is 4 bytes */ - tmp_size = sizeof( int32_t ); - if ( tmp_size != 4 ) - { - fprintf( stderr, "Error: Expecting 'int32_t' to be a 32 Bits Integer!" ); - exit( -1 ); - } - - /* create allocation list for malloc() memory blocks */ - if ( allocation_list == NULL ) - { - allocation_list = malloc( MAX_NUM_RECORDS * sizeof( allocator_record ) ); - } - - if ( allocation_list == NULL ) - { - fprintf( stderr, "Error: Unable to Create List of Memory Blocks!" ); - exit( -1 ); - } - - Num_Records = 0; - Max_Num_Records = MAX_NUM_RECORDS; - - wc_ram_size = 0; - wc_ram_frame = -1; - current_heap_size = 0; - - /* heap allocation tree */ - heap_allocation_call_tree_max_size = MAX_NUM_RECORDS; - if ( heap_allocation_call_tree == NULL ) - { - heap_allocation_call_tree = (int *) malloc( heap_allocation_call_tree_max_size * sizeof( int ) ); - memset( heap_allocation_call_tree, -1, heap_allocation_call_tree_max_size * sizeof( int ) ); - } - heap_allocation_call_tree_size = 0; - - /* wc intra-frame heap */ - max_items_wc_intra_frame_heap = MAX_NUM_RECORDS; - if ( list_wc_intra_frame_heap == NULL ) - { - list_wc_intra_frame_heap = (int *) malloc( max_items_wc_intra_frame_heap * sizeof( int ) ); - memset( list_wc_intra_frame_heap, -1, max_items_wc_intra_frame_heap * sizeof( int ) ); - } - n_items_wc_intra_frame_heap = 0; - size_wc_intra_frame_heap = 0; - location_wc_intra_frame_heap = -1; - - /* current inter-frame heap */ - max_items_current_inter_frame_heap = MAX_NUM_RECORDS; - if ( list_current_inter_frame_heap == NULL ) - { - list_current_inter_frame_heap = (int *) malloc( max_items_current_inter_frame_heap * sizeof( int ) ); - memset( list_current_inter_frame_heap, -1, max_items_current_inter_frame_heap * sizeof( int ) ); - } - n_items_current_inter_frame_heap = 0; - size_current_inter_frame_heap = 0; - - /* wc inter-frame heap */ - max_items_wc_inter_frame_heap = MAX_NUM_RECORDS; - if ( list_wc_inter_frame_heap == NULL ) - { - list_wc_inter_frame_heap = (int *) malloc( max_items_wc_inter_frame_heap * sizeof( int ) ); - memset( list_wc_inter_frame_heap, -1, max_items_wc_inter_frame_heap * sizeof( int ) ); - } - n_items_wc_inter_frame_heap = 0; - size_wc_inter_frame_heap = 0; - location_wc_inter_frame_heap = -1; - -#ifdef MEM_COUNT_DETAILS - /* Check, if the .csv file has already been opened */ - if ( fid_csv_filename == NULL ) - { - fid_csv_filename = fopen( csv_filename, "wb" ); - - if ( fid_csv_filename == NULL ) - { - fprintf( stderr, "\nCannot open %s!\n\n", csv_filename ); - exit( -1 ); - } - } - else - { - /* reset file */ - rewind( fid_csv_filename ); - } -#endif - - return; -} - -/*-------------------------------------------------------------------* - * reset_stack() - * - * Reset stack pointer - *--------------------------------------------------------------------*/ - -void reset_stack( void ) -{ - int16_t something; - - /* initialize/reset stack pointers */ - ptr_base_stack = &something; - ptr_max_stack = ptr_base_stack; - ptr_current_stack = ptr_base_stack; - - return; -} - -/*-------------------------------------------------------------------* - * push_stack() - * - * Check the current stack pointer and update the maximum stack pointer, if new maximum found. - *--------------------------------------------------------------------*/ - -int push_stack( const char *filename, const char *fctname ) -{ - int16_t something; - int32_t current_stack_size; - - ptr_current_stack = &something; - - (void) *filename; /* to avoid compilation warning */ - - /* Is there room to save the caller's information? */ - if ( current_calls >= MAX_RECORDABLE_CALLS ) - { /* No */ - fprintf( stderr, "No more room to store call stack info. Please increase MAX_RECORDABLE_CALLS" ); - exit( -1 ); - } - - /* Valid Function Name? */ - if ( fctname[0] == 0 ) - { /* No */ - fprintf( stderr, "Invalid function name for call stack info." ); - exit( -1 ); - } - - /* Save the Name of the Calling Function in the Table */ - strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FUNCTION_NAME_LENGTH ); - stack_callers[0][current_calls].function_name[MAX_FUNCTION_NAME_LENGTH] = 0; /* Nul Terminate */ - - /* Save the Stack Pointer */ - stack_callers[0][current_calls].stack_ptr = ptr_current_stack; - - /* Increase Stack Calling Tree Level */ - current_calls++; - - /* Is this the First Time or the Worst Case? */ - if ( ptr_current_stack < ptr_max_stack || ptr_max_stack == NULL ) - { /* Yes */ - /* Save Info about it */ - ptr_max_stack = ptr_current_stack; - - wc_stack_frame = update_cnt; /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */ - strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 ); - location_max_stack[sizeof( location_max_stack ) - 1] = '\0'; - - /* Save Call Tree */ - memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls ); - - /* Terminate the List (Unless Full) */ - if ( current_calls < MAX_RECORDABLE_CALLS ) - { - stack_callers[1][current_calls].function_name[0] = 0; - } - } - - /* Check, if This is the New Worst-Case RAM (stack + heap) */ - current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); - - if ( current_stack_size < 0 ) - { - /* prevent negative stack size */ - current_stack_size = 0; - } - - if ( current_stack_size + current_heap_size > wc_ram_size ) - { - wc_ram_size = current_stack_size + current_heap_size; - wc_ram_frame = update_cnt; - } - - return 0 /* for Now */; -} - -/*-------------------------------------------------------------------* - * pop_stack() - * - * Remove stack caller entry from the list - *--------------------------------------------------------------------*/ - -int pop_stack( const char *filename, const char *fctname ) -{ - caller_info *caller_info_ptr; - - (void) *filename; /* to avoid compilation warning */ - - /* Decrease Stack Calling */ - current_calls--; - - /* Get Pointer to Caller Information */ - caller_info_ptr = &stack_callers[0][current_calls]; - - /* Check, if Names Match */ - if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 ) - { - fprintf( stderr, "Invalid usage of pop_stack()" ); - exit( -1 ); - } - - /* Erase Entry */ - caller_info_ptr->function_name[0] = 0; - - /* Retrieve previous stack pointer */ - if ( current_calls == 0 ) - { - ptr_current_stack = ptr_base_stack; - } - else - { - ptr_current_stack = stack_callers[0][current_calls - 1].stack_ptr; - } - - return 0 /* for Now */; -} - -#ifdef MEM_COUNT_DETAILS -/*-------------------------------------------------------------------* - * print_stack_call_tree() - * - * Print detailed information about worst-case stack usage - *--------------------------------------------------------------------*/ - -static void print_stack_call_tree( void ) -{ - caller_info *caller_info_ptr; - int call_level; - char fctname[MAX_FUNCTION_NAME_LENGTH + 1]; - - fprintf( stdout, "\nList of functions when maximum stack size is reached:\n\n" ); - - caller_info_ptr = &stack_callers[1][0]; - for ( call_level = 0; call_level < MAX_RECORDABLE_CALLS; call_level++ ) - { - /* Done? */ - if ( caller_info_ptr->function_name[0] == 0 ) - { - break; - } - - /* Print Name */ - strncpy( fctname, caller_info_ptr->function_name, MAX_FUNCTION_NAME_LENGTH ); - strcat( fctname, "()" ); - fprintf( stdout, "%-42s", fctname ); - - /* Print Stack Usage (Based on Difference) */ - if ( call_level != 0 ) - { - fprintf( stdout, "%lu %s\n", ( ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); - } - else - { - fprintf( stdout, "%lu %s\n", ( ( ptr_base_stack - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); - } - - /* Advance */ - caller_info_ptr++; - } - - fprintf( stdout, "\n" ); - - return; -} -#endif - - -/*-------------------------------------------------------------------* - * mem_alloc() - * - * Creates new record, stores auxiliary information about which function allocated the memory, line number, parameters, etc. - * Finally, it allocates physical memory using malloc() - * The function also updates worst-case heap size and worst-case RAM size - *--------------------------------------------------------------------*/ - -void *mem_alloc( - const char *func_name, - int func_lineno, - size_t size, - char *size_str /* the first char indicates m-alloc or c-alloc */ ) -{ - int index_record; - int32_t current_stack_size; - unsigned long hash; - allocator_record *ptr_record; - - if ( size == 0 ) - { - fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Size of Zero not Supported" ); - exit( -1 ); - } - - /* Search for an existing record (that has been de-allocated before) */ - index_record = 0; - while ( ( ptr_record = get_mem_record( &hash, func_name, func_lineno, size_str, &index_record ) ) != NULL ) - { - if ( ptr_record->frame_allocated == -1 ) - { - break; - } - else - { - index_record++; - } - } - - /* Create new record */ - if ( ptr_record == NULL ) - { - if ( Num_Records >= Max_Num_Records ) - { - /* There is no room for a new record -> reallocate memory */ - Max_Num_Records += MAX_NUM_RECORDS_REALLOC_STEP; - allocation_list = realloc( allocation_list, Max_Num_Records * sizeof( allocator_record ) ); - } - - ptr_record = &( allocation_list[Num_Records] ); - - /* Initialize new record */ - ptr_record->hash = hash; - ptr_record->noccurances = 0; - ptr_record->total_block_size = 0; - ptr_record->total_used_size = 0; - ptr_record->frame_allocated = -1; - ptr_record->OOB_Flag = 0; - ptr_record->wc_heap_size_intra_frame = -1; - ptr_record->wc_heap_size_inter_frame = -1; - - index_record = Num_Records; - Num_Records++; - } - - /* Allocate memory block for the new record, add signature before the beginning and after the memory block and fill it with magic value */ - ptr_record->block_ptr = mem_alloc_block( size, size_str ); - - if ( ptr_record->block_ptr == NULL ) - { - fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Cannot Allocate Memory!" ); - exit( -1 ); - } - - /* Save all auxiliary information about the memory block */ - strncpy( ptr_record->name, func_name, MAX_FUNCTION_NAME_LENGTH ); - ptr_record->name[MAX_FUNCTION_NAME_LENGTH] = '\0'; - strncpy( ptr_record->params, size_str, MAX_PARAMS_LENGTH ); /* Note: The size string starts with either 'm' or 'c' to indicate 'm'alloc or 'c'alloc */ - ptr_record->params[MAX_PARAMS_LENGTH] = '\0'; - ptr_record->lineno = func_lineno; - ptr_record->block_size = size; - ptr_record->total_block_size += size; - -#ifdef MEM_COUNT_DETAILS - /* Export heap memory allocation record to the .csv file */ - fprintf( fid_csv_filename, "A,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); -#endif - - if ( ptr_record->frame_allocated != -1 ) - { - fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Attempt to Allocate the Same Memory Block with Freeing it First!" ); - exit( -1 ); - } - - ptr_record->frame_allocated = update_cnt; /* Store the current frame number -> later it will be used to determine the total duration */ - - /* Update Heap Size in the current frame */ - current_heap_size += ptr_record->block_size; - - /* Check, if this is the new Worst-Case RAM (stack + heap) */ - current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); - if ( current_stack_size + current_heap_size > wc_ram_size ) - { - wc_ram_size = current_stack_size + current_heap_size; - wc_ram_frame = update_cnt; - } - - /* Add new entry to the heap allocation call tree */ - if ( heap_allocation_call_tree == NULL ) - { - fprintf( stderr, "Error: Heap allocation call tree not created!" ); - exit( -1 ); - } - - /* check, if the maximum size of the call tree has been reached -> resize if so */ - if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size ) - { - heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP; - heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) ); - } - - /* push new entry (positive number means push op, neagtive number means pop op; zero index must be converted to 0.01 :-) */ - heap_allocation_call_tree[heap_allocation_call_tree_size++] = index_record; - - return ptr_record->block_ptr; -} - -/*-------------------------------------------------------------------* - * mem_alloc_block() - * - * Physical allocation of memory using malloc(). Appends 'signature' before and after the block, - * pre-fills memory block with magic value - *--------------------------------------------------------------------*/ - -static void *mem_alloc_block( size_t size, const char *size_str ) -{ - size_t rounded_size; - void *block_ptr; - char *tmp_ptr; - size_t n, f; - int32_t fill_value; - int32_t *ptr32; - int32_t mask, temp; - - /* Round Up Block Size */ - rounded_size = ROUND_BLOCK_SIZE( size ); - - /* Allocate memory using the standard malloc() by adding room for Signature Values */ - block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 ); - - if ( block_ptr == NULL ) - { - return NULL; - } - - /* Add Signature Before the Start of the Block */ - ptr32 = (int32_t *) block_ptr; - n = N_32BITS_BLOCKS; - do - { - *ptr32++ = MAGIC_VALUE_OOB; - } while ( --n ); - - /* Fill Memory Block with Magic Value or 0 */ - fill_value = MAGIC_VALUE_USED; - if ( IS_CALLOC( size_str ) ) - { - fill_value = 0x00000000; - } - n = size / sizeof( int32_t ); - while ( n-- ) - { - *ptr32++ = fill_value; - } - - /* Fill the Reminder of the Memory Block - After Rounding */ - n = rounded_size - size; - f = n % sizeof( int32_t ); - if ( f != 0 ) - { - /* when filling with '0' need to adapt the magic value */ - /* shift by [1->24, 2->16, 3->8] */ - mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */ - temp = MAGIC_VALUE_OOB & mask; - if ( fill_value != 0x0 ) - { /* for malloc merge fill value */ - temp += ( ~mask ) & MAGIC_VALUE_USED; - } /* for calloc the code in (1) above already introduces zeros */ - *ptr32++ = temp; - } - n /= sizeof( int32_t ); - n += N_32BITS_BLOCKS; - - /* Add Signature After the End of Block */ - do - { - *ptr32++ = MAGIC_VALUE_OOB; - } while ( --n ); - - /* Adjust the Memory Block Pointer (Magic Value Before and After the Memory Block Requested) */ - tmp_ptr = (char *) block_ptr; - tmp_ptr += BLOCK_ROUNDING; - block_ptr = (void *) tmp_ptr; - - return block_ptr; -} - -/*-------------------------------------------------------------------* - * mem_set_usage() - * - * Calculates actual usage of memory block by checking the magic value that was used to pre-fill - * each memory block during its allocation - *--------------------------------------------------------------------*/ - -static int mem_set_usage( allocator_record *record_ptr ) -{ - int total_bytes_used; - - size_t n; - int32_t *ptr32; - char *ptr8; - size_t total_bytes; - int32_t fill_value; - - fill_value = MAGIC_VALUE_USED; - if ( ( record_ptr->params[0] ) == 'c' ) - { - fill_value = 0x00000000; - } - - total_bytes = record_ptr->block_size; - - /* Check 4 bytes at a time */ - ptr32 = (int32_t *) record_ptr->block_ptr; - total_bytes_used = 0; - for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- ) - { - if ( *ptr32++ != fill_value ) - { - total_bytes_used += sizeof( int32_t ); - } - } - - /* Check remaining bytes (If Applicable) 1 byte at a time */ - ptr8 = (char *) ptr32; - for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- ) - { - if ( *ptr8++ != (char) fill_value ) - { - total_bytes_used++; - } - - /* Update Value */ - fill_value >>= 8; - } - - return total_bytes_used; -} - -/*-------------------------------------------------------------------* - * mem_check_OOB() - * - * Checks, if out-of-bounds access has occured. This is done by inspecting the 'signature' value - * taht has been added before and after the memory block during its allocation - *--------------------------------------------------------------------*/ - -static unsigned int mem_check_OOB( allocator_record *record_ptr ) -{ - int32_t *ptr32; - unsigned int OOB_Flag = 0x0; - int32_t mask; - size_t i; - int f; - - ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS; - - /* Check the Signature at the Beginning of Memory Block */ - i = N_32BITS_BLOCKS; - do - { - if ( *ptr32++ ^ MAGIC_VALUE_OOB ) - { - OOB_Flag |= OOB_START; - } - } while ( --i ); - - /* Advance to End (Snap to lowest 32 Bits) */ - ptr32 += record_ptr->block_size / sizeof( int32_t ); - - /* Calculate Unused Space That has been added to get to the rounded Block Size */ - i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size; - - /* Partial Check of Signature at the End of Memory Block (for block size that has been rounded) */ - f = i % sizeof( int32_t ); - if ( f != 0 ) - { - mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); - if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask ) - { - OOB_Flag |= OOB_END; - } - } - - /* Full Check of Signature at the End of Memory Block, i.e. all 32 Bits (for the remainder after rounding) */ - i /= sizeof( int32_t ); - i += N_32BITS_BLOCKS; - do - { - if ( *ptr32++ ^ MAGIC_VALUE_OOB ) - { - OOB_Flag |= OOB_END; - } - } while ( --i ); - - return OOB_Flag; -} - -/*-------------------------------------------------------------------* - * malloc_hash() - * - * Calculate hash from function name, line number and malloc size - *--------------------------------------------------------------------*/ - -static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str ) -{ - unsigned long hash = 5381; - const char *ptr_str; - - ptr_str = func_name; - while ( ptr_str != NULL && *ptr_str != '\0' ) - { - hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */ - } - - hash = ( ( hash << 5 ) + hash ) + func_lineno; /* hash * 33 + func_lineno */ - - ptr_str = size_str; - while ( ptr_str != NULL && *ptr_str != '\0' ) - { - hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */ - } - - return hash; -} - -/*-------------------------------------------------------------------* - * get_mem_record() - * - * Search for memory record in the internal list, return NULL if not found - * Start from index_record - *--------------------------------------------------------------------*/ - -allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record ) -{ - int i; - - if ( *index_record < 0 || *index_record > Num_Records ) - { - return NULL; - } - - /* calculate hash */ - *hash = malloc_hash( func_name, func_lineno, size_str ); - - for ( i = *index_record; i < Num_Records; i++ ) - { - /* check, if memory block is not allocated at the moment and the hash matches */ - if ( allocation_list[i].block_ptr == NULL && *hash == allocation_list[i].hash ) - { - *index_record = i; - return &( allocation_list[i] ); - } - } - - /* not found */ - *index_record = -1; - return NULL; -} - - -/*-------------------------------------------------------------------* - * mem_free() - * - * This function de-allocatesd the memory block and frees the mphysical memory with free(). - * It also updates actual and average usage of the memory block. - * - * Note: The record is not removed from the list and may be reused later on in mem_alloc()! - *--------------------------------------------------------------------*/ - -void mem_free( const char *func_name, int func_lineno, void *ptr ) -{ - int i, index_record; - char *tmp_ptr; - allocator_record *ptr_record; - - /* Search for the Block Pointer in the List */ - ptr_record = NULL; - index_record = -1; - for ( i = 0; i < Num_Records; i++ ) - { - if ( ptr == allocation_list[i].block_ptr ) - { /* Yes, Found it */ - ptr_record = &( allocation_list[i] ); - index_record = i; - break; - } - } - - if ( ptr_record == NULL ) - { - fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Unable to Find Record Corresponding to the Allocated Memory Block!" ); - exit( -1 ); - } - - /* Update the Heap Size */ - current_heap_size -= ptr_record->block_size; - - /* Calculate the Actual Usage of the Memory Block (Look for Signature) */ - ptr_record->total_used_size += mem_set_usage( ptr_record ); - - /* Check, if Out-Of-Bounds Access has been Detected */ - ptr_record->OOB_Flag = mem_check_OOB( ptr_record ); - -#ifdef MEM_COUNT_DETAILS - /* Export heap memory de-allocation record to the .csv file */ - fprintf( fid_csv_filename, "D,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); -#endif - - /* De-Allocate Memory Block */ - tmp_ptr = (char *) ptr; - tmp_ptr -= BLOCK_ROUNDING; - ptr = (void *) tmp_ptr; - free( ptr ); - - /* Add new entry to the heap allocation call tree */ - if ( heap_allocation_call_tree == NULL ) - { - fprintf( stderr, "Error: Heap allocation call tree not created!" ); - exit( -1 ); - } - - /* check, if the maximum size of the call tree has been reached -> resize if so */ - if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size ) - { - heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP; - heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) ); - } - - heap_allocation_call_tree[heap_allocation_call_tree_size++] = -index_record; - - /* Reset memory block pointer (this is checked when updating wc intra-frame and inter-frame memory) */ - ptr_record->block_ptr = NULL; - - return; -} - - -/*-------------------------------------------------------------------* - * update_mem() - * - * This function updates the worst-case intra-frame memory and the worst-case inter-frame memory. - *--------------------------------------------------------------------*/ - -void update_mem( void ) -{ - int i, j, flag_alloc = -1, i_record; - int size_current_intra_frame_heap; - int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap; - allocator_record *ptr_record; - - /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */ - n_items_current_intra_frame_heap = 0; - size_current_intra_frame_heap = 0; - for ( i = 0; i < heap_allocation_call_tree_size; i++ ) - { - /* get the record */ - i_record = heap_allocation_call_tree[i]; - - if ( i_record > 0 ) - { - flag_alloc = 1; - } - else if ( i_record < 0 ) - { - flag_alloc = 0; - i_record = -i_record; - } - ptr_record = &( allocation_list[i_record] ); - - if ( ptr_record->frame_allocated == update_cnt && ptr_record->block_ptr == NULL ) - { - /* intra-frame heap memory */ - if ( list_current_intra_frame_heap == NULL ) - { - list_current_intra_frame_heap = (int *) malloc( heap_allocation_call_tree_size * sizeof( int ) ); - memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) ); - } - - /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ - if ( i_record == 0 ) - { - flag_alloc = 1; - for ( j = 0; j < n_items_current_intra_frame_heap; j++ ) - { - if ( list_current_intra_frame_heap[j] == i_record ) - { - flag_alloc = 0; - break; - } - } - } - - if ( flag_alloc ) - { - /* add to list */ - list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record; - size_current_intra_frame_heap += ptr_record->block_size; - - /* no need to re-size the list -> the initially allocated size should be large enough */ - } - else - { - /* remove from list */ - for ( j = 0; j < n_items_current_intra_frame_heap; j++ ) - { - if ( list_current_intra_frame_heap[j] == i_record ) - { - break; - } - } - memmove( &list_current_intra_frame_heap[j], &list_current_intra_frame_heap[j + 1], ( n_items_current_intra_frame_heap - j ) * sizeof( int ) ); - n_items_current_intra_frame_heap--; - size_current_intra_frame_heap -= ptr_record->block_size; - - /* reset block size */ - ptr_record->frame_allocated = -1; - ptr_record->block_size = 0; - } - } - else - { - /* inter-frame heap memory */ - - /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ - if ( i_record == 0 ) - { - flag_alloc = 1; - for ( j = 0; j < n_items_current_inter_frame_heap; j++ ) - { - if ( list_current_inter_frame_heap[j] == i_record ) - { - flag_alloc = 0; - break; - } - } - } - - if ( flag_alloc ) - { - /* add to list */ - if ( n_items_current_inter_frame_heap >= max_items_current_inter_frame_heap ) - { - /* resize list, if needed */ - max_items_current_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; - list_current_inter_frame_heap = realloc( list_current_inter_frame_heap, max_items_current_inter_frame_heap * sizeof( int ) ); - } - - list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record; - size_current_inter_frame_heap += ptr_record->block_size; - } - else - { - /* remove from list */ - for ( j = 0; j < n_items_current_inter_frame_heap; j++ ) - { - if ( list_current_inter_frame_heap[j] == i_record ) - { - break; - } - } - memmove( &list_current_inter_frame_heap[j], &list_current_inter_frame_heap[j + 1], ( n_items_current_inter_frame_heap - j ) * sizeof( int ) ); - n_items_current_inter_frame_heap--; - size_current_inter_frame_heap -= ptr_record->block_size; - - /* reset block size */ - ptr_record->frame_allocated = -1; - ptr_record->block_size = 0; - } - } - } - - /* check, if this is the new worst-case for intra-frame heap memory */ - if ( size_current_intra_frame_heap > size_wc_intra_frame_heap ) - { - if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap ) - { - /* resize the list, if needed */ - max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; - list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) ); - } - - /* copy current-frame list to worst-case list */ - memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) ); - n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap; - size_wc_intra_frame_heap = size_current_intra_frame_heap; - location_wc_intra_frame_heap = update_cnt; - - /* update the wc numbers in all individual records */ - for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) - { - i_record = list_wc_intra_frame_heap[i]; - ptr_record = &( allocation_list[i_record] ); - ptr_record->wc_heap_size_intra_frame = ptr_record->block_size; - } - } - - /* check, if this is the new worst-case for inter-frame heap memory */ - if ( size_current_inter_frame_heap > size_wc_inter_frame_heap ) - { - if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap ) - { - /* resize list, if needed */ - max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; - list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) ); - } - - /* copy current-frame list to worst-case list */ - memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) ); - n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap; - size_wc_inter_frame_heap = size_current_inter_frame_heap; - location_wc_inter_frame_heap = update_cnt; - - /* update the wc numbers in all individual records */ - for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) - { - i_record = list_wc_inter_frame_heap[i]; - ptr_record = &( allocation_list[i_record] ); - ptr_record->wc_heap_size_inter_frame = ptr_record->block_size; - } - } - - /* reset heap allocation call tree */ - heap_allocation_call_tree_size = 0; - - /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */ - if ( list_current_intra_frame_heap ) - { - free( list_current_intra_frame_heap ); - } - - return; -} - -#ifdef MEM_COUNT_DETAILS -/*-------------------------------------------------------------------* - * subst() - * - * Substitute character in string - *--------------------------------------------------------------------*/ - -static void subst( char *s, char from, char to ) -{ - while ( *s == from ) - { - *s++ = to; - } - - return; -} - - -/*-------------------------------------------------------------------* - * mem_count_summary() - * - * Print detailed (per-item) information about heap memory usage - *--------------------------------------------------------------------*/ - -static void mem_count_summary( void ) -{ - int i, j, index, index_record; - size_t length; - char buf[300], format_str[50], name_str[MAX_FUNCTION_NAME_LENGTH + 3], parms_str[MAX_PARAMS_LENGTH + 1], type_str[10], usage_str[20], size_str[20], line_str[10]; - allocator_record *ptr_record, *ptr; - - /* Prepare format string */ - sprintf( format_str, "%%-%ds %%5s %%6s %%-%ds %%20s %%6s ", MAX_FUNCTION_NAME_LENGTH, MAX_PARAMS_LENGTH ); - - if ( n_items_wc_intra_frame_heap > 0 ) - { - /* Intra-Frame Heap Size */ - fprintf( stdout, "\nList of memory blocks when maximum intra-frame heap size is reached:\n\n" ); - - /* Find duplicate records (same hash and worst-case heap size) */ - for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) - { - index_record = list_wc_intra_frame_heap[i]; - if ( index_record == -1 ) - { - continue; - } - - ptr_record = &( allocation_list[index_record] ); - for ( j = i + 1; j < n_items_wc_intra_frame_heap; j++ ) - { - index = list_wc_intra_frame_heap[j]; - if ( index == -1 ) - { - continue; - } - ptr = &( allocation_list[index] ); - - if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_intra_frame == ptr_record->wc_heap_size_intra_frame ) - { - ptr_record->noccurances++; - list_wc_intra_frame_heap[j] = -1; - } - } - } - - /* Print Header */ - sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Maximum Size", "Usage" ); - puts( buf ); - length = strlen( buf ); - sprintf( buf, "%0*d\n", (int) length - 1, 0 ); - subst( buf, '0', '-' ); - puts( buf ); - - for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) - { - index_record = list_wc_intra_frame_heap[i]; - - if ( index_record != -1 ) - { - /* get the record */ - ptr_record = &( allocation_list[index_record] ); - - /* prepare information strings */ - strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH ); - strcat( name_str, "()" ); - name_str[MAX_FUNCTION_NAME_LENGTH] = '\0'; - strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH ); - parms_str[MAX_PARAMS_LENGTH] = '\0'; - - if ( ptr_record->params[0] == 'm' ) - { - strcpy( type_str, "malloc" ); - } - else - { - strcpy( type_str, "calloc" ); - } - - sprintf( line_str, "%d", ptr_record->lineno ); - - /* prepare average usage & memory size strings */ - sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) ); - - if ( ptr_record->noccurances > 1 ) - { - sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); - } - else - { - sprintf( size_str, "%d %s", (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); - } - - sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str ); - puts( buf ); - } - } - - fprintf( stdout, "\n" ); - } - - if ( n_items_wc_inter_frame_heap > 0 ) - { - /* Inter-Frame Heap Size */ - fprintf( stdout, "\nList of memory blocks when maximum inter-frame heap size is reached:\n\n" ); - - /* Find duplicate records (same hash and worst-case heap size) */ - for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) - { - index_record = list_wc_inter_frame_heap[i]; - if ( index_record == -1 ) - { - continue; - } - ptr_record = &( allocation_list[index_record] ); - ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */ - for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ ) - { - index = list_wc_inter_frame_heap[j]; - if ( index == -1 ) - { - continue; - } - ptr = &( allocation_list[index] ); - - if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_inter_frame == ptr_record->wc_heap_size_inter_frame ) - { - ptr_record->noccurances++; - list_wc_inter_frame_heap[j] = -1; - } - } - } - - /* Print Header */ - sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Memory Size", "Usage" ); - puts( buf ); - length = strlen( buf ); - sprintf( buf, "%0*d\n", (int) length - 1, 0 ); - subst( buf, '0', '-' ); - puts( buf ); - - for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) - { - index_record = list_wc_inter_frame_heap[i]; - - if ( index_record != -1 ) - { - /* get the record */ - ptr_record = &( allocation_list[index_record] ); - - /* prepare information strings */ - strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH ); - strcat( name_str, "()" ); - name_str[MAX_FUNCTION_NAME_LENGTH] = '\0'; - strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH ); - parms_str[MAX_PARAMS_LENGTH] = '\0'; - - if ( ptr_record->params[0] == 'm' ) - { - strcpy( type_str, "malloc" ); - } - else - { - strcpy( type_str, "calloc" ); - } - - sprintf( line_str, "%d", ptr_record->lineno ); - - /* prepare average usage & memory size strings */ - sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) ); - - if ( ptr_record->noccurances > 1 ) - { - sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); - } - else - { - sprintf( size_str, "%d %s", (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); - } - - sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str ); - puts( buf ); - } - } - - fprintf( stdout, "\n" ); - } - - return; -} - -#endif - -/*-------------------------------------------------------------------* - * print_mem() - * - * Print information about ROM and RAM memory usage - *--------------------------------------------------------------------*/ - -void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) -{ - int i, nElem; - - fprintf( stdout, "\n\n --- Memory usage --- \n\n" ); - - if ( Const_Data_PROM_Table != NULL ) - { - nElem = 0; - while ( strcmp( Const_Data_PROM_Table[nElem].file_spec, "" ) != 0 ) - nElem++; - - for ( i = 0; i < nElem; i++ ) - { - fprintf( stdout, "Program ROM size (%s): %d instruction words\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size ); - } - - for ( i = 0; i < nElem; i++ ) - { - if ( Const_Data_PROM_Table[i].Get_Const_Data_Size_Func == NULL ) - { - fprintf( stdout, "Error: Cannot retrieve or calculate Table ROM size of (%s)!\n", Const_Data_PROM_Table[i].file_spec ); - } - - fprintf( stdout, "Table ROM (const data) size (%s): %d %s\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].Get_Const_Data_Size_Func() >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); - } - } - else - { - fprintf( stdout, "Program ROM size: not available\n" ); - fprintf( stdout, "Table ROM (const data) size: not available\n" ); - } - - if ( wc_ram_size > 0 ) - { - fprintf( stdout, "Maximum RAM (stack + heap) size: %d %s in frame %d\n", wc_ram_size >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], wc_ram_frame ); - } - else - { - fprintf( stdout, "Maximum RAM (stack + heap) size: not available\n" ); - } - - /* check, if the stack is empty */ - if ( ptr_current_stack != ptr_base_stack ) - { - fprintf( stderr, "Warning: Stack is not empty.\n" ); - } - - if ( ptr_base_stack - ptr_max_stack > 0 ) - { - fprintf( stdout, "Maximum stack size: %lu %s in frame %d\n", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], - wc_stack_frame ); - } - else - { - fprintf( stdout, "Maximum stack size: not available\n" ); - } - - /* last update of intra-frame memory and inter-frame memory, if needed */ - if ( heap_allocation_call_tree_size > 0 ) - { - update_mem(); - } - - /* check, if all memory blocks have been deallocated (freed) */ - for ( i = 0; i < Num_Records; i++ ) - { - if ( allocation_list[i].block_ptr != NULL ) - { - fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", allocation_list[i].name, allocation_list[i].lineno, "Error: Memory Block has not been De-Allocated with free()!" ); - exit( -1 ); - } - } - - if ( n_items_wc_intra_frame_heap > 0 ) - { - fprintf( stdout, "Maximum intra-frame heap size: %d %s in frame %d\n", size_wc_intra_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_intra_frame_heap ); - } - else - { - fprintf( stdout, "Maximum intra-frame heap size: 0\n" ); - } - - if ( n_items_wc_inter_frame_heap > 0 ) - { - fprintf( stdout, "Maximum inter-frame heap size: %d %s in frame %d\n", size_wc_inter_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_inter_frame_heap ); - } - else - { - fprintf( stdout, "Maximum inter-frame heap size: 0\n" ); - } - -#ifdef MEM_COUNT_DETAILS - /* Print detailed information about worst-case stack usage */ - if ( ptr_base_stack - ptr_max_stack > 0 ) - { - print_stack_call_tree(); - } - - /* Print detailed information about worst-case heap usage */ - mem_count_summary(); -#endif - - if ( Stat_Cnt_Size > 0 ) - { - fprintf( stdout, "\nNote: 1 word = %d bits\n", 8 << Stat_Cnt_Size ); - fprintf( stdout, "This is an optimistic estimate of memory consumption assuming that each variable type is stored with sizeof(type) bits\n" ); - } - - if ( n_items_wc_intra_frame_heap > 0 ) - { - fprintf( stdout, "Intra-frame heap memory is allocated and de-allocated in the same frame\n" ); - } - - /* De-allocate list of heap memory blocks */ - if ( allocation_list != NULL ) - { - free( allocation_list ); - } - - /* De-allocate heap allocation call tree */ - if ( heap_allocation_call_tree != NULL ) - { - free( heap_allocation_call_tree ); - } - - /* De-allocate intra-frame and inter-frame heap lists */ - if ( list_wc_intra_frame_heap != NULL ) - { - free( list_wc_intra_frame_heap ); - } - - if ( list_current_inter_frame_heap != NULL ) - { - free( list_current_inter_frame_heap ); - } - - if ( list_wc_inter_frame_heap != NULL ) - { - free( list_wc_inter_frame_heap ); - } - -#ifdef MEM_COUNT_DETAILS - if ( fid_csv_filename != NULL ) - { - fclose( fid_csv_filename ); - } -#endif - - return; -} - -#endif /* WMOPS */ - -#ifndef WMOPS -int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */ -#endif - +/* + * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. + * + * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, + * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file + * or refer to ITU-T Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS". + * + * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor + * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software + * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE. + * + * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca) + */ + +#include +#include +#include +#include +#include + +#ifndef _MSC_VER +#include +#include +#else +#include +#endif + +#include "wmc_auto.h" + + +#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */ + +#ifdef WMOPS + +/*-------------------------------------------------------------------* + * Complexity counting tool + *--------------------------------------------------------------------*/ + +#define MAX_RECORDS 1024 +#define MAX_CHAR 64 +#define MAX_STACK 64 +#define DOUBLE_MAX 0x80000000 + +struct wmops_record +{ + char label[MAX_CHAR]; + long call_number; + long update_cnt; + int call_tree[MAX_RECORDS]; + double start_selfcnt; + double current_selfcnt; + double max_selfcnt; + double min_selfcnt; + double tot_selfcnt; + double start_cnt; /* The following take into account the decendants */ + double current_cnt; + double max_cnt; + double min_cnt; + double tot_cnt; +#ifdef WMOPS_WC_FRAME_ANALYSIS + int32_t current_call_number; + double wc_cnt; + double wc_selfcnt; + int32_t wc_call_number; +#endif +}; + +double ops_cnt; +double prom_cnt; +double inst_cnt[NUM_INST]; + +static struct wmops_record wmops[MAX_RECORDS]; +static int stack[MAX_STACK]; +static int sptr; +static int num_records; +static int current_record; +static long update_cnt; +static double start_cnt; +static double max_cnt; +static double min_cnt; +static double inst_cnt_wc[NUM_INST]; +static long fnum_cnt_wc; + +static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0; + + +void reset_wmops( void ) +{ + int i, j; + + for ( i = 0; i < MAX_RECORDS; i++ ) + { + strcpy( &wmops[i].label[0], "\0" ); + wmops[i].call_number = 0; + wmops[i].update_cnt = 0; + for ( j = 0; j < MAX_RECORDS; j++ ) + { + wmops[i].call_tree[j] = -1; + } + wmops[i].start_selfcnt = 0.0; + wmops[i].current_selfcnt = 0.0; + wmops[i].max_selfcnt = 0.0; + wmops[i].min_selfcnt = DOUBLE_MAX; + wmops[i].tot_selfcnt = 0.0; + wmops[i].start_cnt = 0.0; + wmops[i].current_cnt = 0.0; + wmops[i].max_cnt = 0.0; + wmops[i].min_cnt = DOUBLE_MAX; + wmops[i].tot_cnt = 0.0; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[i].wc_cnt = 0.0; + wmops[i].wc_selfcnt = 0.0; + wmops[i].current_call_number = 0; +#endif + } + + for ( i = 0; i < MAX_STACK; i++ ) + { + stack[i] = -1; + } + sptr = 0; + num_records = 0; + current_record = -1; + update_cnt = 0; + + max_cnt = 0.0; + min_cnt = DOUBLE_MAX; + start_cnt = 0.0; + ops_cnt = 0.0; +} + + +void push_wmops( const char *label ) +{ + int new_flag; + int i, j; + + /* Check if new function record label */ + new_flag = 1; + for ( i = 0; i < num_records; i++ ) + { + if ( strcmp( wmops[i].label, label ) == 0 ) + { + new_flag = 0; + break; + } + } + + /* Configure new record */ + if ( new_flag ) + { + if ( num_records >= MAX_RECORDS ) + { + fprintf( stdout, "push_wmops(): exceeded MAX_RECORDS count.\n\n" ); + exit( -1 ); + } + strcpy( wmops[i].label, label ); + num_records++; + } + + /* Push current context onto stack */ + if ( current_record >= 0 ) + { + if ( sptr >= MAX_STACK ) + { + fprintf( stdout, "\r push_wmops(): stack exceeded, try inreasing MAX_STACK\n" ); + exit( -1 ); + } + stack[sptr++] = current_record; + + /* accumulate op counts */ + wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; + + /* update call tree */ + for ( j = 0; j < MAX_RECORDS; j++ ) + { + if ( wmops[i].call_tree[j] == current_record ) + { + break; + } + else if ( wmops[i].call_tree[j] == -1 ) + { + wmops[i].call_tree[j] = current_record; + break; + } + } + } + + /* init current record */ + current_record = i; + wmops[current_record].start_selfcnt = ops_cnt; + wmops[current_record].start_cnt = ops_cnt; + wmops[current_record].call_number++; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[current_record].current_call_number++; +#endif + + return; +} + + +void pop_wmops( void ) +{ + + /* Check for underflow */ + if ( current_record < 0 ) + { + fprintf( stdout, "\r pop_wmops(): stack underflow, too many calls to pop_wmops()\n" ); + exit( -1 ); + } + + /* update count of current record */ + wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; + wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt; + + /* Get back previous context from stack */ + if ( sptr > 0 ) + { + current_record = stack[--sptr]; + wmops[current_record].start_selfcnt = ops_cnt; + } + else + { + current_record = -1; + } + + return; +} + + +void update_wmops( void ) +{ + int i; + double current_cnt; +#ifdef WMOPS_PER_FRAME + static FILE *fid = NULL; + const char filename[] = "wmops_analysis"; + float tmpF; +#endif + + if ( sptr != 0 ) + { + fprintf( stdout, "update_wmops(): Stack must be empty!\n" ); + exit( -1 ); + } + +#ifdef WMOPS_PER_FRAME + /* Check, if the output file has already been opened */ + if ( fid == NULL ) + { + fid = fopen( filename, "wb" ); + + if ( fid == NULL ) + { + fprintf( stderr, "\nCannot open %s!\n\n", filename ); + exit( -1 ); + } + } + + /* Write current complexity to the external file */ + tmpF = (float) ( FAC * wmops[0].current_cnt ); + fwrite( &tmpF, sizeof( float ), 1, fid ); +#endif + +#ifdef WMOPS_WC_FRAME_ANALYSIS + if ( ops_cnt - start_cnt > max_cnt ) + { + for ( i = 0; i < num_records; i++ ) + { + wmops[i].wc_cnt = wmops[i].current_cnt; + wmops[i].wc_selfcnt = wmops[i].current_selfcnt; + wmops[i].wc_call_number = wmops[i].current_call_number; + } + } +#endif + + for ( i = 0; i < num_records; i++ ) + { + wmops[i].tot_selfcnt += wmops[i].current_selfcnt; + wmops[i].tot_cnt += wmops[i].current_cnt; + + if ( wmops[i].current_selfcnt > 0 ) + { + if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt ) + { + wmops[i].max_selfcnt = wmops[i].current_selfcnt; + } + + if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt ) + { + wmops[i].min_selfcnt = wmops[i].current_selfcnt; + } + } + + wmops[i].current_selfcnt = 0; + + if ( wmops[i].current_cnt > 0 ) + { + if ( wmops[i].current_cnt > wmops[i].max_cnt ) + { + wmops[i].max_cnt = wmops[i].current_cnt; + } + + if ( wmops[i].current_cnt < wmops[i].min_cnt ) + { + wmops[i].min_cnt = wmops[i].current_cnt; + } + + wmops[i].update_cnt++; + } + + wmops[i].current_cnt = 0; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[i].current_call_number = 0; +#endif + } + + current_cnt = ops_cnt - start_cnt; + if ( current_cnt > max_cnt ) + { + max_cnt = current_cnt; + + for ( i = 0; i < NUM_INST; i++ ) + { + inst_cnt_wc[i] = inst_cnt[i]; + } + + fnum_cnt_wc = update_cnt + 1; + } + + if ( current_cnt < min_cnt ) + { + min_cnt = current_cnt; + } + + for ( i = 0; i < NUM_INST; i++ ) + { + inst_cnt[i] = 0.0; + } + + start_cnt = ops_cnt; + + /* increment frame counter */ + update_cnt++; + + return; +} + + +void print_wmops( void ) +{ + int i; + + char *sfmts = "%20s %8s %8s %7s %7s\n"; + char *dfmts = "%20s %8.2f %8.3f %7.3f %7.3f\n"; + char *sfmt = "%20s %8s %8s %7s %7s %7s %7s %7s\n"; + char *dfmt = "%20s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n"; + +#ifdef WMOPS_WC_FRAME_ANALYSIS + int j, label_len, max_label_len; + char *sfmtt = "%20s %4s %15s\n"; + char *dfmtt = "%20s %4d "; +#endif + + fprintf( stdout, "\n\n --- Complexity analysis [WMOPS] --- \n\n" ); + + fprintf( stdout, "%54s %23s\n", "|------ SELF ------|", "|--- CUMULATIVE ---|" ); + fprintf( stdout, sfmt, " routine", " calls", " min ", " max ", " avg ", " min ", " max ", " avg " ); + fprintf( stdout, sfmt, "---------------", "------", "------", "------", "------", "------", "------", "------" ); + + for ( i = 0; i < num_records; i++ ) + { + fprintf( stdout, dfmt, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt, + wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt, + FAC * wmops[i].max_selfcnt, + wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt, + wmops[i].min_cnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_cnt, + FAC * wmops[i].max_cnt, + wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt ); + } + + fprintf( stdout, sfmts, "---------------", "------", "------", "------", "------" ); + fprintf( stdout, dfmts, "total", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt ); + fprintf( stdout, "\n" ); + +#ifdef WMOPS_WC_FRAME_ANALYSIS + /* calculate maximum label length for compact prinout */ + max_label_len = 0; + for ( i = 0; i < num_records; i++ ) + { + label_len = strlen( wmops[i].label ); + if ( label_len > max_label_len ) + { + max_label_len = label_len; + } + } + max_label_len += 4; + + fprintf( stdout, "\nComplexity analysis for the worst-case frame %ld:\n", fnum_cnt_wc ); + fprintf( stdout, "%*s %8s %10s %12s\n", max_label_len, " routine", " calls", " SELF", " CUMULATIVE" ); + fprintf( stdout, "%*s %8s %10s %10s\n", max_label_len, "---------------", "------", "------", "----------" ); + + for ( i = 0; i < num_records; i++ ) + { + fprintf( stdout, "%*s %8d %10.3f %12.3f\n", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt ); + } + + fprintf( stdout, "\nCall Tree:\n\n" ); + fprintf( stdout, sfmtt, " function", "num", "called by: " ); + fprintf( stdout, sfmtt, "---------------", "---", "--------------" ); + + for ( i = 0; i < num_records; i++ ) + { + fprintf( stdout, dfmtt, wmops[i].label, i ); + for ( j = 0; wmops[i].call_tree[j] != -1; j++ ) + { + if ( j != 0 ) + { + fprintf( stdout, ", " ); + } + fprintf( stdout, "%d", wmops[i].call_tree[j] ); + } + fprintf( stdout, "\n" ); + } + + fprintf( stdout, sfmtt, "---------------", "---", "--------------" ); + fprintf( stdout, "\n\n" ); + + fprintf( stdout, "\nInstruction type analysis for the worst-case frame %ld:\n\n", fnum_cnt_wc ); /* added -- JPA */ + for ( i = 0; i < NUM_INST; i++ ) + { + switch ( (enum instructions) i ) + { + case _ADD: + fprintf( stdout, "\tAdds: %12.1f\n", inst_cnt_wc[i] ); + break; + case _ABS: + fprintf( stdout, "\tAbsolutes: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MULT: + fprintf( stdout, "\tMultiplies: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MAC: + fprintf( stdout, "\tMACs: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MOVE: + fprintf( stdout, "\tMoves: %12.1f\n", inst_cnt_wc[i] ); + break; + case _STORE: + fprintf( stdout, "\tStores: %12.1f\n", inst_cnt_wc[i] ); + break; + case _LOGIC: + fprintf( stdout, "\tLogicals: %12.1f\n", inst_cnt_wc[i] ); + break; + case _SHIFT: + fprintf( stdout, "\tShifts: %12.1f\n", inst_cnt_wc[i] ); + break; + case _BRANCH: + fprintf( stdout, "\tBranches: %12.1f\n", inst_cnt_wc[i] ); + break; + case _DIV: + fprintf( stdout, "\tDivisions: %12.1f\n", inst_cnt_wc[i] ); + break; + case _SQRT: + fprintf( stdout, "\tSquare Root: %12.1f\n", inst_cnt_wc[i] ); + break; + case _TRANS: + fprintf( stdout, "\tTrans: %12.1f\n", inst_cnt_wc[i] ); + break; + case _FUNC: + fprintf( stdout, "\tFunc Call: %12.1f\n", inst_cnt_wc[i] ); + break; + case _LOOP: + fprintf( stdout, "\tLoop Init: %12.1f\n", inst_cnt_wc[i] ); + break; + case _INDIRECT: + fprintf( stdout, "\tIndirect Addr: %12.1f\n", inst_cnt_wc[i] ); + break; + case _PTR_INIT: + fprintf( stdout, "\tPointer Init: %12.1f\n", inst_cnt_wc[i] ); + break; + case _TEST: + fprintf( stdout, "\tExtra condit.: %12.1f\n", inst_cnt_wc[i] ); + break; + case _POWER: + fprintf( stdout, "\tExponential: %12.1f\n", inst_cnt_wc[i] ); + break; + case _LOG: + fprintf( stdout, "\tLogarithm: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MISC: + fprintf( stdout, "\tAll other op.: %12.1f\n", inst_cnt_wc[i] ); + break; + default: + fprintf( stdout, "\tERROR: Invalid instruction type: %d\n\n", i ); + } + } +#endif + + return; +} + + +/*-------------------------------------------------------------------* + * Memory counting tool measuring RAM usage (stack and heap) + * + * Maximum RAM is measured by monitoring the total allocated memory (stack and heap) in each frame. + * + * Maximum stack is measured by monitoring the difference between the 'top' and 'bottom' of the stack. The 'bottom' of the stack is updated in each function + * with a macro 'func_start_' which is inserted automatically to all functions during the instrumentation process. + * + * Maximum heap is measured by summing the sizes of all memory blocks allocated by malloc() or calloc() and deallocated by free(). The maximum heap size is + * updated each time when the macros malloc_() or calloc_() is invoked. The macros 'malloc_ and calloc_' are inserted automatically during the instrumentation process. + * As part of heap measurements, intra-frame heap and inter-frame heap are measured separately. Intra-frame heap refers to heap memory which is allocated and deallocated + * within a single frame. Inter-frame heap, on the contrary, refers to heap memory which is reserved for more than one frame. + * + * In order to run the memory counting tool the function reset_mem(cnt_size) must be called at the beginning of the encoding/decoding process. + * The unit in which memory consumption is reported is set via the parameter 'cnt_size'. It can be set to 0 (bytes), 1 (32b words) or 2 (64b words). + * At the end of the encoding/decoding process, 'print_mem()' function may be called to print basic information about memory consumption. If the macro 'MEM_COUNT_DETAILS' + * is activated, detailed information is printed + * + * The macro 'WMOPS' needs to be activated to enable memory counting. To avoid the instrumentation of malloc()/calloc()/free() calls, use + * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free(). + *--------------------------------------------------------------------*/ + +#define MAX_RECORDABLE_CALLS 100 +#define MAX_FUNCTION_NAME_LENGTH 35 /* Maximum length that the function string will be truncated to */ +#define MAX_PARAMS_LENGTH 50 /* Maximum length that the parameter string will be truncated to */ +#define MAX_NUM_RECORDS 300 /* Initial maximum number of memory records -> mightb be increased during runtime, if needed */ +#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of memory records, increase the number of records by this number */ + +/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using + a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */ +#ifdef MEM_ALIGN_64BITS +#define BLOCK_ROUNDING 8 /* Align on 64 Bits */ +#else +#define BLOCK_ROUNDING 4 /* Align on 32 Bits */ +#endif + +#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) ) + +#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */ +#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */ +#define OOB_START 0x1 /* Flag indicating out-of-bounds access before memory block */ +#define OOB_END 0x2 /* Flag indicating out-of-bounds access after memory block */ + +#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) ) +#define IS_CALLOC( str ) ( str[0] == 'c' ) + +#ifdef MEM_COUNT_DETAILS +const char *csv_filename = "mem_analysis.csv"; +static FILE *fid_csv_filename = NULL; +#endif + +typedef struct +{ + char function_name[MAX_FUNCTION_NAME_LENGTH + 1]; + int16_t *stack_ptr; +} caller_info; + +caller_info stack_callers[2][MAX_RECORDABLE_CALLS]; + +typedef struct +{ + char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */ + char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */ + unsigned long hash; + int lineno; + void *block_ptr; + int block_size; + unsigned long total_block_size; /* Cumulative sum of the allocated size in the session */ + unsigned long total_used_size; /* Cumulative sum of the used size in the session */ + int wc_heap_size_intra_frame; /* Worst-Case Intra-Frame Heap Size */ + int wc_heap_size_inter_frame; /* Worst-Case Inter-Frame Heap Size */ + int frame_allocated; /* Frame number in which the Memory Block has been allocated (-1 if not allocated at the moment) */ + int OOB_Flag; + int noccurances; /* Number of times that the memory block has been allocated in a frame */ +} allocator_record; + +allocator_record *allocation_list = NULL; + +static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */ +static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */ +static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */ +static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */ +static int32_t wc_ram_size, wc_ram_frame; +static int32_t current_heap_size; +static int current_calls = 0; +static char location_max_stack[256] = "undefined"; +static int Num_Records, Max_Num_Records; +static size_t Stat_Cnt_Size = USE_BYTES; +static const char *Count_Unit[] = { "bytes", "words", "words" }; + +static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap; +static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap; +static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap; + +/* Local Functions */ +static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str ); +allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record ); +static void *mem_alloc_block( size_t size, const char *size_str ); + +/*-------------------------------------------------------------------* + * reset_mem() + * + * Initialize/reset memory counting tool (stack and heap) + *--------------------------------------------------------------------*/ + +void reset_mem( Counting_Size cnt_size ) +{ + int16_t something; + size_t tmp_size; + + /* initialize stack pointers */ + ptr_base_stack = &something; + ptr_max_stack = ptr_base_stack; + ptr_current_stack = ptr_base_stack; + + Stat_Cnt_Size = cnt_size; + + /* Check, if sizeof(int32_t) is 4 bytes */ + tmp_size = sizeof( int32_t ); + if ( tmp_size != 4 ) + { + fprintf( stderr, "Error: Expecting 'int32_t' to be a 32 Bits Integer!" ); + exit( -1 ); + } + + /* create allocation list for malloc() memory blocks */ + if ( allocation_list == NULL ) + { + allocation_list = malloc( MAX_NUM_RECORDS * sizeof( allocator_record ) ); + } + + if ( allocation_list == NULL ) + { + fprintf( stderr, "Error: Unable to Create List of Memory Blocks!" ); + exit( -1 ); + } + + Num_Records = 0; + Max_Num_Records = MAX_NUM_RECORDS; + + wc_ram_size = 0; + wc_ram_frame = -1; + current_heap_size = 0; + + /* heap allocation tree */ + heap_allocation_call_tree_max_size = MAX_NUM_RECORDS; + if ( heap_allocation_call_tree == NULL ) + { + heap_allocation_call_tree = (int *) malloc( heap_allocation_call_tree_max_size * sizeof( int ) ); + memset( heap_allocation_call_tree, -1, heap_allocation_call_tree_max_size * sizeof( int ) ); + } + heap_allocation_call_tree_size = 0; + + /* wc intra-frame heap */ + max_items_wc_intra_frame_heap = MAX_NUM_RECORDS; + if ( list_wc_intra_frame_heap == NULL ) + { + list_wc_intra_frame_heap = (int *) malloc( max_items_wc_intra_frame_heap * sizeof( int ) ); + memset( list_wc_intra_frame_heap, -1, max_items_wc_intra_frame_heap * sizeof( int ) ); + } + n_items_wc_intra_frame_heap = 0; + size_wc_intra_frame_heap = 0; + location_wc_intra_frame_heap = -1; + + /* current inter-frame heap */ + max_items_current_inter_frame_heap = MAX_NUM_RECORDS; + if ( list_current_inter_frame_heap == NULL ) + { + list_current_inter_frame_heap = (int *) malloc( max_items_current_inter_frame_heap * sizeof( int ) ); + memset( list_current_inter_frame_heap, -1, max_items_current_inter_frame_heap * sizeof( int ) ); + } + n_items_current_inter_frame_heap = 0; + size_current_inter_frame_heap = 0; + + /* wc inter-frame heap */ + max_items_wc_inter_frame_heap = MAX_NUM_RECORDS; + if ( list_wc_inter_frame_heap == NULL ) + { + list_wc_inter_frame_heap = (int *) malloc( max_items_wc_inter_frame_heap * sizeof( int ) ); + memset( list_wc_inter_frame_heap, -1, max_items_wc_inter_frame_heap * sizeof( int ) ); + } + n_items_wc_inter_frame_heap = 0; + size_wc_inter_frame_heap = 0; + location_wc_inter_frame_heap = -1; + +#ifdef MEM_COUNT_DETAILS + /* Check, if the .csv file has already been opened */ + if ( fid_csv_filename == NULL ) + { + fid_csv_filename = fopen( csv_filename, "wb" ); + + if ( fid_csv_filename == NULL ) + { + fprintf( stderr, "\nCannot open %s!\n\n", csv_filename ); + exit( -1 ); + } + } + else + { + /* reset file */ + rewind( fid_csv_filename ); + } +#endif + + return; +} + +/*-------------------------------------------------------------------* + * reset_stack() + * + * Reset stack pointer + *--------------------------------------------------------------------*/ + +void reset_stack( void ) +{ + int16_t something; + + /* initialize/reset stack pointers */ + ptr_base_stack = &something; + ptr_max_stack = ptr_base_stack; + ptr_current_stack = ptr_base_stack; + + return; +} + +/*-------------------------------------------------------------------* + * push_stack() + * + * Check the current stack pointer and update the maximum stack pointer, if new maximum found. + *--------------------------------------------------------------------*/ + +int push_stack( const char *filename, const char *fctname ) +{ + int16_t something; + int32_t current_stack_size; + + ptr_current_stack = &something; + + (void) *filename; /* to avoid compilation warning */ + + /* Is there room to save the caller's information? */ + if ( current_calls >= MAX_RECORDABLE_CALLS ) + { /* No */ + fprintf( stderr, "No more room to store call stack info. Please increase MAX_RECORDABLE_CALLS" ); + exit( -1 ); + } + + /* Valid Function Name? */ + if ( fctname[0] == 0 ) + { /* No */ + fprintf( stderr, "Invalid function name for call stack info." ); + exit( -1 ); + } + + /* Save the Name of the Calling Function in the Table */ + strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FUNCTION_NAME_LENGTH ); + stack_callers[0][current_calls].function_name[MAX_FUNCTION_NAME_LENGTH] = 0; /* Nul Terminate */ + + /* Save the Stack Pointer */ + stack_callers[0][current_calls].stack_ptr = ptr_current_stack; + + /* Increase Stack Calling Tree Level */ + current_calls++; + + /* Is this the First Time or the Worst Case? */ + if ( ptr_current_stack < ptr_max_stack || ptr_max_stack == NULL ) + { /* Yes */ + /* Save Info about it */ + ptr_max_stack = ptr_current_stack; + + wc_stack_frame = update_cnt; /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */ + strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 ); + location_max_stack[sizeof( location_max_stack ) - 1] = '\0'; + + /* Save Call Tree */ + memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls ); + + /* Terminate the List (Unless Full) */ + if ( current_calls < MAX_RECORDABLE_CALLS ) + { + stack_callers[1][current_calls].function_name[0] = 0; + } + } + + /* Check, if This is the New Worst-Case RAM (stack + heap) */ + current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); + + if ( current_stack_size < 0 ) + { + /* prevent negative stack size */ + current_stack_size = 0; + } + + if ( current_stack_size + current_heap_size > wc_ram_size ) + { + wc_ram_size = current_stack_size + current_heap_size; + wc_ram_frame = update_cnt; + } + + return 0 /* for Now */; +} + +/*-------------------------------------------------------------------* + * pop_stack() + * + * Remove stack caller entry from the list + *--------------------------------------------------------------------*/ + +int pop_stack( const char *filename, const char *fctname ) +{ + caller_info *caller_info_ptr; + + (void) *filename; /* to avoid compilation warning */ + + /* Decrease Stack Calling */ + current_calls--; + + /* Get Pointer to Caller Information */ + caller_info_ptr = &stack_callers[0][current_calls]; + + /* Check, if Names Match */ + if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 ) + { + fprintf( stderr, "Invalid usage of pop_stack()" ); + exit( -1 ); + } + + /* Erase Entry */ + caller_info_ptr->function_name[0] = 0; + + /* Retrieve previous stack pointer */ + if ( current_calls == 0 ) + { + ptr_current_stack = ptr_base_stack; + } + else + { + ptr_current_stack = stack_callers[0][current_calls - 1].stack_ptr; + } + + return 0 /* for Now */; +} + +#ifdef MEM_COUNT_DETAILS +/*-------------------------------------------------------------------* + * print_stack_call_tree() + * + * Print detailed information about worst-case stack usage + *--------------------------------------------------------------------*/ + +static void print_stack_call_tree( void ) +{ + caller_info *caller_info_ptr; + int call_level; + char fctname[MAX_FUNCTION_NAME_LENGTH + 1]; + + fprintf( stdout, "\nList of functions when maximum stack size is reached:\n\n" ); + + caller_info_ptr = &stack_callers[1][0]; + for ( call_level = 0; call_level < MAX_RECORDABLE_CALLS; call_level++ ) + { + /* Done? */ + if ( caller_info_ptr->function_name[0] == 0 ) + { + break; + } + + /* Print Name */ + strncpy( fctname, caller_info_ptr->function_name, MAX_FUNCTION_NAME_LENGTH ); + strcat( fctname, "()" ); + fprintf( stdout, "%-42s", fctname ); + + /* Print Stack Usage (Based on Difference) */ + if ( call_level != 0 ) + { + fprintf( stdout, "%lu %s\n", ( ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); + } + else + { + fprintf( stdout, "%lu %s\n", ( ( ptr_base_stack - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); + } + + /* Advance */ + caller_info_ptr++; + } + + fprintf( stdout, "\n" ); + + return; +} +#endif + + +/*-------------------------------------------------------------------* + * mem_alloc() + * + * Creates new record, stores auxiliary information about which function allocated the memory, line number, parameters, etc. + * Finally, it allocates physical memory using malloc() + * The function also updates worst-case heap size and worst-case RAM size + *--------------------------------------------------------------------*/ + +void *mem_alloc( + const char *func_name, + int func_lineno, + size_t size, + char *size_str /* the first char indicates m-alloc or c-alloc */ ) +{ + int index_record; + int32_t current_stack_size; + unsigned long hash; + allocator_record *ptr_record; + + if ( size == 0 ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Size of Zero not Supported" ); + exit( -1 ); + } + + /* Search for an existing record (that has been de-allocated before) */ + index_record = 0; + while ( ( ptr_record = get_mem_record( &hash, func_name, func_lineno, size_str, &index_record ) ) != NULL ) + { + if ( ptr_record->frame_allocated == -1 ) + { + break; + } + else + { + index_record++; + } + } + + /* Create new record */ + if ( ptr_record == NULL ) + { + if ( Num_Records >= Max_Num_Records ) + { + /* There is no room for a new record -> reallocate memory */ + Max_Num_Records += MAX_NUM_RECORDS_REALLOC_STEP; + allocation_list = realloc( allocation_list, Max_Num_Records * sizeof( allocator_record ) ); + } + + ptr_record = &( allocation_list[Num_Records] ); + + /* Initialize new record */ + ptr_record->hash = hash; + ptr_record->noccurances = 0; + ptr_record->total_block_size = 0; + ptr_record->total_used_size = 0; + ptr_record->frame_allocated = -1; + ptr_record->OOB_Flag = 0; + ptr_record->wc_heap_size_intra_frame = -1; + ptr_record->wc_heap_size_inter_frame = -1; + + index_record = Num_Records; + Num_Records++; + } + + /* Allocate memory block for the new record, add signature before the beginning and after the memory block and fill it with magic value */ + ptr_record->block_ptr = mem_alloc_block( size, size_str ); + + if ( ptr_record->block_ptr == NULL ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Cannot Allocate Memory!" ); + exit( -1 ); + } + + /* Save all auxiliary information about the memory block */ + strncpy( ptr_record->name, func_name, MAX_FUNCTION_NAME_LENGTH ); + ptr_record->name[MAX_FUNCTION_NAME_LENGTH] = '\0'; + strncpy( ptr_record->params, size_str, MAX_PARAMS_LENGTH ); /* Note: The size string starts with either 'm' or 'c' to indicate 'm'alloc or 'c'alloc */ + ptr_record->params[MAX_PARAMS_LENGTH] = '\0'; + ptr_record->lineno = func_lineno; + ptr_record->block_size = size; + ptr_record->total_block_size += size; + +#ifdef MEM_COUNT_DETAILS + /* Export heap memory allocation record to the .csv file */ + fprintf( fid_csv_filename, "A,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); +#endif + + if ( ptr_record->frame_allocated != -1 ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Attempt to Allocate the Same Memory Block with Freeing it First!" ); + exit( -1 ); + } + + ptr_record->frame_allocated = update_cnt; /* Store the current frame number -> later it will be used to determine the total duration */ + + /* Update Heap Size in the current frame */ + current_heap_size += ptr_record->block_size; + + /* Check, if this is the new Worst-Case RAM (stack + heap) */ + current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); + if ( current_stack_size + current_heap_size > wc_ram_size ) + { + wc_ram_size = current_stack_size + current_heap_size; + wc_ram_frame = update_cnt; + } + + /* Add new entry to the heap allocation call tree */ + if ( heap_allocation_call_tree == NULL ) + { + fprintf( stderr, "Error: Heap allocation call tree not created!" ); + exit( -1 ); + } + + /* check, if the maximum size of the call tree has been reached -> resize if so */ + if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size ) + { + heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP; + heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) ); + } + + /* push new entry (positive number means push op, neagtive number means pop op; zero index must be converted to 0.01 :-) */ + heap_allocation_call_tree[heap_allocation_call_tree_size++] = index_record; + + return ptr_record->block_ptr; +} + +/*-------------------------------------------------------------------* + * mem_alloc_block() + * + * Physical allocation of memory using malloc(). Appends 'signature' before and after the block, + * pre-fills memory block with magic value + *--------------------------------------------------------------------*/ + +static void *mem_alloc_block( size_t size, const char *size_str ) +{ + size_t rounded_size; + void *block_ptr; + char *tmp_ptr; + size_t n, f; + int32_t fill_value; + int32_t *ptr32; + int32_t mask, temp; + + /* Round Up Block Size */ + rounded_size = ROUND_BLOCK_SIZE( size ); + + /* Allocate memory using the standard malloc() by adding room for Signature Values */ + block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 ); + + if ( block_ptr == NULL ) + { + return NULL; + } + + /* Add Signature Before the Start of the Block */ + ptr32 = (int32_t *) block_ptr; + n = N_32BITS_BLOCKS; + do + { + *ptr32++ = MAGIC_VALUE_OOB; + } while ( --n ); + + /* Fill Memory Block with Magic Value or 0 */ + fill_value = MAGIC_VALUE_USED; + if ( IS_CALLOC( size_str ) ) + { + fill_value = 0x00000000; + } + n = size / sizeof( int32_t ); + while ( n-- ) + { + *ptr32++ = fill_value; + } + + /* Fill the Reminder of the Memory Block - After Rounding */ + n = rounded_size - size; + f = n % sizeof( int32_t ); + if ( f != 0 ) + { + /* when filling with '0' need to adapt the magic value */ + /* shift by [1->24, 2->16, 3->8] */ + mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */ + temp = MAGIC_VALUE_OOB & mask; + if ( fill_value != 0x0 ) + { /* for malloc merge fill value */ + temp += ( ~mask ) & MAGIC_VALUE_USED; + } /* for calloc the code in (1) above already introduces zeros */ + *ptr32++ = temp; + } + n /= sizeof( int32_t ); + n += N_32BITS_BLOCKS; + + /* Add Signature After the End of Block */ + do + { + *ptr32++ = MAGIC_VALUE_OOB; + } while ( --n ); + + /* Adjust the Memory Block Pointer (Magic Value Before and After the Memory Block Requested) */ + tmp_ptr = (char *) block_ptr; + tmp_ptr += BLOCK_ROUNDING; + block_ptr = (void *) tmp_ptr; + + return block_ptr; +} + +/*-------------------------------------------------------------------* + * mem_set_usage() + * + * Calculates actual usage of memory block by checking the magic value that was used to pre-fill + * each memory block during its allocation + *--------------------------------------------------------------------*/ + +static int mem_set_usage( allocator_record *record_ptr ) +{ + int total_bytes_used; + + size_t n; + int32_t *ptr32; + char *ptr8; + size_t total_bytes; + int32_t fill_value; + + fill_value = MAGIC_VALUE_USED; + if ( ( record_ptr->params[0] ) == 'c' ) + { + fill_value = 0x00000000; + } + + total_bytes = record_ptr->block_size; + + /* Check 4 bytes at a time */ + ptr32 = (int32_t *) record_ptr->block_ptr; + total_bytes_used = 0; + for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- ) + { + if ( *ptr32++ != fill_value ) + { + total_bytes_used += sizeof( int32_t ); + } + } + + /* Check remaining bytes (If Applicable) 1 byte at a time */ + ptr8 = (char *) ptr32; + for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- ) + { + if ( *ptr8++ != (char) fill_value ) + { + total_bytes_used++; + } + + /* Update Value */ + fill_value >>= 8; + } + + return total_bytes_used; +} + +/*-------------------------------------------------------------------* + * mem_check_OOB() + * + * Checks, if out-of-bounds access has occured. This is done by inspecting the 'signature' value + * taht has been added before and after the memory block during its allocation + *--------------------------------------------------------------------*/ + +static unsigned int mem_check_OOB( allocator_record *record_ptr ) +{ + int32_t *ptr32; + unsigned int OOB_Flag = 0x0; + int32_t mask; + size_t i; + int f; + + ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS; + + /* Check the Signature at the Beginning of Memory Block */ + i = N_32BITS_BLOCKS; + do + { + if ( *ptr32++ ^ MAGIC_VALUE_OOB ) + { + OOB_Flag |= OOB_START; + } + } while ( --i ); + + /* Advance to End (Snap to lowest 32 Bits) */ + ptr32 += record_ptr->block_size / sizeof( int32_t ); + + /* Calculate Unused Space That has been added to get to the rounded Block Size */ + i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size; + + /* Partial Check of Signature at the End of Memory Block (for block size that has been rounded) */ + f = i % sizeof( int32_t ); + if ( f != 0 ) + { + mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); + if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask ) + { + OOB_Flag |= OOB_END; + } + } + + /* Full Check of Signature at the End of Memory Block, i.e. all 32 Bits (for the remainder after rounding) */ + i /= sizeof( int32_t ); + i += N_32BITS_BLOCKS; + do + { + if ( *ptr32++ ^ MAGIC_VALUE_OOB ) + { + OOB_Flag |= OOB_END; + } + } while ( --i ); + + return OOB_Flag; +} + +/*-------------------------------------------------------------------* + * malloc_hash() + * + * Calculate hash from function name, line number and malloc size + *--------------------------------------------------------------------*/ + +static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str ) +{ + unsigned long hash = 5381; + const char *ptr_str; + + ptr_str = func_name; + while ( ptr_str != NULL && *ptr_str != '\0' ) + { + hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */ + } + + hash = ( ( hash << 5 ) + hash ) + func_lineno; /* hash * 33 + func_lineno */ + + ptr_str = size_str; + while ( ptr_str != NULL && *ptr_str != '\0' ) + { + hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */ + } + + return hash; +} + +/*-------------------------------------------------------------------* + * get_mem_record() + * + * Search for memory record in the internal list, return NULL if not found + * Start from index_record + *--------------------------------------------------------------------*/ + +allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record ) +{ + int i; + + if ( *index_record < 0 || *index_record > Num_Records ) + { + return NULL; + } + + /* calculate hash */ + *hash = malloc_hash( func_name, func_lineno, size_str ); + + for ( i = *index_record; i < Num_Records; i++ ) + { + /* check, if memory block is not allocated at the moment and the hash matches */ + if ( allocation_list[i].block_ptr == NULL && *hash == allocation_list[i].hash ) + { + *index_record = i; + return &( allocation_list[i] ); + } + } + + /* not found */ + *index_record = -1; + return NULL; +} + + +/*-------------------------------------------------------------------* + * mem_free() + * + * This function de-allocatesd the memory block and frees the mphysical memory with free(). + * It also updates actual and average usage of the memory block. + * + * Note: The record is not removed from the list and may be reused later on in mem_alloc()! + *--------------------------------------------------------------------*/ + +void mem_free( const char *func_name, int func_lineno, void *ptr ) +{ + int i, index_record; + char *tmp_ptr; + allocator_record *ptr_record; + + /* Search for the Block Pointer in the List */ + ptr_record = NULL; + index_record = -1; + for ( i = 0; i < Num_Records; i++ ) + { + if ( ptr == allocation_list[i].block_ptr ) + { /* Yes, Found it */ + ptr_record = &( allocation_list[i] ); + index_record = i; + break; + } + } + + if ( ptr_record == NULL ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Unable to Find Record Corresponding to the Allocated Memory Block!" ); + exit( -1 ); + } + + /* Update the Heap Size */ + current_heap_size -= ptr_record->block_size; + + /* Calculate the Actual Usage of the Memory Block (Look for Signature) */ + ptr_record->total_used_size += mem_set_usage( ptr_record ); + + /* Check, if Out-Of-Bounds Access has been Detected */ + ptr_record->OOB_Flag = mem_check_OOB( ptr_record ); + +#ifdef MEM_COUNT_DETAILS + /* Export heap memory de-allocation record to the .csv file */ + fprintf( fid_csv_filename, "D,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); +#endif + + /* De-Allocate Memory Block */ + tmp_ptr = (char *) ptr; + tmp_ptr -= BLOCK_ROUNDING; + ptr = (void *) tmp_ptr; + free( ptr ); + + /* Add new entry to the heap allocation call tree */ + if ( heap_allocation_call_tree == NULL ) + { + fprintf( stderr, "Error: Heap allocation call tree not created!" ); + exit( -1 ); + } + + /* check, if the maximum size of the call tree has been reached -> resize if so */ + if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size ) + { + heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP; + heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) ); + } + + heap_allocation_call_tree[heap_allocation_call_tree_size++] = -index_record; + + /* Reset memory block pointer (this is checked when updating wc intra-frame and inter-frame memory) */ + ptr_record->block_ptr = NULL; + + return; +} + + +/*-------------------------------------------------------------------* + * update_mem() + * + * This function updates the worst-case intra-frame memory and the worst-case inter-frame memory. + *--------------------------------------------------------------------*/ + +void update_mem( void ) +{ + int i, j, flag_alloc = -1, i_record; + int size_current_intra_frame_heap; + int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap; + allocator_record *ptr_record; + + /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */ + n_items_current_intra_frame_heap = 0; + size_current_intra_frame_heap = 0; + for ( i = 0; i < heap_allocation_call_tree_size; i++ ) + { + /* get the record */ + i_record = heap_allocation_call_tree[i]; + + if ( i_record > 0 ) + { + flag_alloc = 1; + } + else if ( i_record < 0 ) + { + flag_alloc = 0; + i_record = -i_record; + } + ptr_record = &( allocation_list[i_record] ); + + if ( ptr_record->frame_allocated == update_cnt && ptr_record->block_ptr == NULL ) + { + /* intra-frame heap memory */ + if ( list_current_intra_frame_heap == NULL ) + { + list_current_intra_frame_heap = (int *) malloc( heap_allocation_call_tree_size * sizeof( int ) ); + memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) ); + } + + /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ + if ( i_record == 0 ) + { + flag_alloc = 1; + for ( j = 0; j < n_items_current_intra_frame_heap; j++ ) + { + if ( list_current_intra_frame_heap[j] == i_record ) + { + flag_alloc = 0; + break; + } + } + } + + if ( flag_alloc ) + { + /* add to list */ + list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record; + size_current_intra_frame_heap += ptr_record->block_size; + + /* no need to re-size the list -> the initially allocated size should be large enough */ + } + else + { + /* remove from list */ + for ( j = 0; j < n_items_current_intra_frame_heap; j++ ) + { + if ( list_current_intra_frame_heap[j] == i_record ) + { + break; + } + } + memmove( &list_current_intra_frame_heap[j], &list_current_intra_frame_heap[j + 1], ( n_items_current_intra_frame_heap - j ) * sizeof( int ) ); + n_items_current_intra_frame_heap--; + size_current_intra_frame_heap -= ptr_record->block_size; + + /* reset block size */ + ptr_record->frame_allocated = -1; + ptr_record->block_size = 0; + } + } + else + { + /* inter-frame heap memory */ + + /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ + if ( i_record == 0 ) + { + flag_alloc = 1; + for ( j = 0; j < n_items_current_inter_frame_heap; j++ ) + { + if ( list_current_inter_frame_heap[j] == i_record ) + { + flag_alloc = 0; + break; + } + } + } + + if ( flag_alloc ) + { + /* add to list */ + if ( n_items_current_inter_frame_heap >= max_items_current_inter_frame_heap ) + { + /* resize list, if needed */ + max_items_current_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_current_inter_frame_heap = realloc( list_current_inter_frame_heap, max_items_current_inter_frame_heap * sizeof( int ) ); + } + + list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record; + size_current_inter_frame_heap += ptr_record->block_size; + } + else + { + /* remove from list */ + for ( j = 0; j < n_items_current_inter_frame_heap; j++ ) + { + if ( list_current_inter_frame_heap[j] == i_record ) + { + break; + } + } + memmove( &list_current_inter_frame_heap[j], &list_current_inter_frame_heap[j + 1], ( n_items_current_inter_frame_heap - j ) * sizeof( int ) ); + n_items_current_inter_frame_heap--; + size_current_inter_frame_heap -= ptr_record->block_size; + + /* reset block size */ + ptr_record->frame_allocated = -1; + ptr_record->block_size = 0; + } + } + } + + /* check, if this is the new worst-case for intra-frame heap memory */ + if ( size_current_intra_frame_heap > size_wc_intra_frame_heap ) + { + if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap ) + { + /* resize the list, if needed */ + max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) ); + } + + /* copy current-frame list to worst-case list */ + memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) ); + n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap; + size_wc_intra_frame_heap = size_current_intra_frame_heap; + location_wc_intra_frame_heap = update_cnt; + + /* update the wc numbers in all individual records */ + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + i_record = list_wc_intra_frame_heap[i]; + ptr_record = &( allocation_list[i_record] ); + ptr_record->wc_heap_size_intra_frame = ptr_record->block_size; + } + } + + /* check, if this is the new worst-case for inter-frame heap memory */ + if ( size_current_inter_frame_heap > size_wc_inter_frame_heap ) + { + if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap ) + { + /* resize list, if needed */ + max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) ); + } + + /* copy current-frame list to worst-case list */ + memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) ); + n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap; + size_wc_inter_frame_heap = size_current_inter_frame_heap; + location_wc_inter_frame_heap = update_cnt; + + /* update the wc numbers in all individual records */ + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + i_record = list_wc_inter_frame_heap[i]; + ptr_record = &( allocation_list[i_record] ); + ptr_record->wc_heap_size_inter_frame = ptr_record->block_size; + } + } + + /* reset heap allocation call tree */ + heap_allocation_call_tree_size = 0; + + /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */ + if ( list_current_intra_frame_heap ) + { + free( list_current_intra_frame_heap ); + } + + return; +} + +#ifdef MEM_COUNT_DETAILS +/*-------------------------------------------------------------------* + * subst() + * + * Substitute character in string + *--------------------------------------------------------------------*/ + +static void subst( char *s, char from, char to ) +{ + while ( *s == from ) + { + *s++ = to; + } + + return; +} + + +/*-------------------------------------------------------------------* + * mem_count_summary() + * + * Print detailed (per-item) information about heap memory usage + *--------------------------------------------------------------------*/ + +static void mem_count_summary( void ) +{ + int i, j, index, index_record; + size_t length; + char buf[300], format_str[50], name_str[MAX_FUNCTION_NAME_LENGTH + 3], parms_str[MAX_PARAMS_LENGTH + 1], type_str[10], usage_str[20], size_str[20], line_str[10]; + allocator_record *ptr_record, *ptr; + + /* Prepare format string */ + sprintf( format_str, "%%-%ds %%5s %%6s %%-%ds %%20s %%6s ", MAX_FUNCTION_NAME_LENGTH, MAX_PARAMS_LENGTH ); + + if ( n_items_wc_intra_frame_heap > 0 ) + { + /* Intra-Frame Heap Size */ + fprintf( stdout, "\nList of memory blocks when maximum intra-frame heap size is reached:\n\n" ); + + /* Find duplicate records (same hash and worst-case heap size) */ + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + index_record = list_wc_intra_frame_heap[i]; + if ( index_record == -1 ) + { + continue; + } + + ptr_record = &( allocation_list[index_record] ); + for ( j = i + 1; j < n_items_wc_intra_frame_heap; j++ ) + { + index = list_wc_intra_frame_heap[j]; + if ( index == -1 ) + { + continue; + } + ptr = &( allocation_list[index] ); + + if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_intra_frame == ptr_record->wc_heap_size_intra_frame ) + { + ptr_record->noccurances++; + list_wc_intra_frame_heap[j] = -1; + } + } + } + + /* Print Header */ + sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Maximum Size", "Usage" ); + puts( buf ); + length = strlen( buf ); + sprintf( buf, "%0*d\n", (int) length - 1, 0 ); + subst( buf, '0', '-' ); + puts( buf ); + + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + index_record = list_wc_intra_frame_heap[i]; + + if ( index_record != -1 ) + { + /* get the record */ + ptr_record = &( allocation_list[index_record] ); + + /* prepare information strings */ + strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH ); + strcat( name_str, "()" ); + name_str[MAX_FUNCTION_NAME_LENGTH] = '\0'; + strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH ); + parms_str[MAX_PARAMS_LENGTH] = '\0'; + + if ( ptr_record->params[0] == 'm' ) + { + strcpy( type_str, "malloc" ); + } + else + { + strcpy( type_str, "calloc" ); + } + + sprintf( line_str, "%d", ptr_record->lineno ); + + /* prepare average usage & memory size strings */ + sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) ); + + if ( ptr_record->noccurances > 1 ) + { + sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + else + { + sprintf( size_str, "%d %s", (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + + sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str ); + puts( buf ); + } + } + + fprintf( stdout, "\n" ); + } + + if ( n_items_wc_inter_frame_heap > 0 ) + { + /* Inter-Frame Heap Size */ + fprintf( stdout, "\nList of memory blocks when maximum inter-frame heap size is reached:\n\n" ); + + /* Find duplicate records (same hash and worst-case heap size) */ + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + index_record = list_wc_inter_frame_heap[i]; + if ( index_record == -1 ) + { + continue; + } + ptr_record = &( allocation_list[index_record] ); + ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */ + for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ ) + { + index = list_wc_inter_frame_heap[j]; + if ( index == -1 ) + { + continue; + } + ptr = &( allocation_list[index] ); + + if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_inter_frame == ptr_record->wc_heap_size_inter_frame ) + { + ptr_record->noccurances++; + list_wc_inter_frame_heap[j] = -1; + } + } + } + + /* Print Header */ + sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Memory Size", "Usage" ); + puts( buf ); + length = strlen( buf ); + sprintf( buf, "%0*d\n", (int) length - 1, 0 ); + subst( buf, '0', '-' ); + puts( buf ); + + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + index_record = list_wc_inter_frame_heap[i]; + + if ( index_record != -1 ) + { + /* get the record */ + ptr_record = &( allocation_list[index_record] ); + + /* prepare information strings */ + strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH ); + strcat( name_str, "()" ); + name_str[MAX_FUNCTION_NAME_LENGTH] = '\0'; + strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH ); + parms_str[MAX_PARAMS_LENGTH] = '\0'; + + if ( ptr_record->params[0] == 'm' ) + { + strcpy( type_str, "malloc" ); + } + else + { + strcpy( type_str, "calloc" ); + } + + sprintf( line_str, "%d", ptr_record->lineno ); + + /* prepare average usage & memory size strings */ + sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) ); + + if ( ptr_record->noccurances > 1 ) + { + sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + else + { + sprintf( size_str, "%d %s", (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + + sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str ); + puts( buf ); + } + } + + fprintf( stdout, "\n" ); + } + + return; +} + +#endif + +/*-------------------------------------------------------------------* + * print_mem() + * + * Print information about ROM and RAM memory usage + *--------------------------------------------------------------------*/ + +void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) +{ + int i, nElem; + + fprintf( stdout, "\n\n --- Memory usage --- \n\n" ); + + if ( Const_Data_PROM_Table != NULL ) + { + nElem = 0; + while ( strcmp( Const_Data_PROM_Table[nElem].file_spec, "" ) != 0 ) + nElem++; + + for ( i = 0; i < nElem; i++ ) + { + fprintf( stdout, "Program ROM size (%s): %d instruction words\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size ); + } + + for ( i = 0; i < nElem; i++ ) + { + if ( Const_Data_PROM_Table[i].Get_Const_Data_Size_Func == NULL ) + { + fprintf( stdout, "Error: Cannot retrieve or calculate Table ROM size of (%s)!\n", Const_Data_PROM_Table[i].file_spec ); + } + + fprintf( stdout, "Table ROM (const data) size (%s): %d %s\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].Get_Const_Data_Size_Func() >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); + } + } + else + { + fprintf( stdout, "Program ROM size: not available\n" ); + fprintf( stdout, "Table ROM (const data) size: not available\n" ); + } + + if ( wc_ram_size > 0 ) + { + fprintf( stdout, "Maximum RAM (stack + heap) size: %d %s in frame %d\n", wc_ram_size >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], wc_ram_frame ); + } + else + { + fprintf( stdout, "Maximum RAM (stack + heap) size: not available\n" ); + } + + /* check, if the stack is empty */ + if ( ptr_current_stack != ptr_base_stack ) + { + fprintf( stderr, "Warning: Stack is not empty.\n" ); + } + + if ( ptr_base_stack - ptr_max_stack > 0 ) + { + fprintf( stdout, "Maximum stack size: %lu %s in frame %d\n", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], + wc_stack_frame ); + } + else + { + fprintf( stdout, "Maximum stack size: not available\n" ); + } + + /* last update of intra-frame memory and inter-frame memory, if needed */ + if ( heap_allocation_call_tree_size > 0 ) + { + update_mem(); + } + + /* check, if all memory blocks have been deallocated (freed) */ + for ( i = 0; i < Num_Records; i++ ) + { + if ( allocation_list[i].block_ptr != NULL ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", allocation_list[i].name, allocation_list[i].lineno, "Error: Memory Block has not been De-Allocated with free()!" ); + exit( -1 ); + } + } + + if ( n_items_wc_intra_frame_heap > 0 ) + { + fprintf( stdout, "Maximum intra-frame heap size: %d %s in frame %d\n", size_wc_intra_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_intra_frame_heap ); + } + else + { + fprintf( stdout, "Maximum intra-frame heap size: 0\n" ); + } + + if ( n_items_wc_inter_frame_heap > 0 ) + { + fprintf( stdout, "Maximum inter-frame heap size: %d %s in frame %d\n", size_wc_inter_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_inter_frame_heap ); + } + else + { + fprintf( stdout, "Maximum inter-frame heap size: 0\n" ); + } + +#ifdef MEM_COUNT_DETAILS + /* Print detailed information about worst-case stack usage */ + if ( ptr_base_stack - ptr_max_stack > 0 ) + { + print_stack_call_tree(); + } + + /* Print detailed information about worst-case heap usage */ + mem_count_summary(); +#endif + + if ( Stat_Cnt_Size > 0 ) + { + fprintf( stdout, "\nNote: 1 word = %d bits\n", 8 << Stat_Cnt_Size ); + fprintf( stdout, "This is an optimistic estimate of memory consumption assuming that each variable type is stored with sizeof(type) bits\n" ); + } + + if ( n_items_wc_intra_frame_heap > 0 ) + { + fprintf( stdout, "Intra-frame heap memory is allocated and de-allocated in the same frame\n" ); + } + + /* De-allocate list of heap memory blocks */ + if ( allocation_list != NULL ) + { + free( allocation_list ); + } + + /* De-allocate heap allocation call tree */ + if ( heap_allocation_call_tree != NULL ) + { + free( heap_allocation_call_tree ); + } + + /* De-allocate intra-frame and inter-frame heap lists */ + if ( list_wc_intra_frame_heap != NULL ) + { + free( list_wc_intra_frame_heap ); + } + + if ( list_current_inter_frame_heap != NULL ) + { + free( list_current_inter_frame_heap ); + } + + if ( list_wc_inter_frame_heap != NULL ) + { + free( list_wc_inter_frame_heap ); + } + +#ifdef MEM_COUNT_DETAILS + if ( fid_csv_filename != NULL ) + { + fclose( fid_csv_filename ); + } +#endif + + return; +} + +#endif /* WMOPS */ + +#ifndef WMOPS +int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */ +#endif + + \ No newline at end of file diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index 989be87101839facda4638d75a16b65b1188720d..fda367732897571857b4b48204a6a2e4f99b16ae 100644 GIT binary patch literal 43832 zcmeHQZF3tplD^NW%6~xQ-B6Zg*-~C=tBcF?K_W5zbT_)ucn9%hM z$h+C@MW&j?WL!+rGA~A3YIiVDr}TcRPP1t?d6)IJhy!!!T;@|XE&AnEI>{71k0(W$ zb<3=$&aVaQL3*Xq5hv!OGMkK;c{)(#B*VvSx}`do892=*-3+*1w#oDQy$%CeY(#c0S0v>HroP zO|!Kvbu!4(DYSroJ!XK{^h)*fLB{fn310SzeW5h-)2v$zhuNsdYN}UT+uv=gVx-pE z$1giS?Vj$d&hha7=)*-VD-SKFlZTFdby0;@$M^wOY4{TQ2e6&)Trx z`J^b`W?S9#A?4=D=bwH4*@L`~lGj&19Uh;wlh;VVw|tbj1V^*~_f{u)x!XE8JKd+$ zQFkzdO@Ek{y+MAyb@`)uvZ3@B_GFe(i6>KJ@AGo~A&Y!~QkVCo=>6lD9=E)3%<{tH z)gMm~nf*C-pMM7FokE>VvUhN&E@quKC0o2;o} zHl3!ZN^}6eYBsf&d7rG3B(ILnnn?ov#*_47m?|QeUQf$xm|P;@GL%7=BPej1rGv+1 zKFm-Y2D*S<=HsbmYE1j`boX$-ot*5SChh&^F#_wGr&~||E$}oC_S*{2cJ?jg)I9Uz z__$5pXyWy{+TMEFR}b0#-E@FltA5%okxjP#KW9k$7o}1uhxt(%WFy4ec~)L!*+?O# ziXpV^a>xzS5dbjRw4BUPOXxtUXMyFCYW7)I^Vxc$4qFEYt>dGl`47&@hACD~d6Yz( zucNcWq;=HpSdI$SKIN!Wl+Z@|i|bg{t4o!>DzC@cRIS6i83>S{L2;$anJHo9MK0T) zf5sF#Qw*Md{@HJc13by@-X2xe{P9KGemp!o=v1F~o7KnTH~aQ;yK{V6eK|OO)vBo4 zuUjuG^b3S{^R)%-wcgl|?Z2H?L>&-SvR|GZRjdw~>E{SFnz z5h^umF4A646v=dQ!GThb^Mo8{z+VZT)`xhtBa*Evku1$Y9<>@sYI3eluPF@c8EREa zC#Rbi;4T=E<4?kl4lrF7Ej%V6> zGW%VpOKRhQ5u}pDz$j@IsDKf)7*CTf+VV%w(Z-o73L^s6{o(gSp&t)Ml|12o zCdjWEjqD0Q5EiSbCyjVbsg3NS$t=|vg6AX=O#qhnk(n!NG zQWTGX(N`}fco-%;KqUNlFxNgHr*|I_o;1=RCLjW^n0N@lVk{bfk)q3@VG+y=1|Am) zPXu5wWz>VkKqwOe77GzD83-82-FGBNZDSlqn(`xZN#DI#&~p#M1sa6E9!>-UFn1pf zzC6++CLBVzn0N@`qU`F~#oB9GM19%bQb^#UF#;#Tf+sTW zJualeQ4S z3KDIl`ro?>6783}7<$*rIw>1p-bDe32ayN^6hXq1+<(*{u}d>61qp*b1ql@g|GBFm zu`4ISFQUj=sc}Wu1IB?!gaF2a1W*KtUh=vBD3LnHbqTC3C6dzWJ+5l4QaEH0(zPZU zbsv%9YfHMsb-F^xxL#KX8EIotk}9j=!}4ee$s`V5$E#XV6z&Pgj4Z_-G7?2<3FHbW zffONw<e{6Hl92x;`)g$W>cA0wVLk{A;p0a#3Q1Yj{1 z4ZujzWpS|xR-eJr>*>N10a#2a^H zY*`U5&>;Nva4r}KbNA8U%OgEv!Xbo`OvB@qq@$crki z9xe()3JF{^M&LwP@CKNBj|-`Almkgwend{`dp$DjrY+$Kjly3K=t6@*_YfPtMA9TG zI6}av=m-Jhtm_%a8f|HOgd`H!3lO`jO86xpF|Oo#z&H@;B!KZC0Te+(`}poXMufg` zP9$CN2poN_M~K;hC>%jF{CGGQAcVPx`0(VB4pHF|z(qwz02gJ~0FHEB8XJpn_3jiq z)~UKekYr*h`(>=+k^zMSqUfPig2aD7uy;-wGUkt+z<##K%gl5n=8jbUZyt z*Qiz~fQxE@0=Ou<25_Y7(w1ituHNdfLq3vD8=oM#_qdP+Jj#LOEq*+Y)FVS5e_64k z#-MwM4Vg!)eN=FSfKkyA0>)X_v#M2hX?%nv64)E?+ha+h$_hw~>mzxWPLqp_^l%yvnFaofcun53nEE<53qRT>J z5v<-~kSFew z7=c4rxRZl)LO41wh>3oT3Q_K`nEHQ_iCc0J9Ef#2Y|MH0M=CkI#m0F;|N7|B_jQ#6 z-#i^e2;RK)-m&sH+`<+f2Vxx+mJ4;D7f}IvBZn1p637LyUmCPG>cAZ8Et)wJZwtm< zG;U4>8Jd*3Qg~`M!Vb4U6A#0o7Up{^9F;ft75!($k_M|lMScldi{c&3WG^@^@4;N) zeL5*mW)#n|2=XjxkzT6@vwjpE!M#;Z2;VXiZW{^`M{bypg$0L%Jr}xQ_;f(n7H9c? zSw#4Luvjl7KBfc0dn=p}zGYO1LVBm|1N~&r{7jmVM(z_K@#%oDEzkP@vS{!uX~BLl zd?W{i_h`5fJ0QAcB*^+@l~9m4azmhf2#<9<7m8rGd6eSeqILCfq-)fOB!G(=hXim@ zx(0Bh>#~UO{XiIc{E#4L+{yUD(=&QpAaKzb%80><`Ln&1P6!)(ln+Q=^$3Mm0}CKA zn~#h|hlD+#3yn_)gsXB;xyO818XvX*%>nB}@sI6*@E&H%ThX&={||$N^js1_syjA}wcz_=>Nt3hm;zpEh8KDm=-#Lr`Vn;`NS4fn=DCrSdrLTdOg!Eq}NIo49p0g@hmY%x`l8^0x@ZJi?9Zi8?Sx9)6v^a0<@v)qC+*{?i<1HgWR{5)hg2a&<0!@Yfk#4b6%5G0wl{hF>PYC9 z(G9}{H-^)(Sl2bo>#*aKF3G^HP^jVli6mhffToZ;O{jvxz}UQF9b%4(WIB+eV!bx;MF zG&Pc|o1zeM!?dfuRKw{^tsmjupH_7@5yI|GHkslwpsBfF%G_uLgky~_DDs=?d{cEf zu<#B4A0ZIV@t=B{lujkwNVOMZ)!9sEAvTW}vjIbS!xmpswYT5iZFX93c02ogAyd;< zB!?NQw^2SF*6v!OJ7kW}jylOYYS2wJA}#0m9FK839AAmV+;GR$Pm^?v#QK#q6|bL8 zcTaEu)wW^!4mT`OeZ&8q*?jUHkZ1456Ins{G+!B(nvTf>`W_S)Ic}8 z9MH{fbTgT)68Y{edq)u$aH@n2!^VbfQpV*3cYICN*;HT8vrFy3GjRu4QP~Hjr(s|X z6sv1o8pW4?(XD5_HFbrX=2Y|g;tF?4U39y+VsJRdMS5s-pp}_RH4UVcuAZwe4Oda2 zSGLiv^R8T3S2YfN$w@JO@IX$IZMr4+V(ey&Z5i13y$>>l=sG$^?eom`Z&v7(-zTJy1Vr*!e zHyjwy=_R$h?5ct<1{@Z>*#I|zDaVB`4zzdF@oj|q!ZyAaacfB)D_xe*-Tb=Z(xGeD zT%P$pKxrq==oOV8zNt=XD{@2^I%2U@UvEb@x#1G3oMRr>3#O{kgu#i#+-7((DgFzW z51OoMU4CzIAujA|cO9j^3GtQo@Jn(y5s6iYsyrY@o+3CHe@FEdRfy4bmhI2;!Uk1O zo7~y)eJI9K-}~>}cSEIXBU@Wl@ouVDuP!tgmQR{fS1bI)=|EVaN0?QWDtJ=nb!BQV zV?_Aw>5CufCey>TJ1M3dV8yIdjo%ums2d*|-1wU7J<+>W)5~Ipn=es=qAsT%uct|biRU8lO z*l{dWjR!6Xj8cPkI5-|P7I+oKLoWhXOe7C}6~#m^k_DOYt0*RV5h2KgUqvx7zrAR= z$n5A>QCw*H*0MlBlU(pBiUm)1IUbS)y^7+YX9OxHk_W$vVxrGfR!js>*E@ofWPTUW zKz_xhW)m8-MCoEjGKP=LkbM=!#}0i0eC(?zK71I#%^d+otbt zDl0y!L?&V5;%bpSYyoE+=p+mcR1^$!5;iC< z7Qu9=uq;q{pzWt&i_}5eXs=!Db&G|bwsFYPKqq0-e6&c#8Vqz2R;F<<&`DUTwG5S! znlz%T;k25|ah{r~)^j<|*Aw4&!ak_$NpwbsZRHf4+TRECb%2?O*+Zb5pE%;j=Alsf(*4VO^KlH3z<*W1|VKX#|Bd-RIw7GHb)3?EAUF+ z-^A;%brjDF#5eNV{rd{McK?1OuT|`Ic(c6@SFsm}Lwcczv~jODE}y5tV-D{I-HiGe zCNL8ZK{wM)&bUCFTnl0nMbtI_wpU>S;xLoHoyKc|CMC#Z%2_simS>0T6Xc^!7s*Ex zhxz>NZ1>dm<(KKxX5tzj@?w603)pY;At-KARgWgL2SHjBV8flHMDifgFpt(NicKmW z!K?~B+90j*aK-hsD9R=IMIWMngCM`Z(f1{_Mwn14ZG0>jn2+8iDEnokOiS*IJw|ow zOadKIsC5^E|NS%>^`Gkf4`tl_8*rk337 z)bnco=H?mJLDnxHWBR&>S!&Eh)Bir!$cDp|=YX>*&C#pNbgD*$%KCjwO|9|W(l^ey z+MFg6Op^DE5rf&R)WkGX^?6fiU@eQ5r)Fu*7cyPNr_R#=gG^D7W@v10aQ6bH23TWC zQInMl&B+rq1GV;>))sGU!)fkmUFk^^t{bW$Hh<&e{ao*J&9Au;Vo@W{0&i-#Ru{Oi zWkV0guJ+ut(qo2ephjNZ>Q2a$blT0dav+z~qDznErIi@fSA*=b%u6$UUGHzvq&Aq3 z(qXo_uqJThTCDSclKO(&8$2+}C3@6ZEs~g}rP?A%0w300O?AnaU!vt|3#X!ByuCIzouWpUJPlKR^kD03U9Z8j_ z%o?N{%DnH??9=!bPY8{g7Rl?|4<9O!In321CeFc~76A=QP7)d}(1}*iq)ya9=A}g1 zC@{)0WE_*ClT@v(KU|}qhiGgzR5s$x1KGrE8n87|uSl%;UZG_hvA;Q8lS(u5PKy8D z;_Lg(WuAEA*M!bRQ9|UxXF;A9`+@j5P0ukvdApeX%G{ZsV~-sn*nct07D!l`z2)a5 zOtNw|;eq!;6GgwcL7jEiV4h;cWyg_x8G#-nQs|5`Ox zpxtyK#orv6-kn|-?I{Hn&|hLLKM=|3u9sw=S{iq-{bci7MP z@+<8@YW&#vp5D|2O0Xw}Uh%RTvHOxnvvoBrlupvjtVK zWmVbJJNd93Fm9)fsWM%&-uGGSxW)dAe-pUbuQ8GYxDk@QKM9^ zX|v{tXLyLEe3+OPgJ`mU;ReSB%@;JP#h`O++oA3(R*sf!YLv3*v+QhFpFQsp9l|g{ zcPqi(OLQ{Cw*W2rrt4~LZ7!TR>OBLYKcCJ9wx3Fp?9=CM=a{dYmOUUh)!Hu;?%O`Y zhG1+1!(oD|bMN}sjXzHtzl_#4Nk#Q|K~c}%=g`pWK8Ow#y#M2m&(*fb8~Rq1WV=-$ z))l56ih+<*YLhOz*jvT3#IE~apBMQP}QzyH~Q;v4EP8y47x z$ukqQy|OHd0loPB{2%MV3JUW62s6Z8%z9vU2!o(KtQTVeWDGb#!RqbrO z$loE_dAH`Yi}`Z1@AyqVone8uUCw%W0h@@e#}CGn^a69~SLtK~>#W;TC*Vqgscxzj zHQ&HAA%Ajue5lQBHis)a1g@7t#wO&PgbbY!)w^LI8fyv&enJ$le&7<^cbNwc)z>Rw+DS>{3yMEwY+D3^nD5#^4q2xvUd~%?W+<@;?Ve&RxE_&{yT>peWwX#;QZ- zo)Af0%*3TQ{sjdvsvqiu2Ftzf4|tz+$vR+I&%}J70+j_C5Z+}i1kR@Egm&0$65F1oo~LOvuR;PJok$MX5FdY6dTP|Zw3pZDhDbbRcB_je{hbki&Z(i z;P+cy9pP74#KazQAgbC*x&gfw+J#b@nQJ(TY8LEU$@@7r;O8Y(+72MXk;@kwQ`g*_ zpZfeATA`rzWo$Y&KVzuFJ`3Hwzi%O^791q>rd!6lkk75ia;;XivW9iUo{t2 z74;Gp8^y70M?Zu5xq$Vce@6;ewtH_6%S( z^{XAtgGzB-4}D^2Z@;tKI%wxclNk#ZZm=Ao%pFgsO|5*`|j!X0r<13 zN%HFGtO@SakK-nEsaQIEG^gC!53|wRQE@f;5lh;(eBiifT}LA;oI7g5xUUe%tKFo} zYC}Ue-Obg;1}ew|)o6i68Z~isN|r6B7aXZp;;#d^W>jFS54Gzh|HF|uK2*yb67GJ& zo6MOQ_puNW&sQr%Ljp5DZwxxr+;y)E?!hCpwqC|^eR9w`+E1|NK^mfmKYX^P9?)m$ z9y)DM@N%lA1H&cU^b!P}^V7V*xl5c!3Sl0QK)FU=n=?Yn;&H|Zsmqj9NwWp?*m z>tRBZ+KJY{+St{VE7pD5z~oszH_XdMo}W4Nh!Jx&m~VikO^wb2|z YzJ;x|^=xCHJy!i3LGs%4NB-@90T>HoO8@`> literal 42791 zcmeHQX>;31lKrkziD>N#kC0a2<(O zIvJ;vFptw@OB@V`;)331;v&kT$@{3k1p-8)dlP3OO9%OFIEe&4k0)s!_424MuI?QZrRk&>0oRW9dgH)zqSHmv!Np-`RcZJjxf4_Hg%( z-9*Da$Y$d-$>OUa)LvxlL+3qsLs=d0pVvoFal0c<&jhr6ad6uGC+oWV8i~pVTCK9k z`{LE~4$j@X2`Bvx@n#tI<54^jC*d$k()ZcBJJD2$TPE>ummTQtYLce!qOD%IhN5h* ztUQVb@V9|@dvbQ(30|)}!k0LS^mm=%=pXHF@baL2e0gz%#H2TzLX*$3yg!Vuwr+kA z+v`GpVe>^1`8a7H`Vi;MHDdM%eijc5&!e-KE~Pj%gyOVBXE2^13#mQ;(QXl zhbhG>LOO|)>wVGqQ$xgwK%^ykJc!{m5G9$8uA<4R7)4nYqQ;P+_Nvul>EZz?A_!ic zUbcc@<k4C`_0xO#6a)9?m6b?7@cof0#L+MF3@i=38g(hEK9Go0= zg7c$`pmWqZL-hQ(v$dlYebPQYZl9e7t$((Tk2(U+ZuFCWE6wua?5sn|Z{clI>~8H0 z#2V|n7Yh$s?XrFevil9K9PUY#QIb@Mm;wqG- z>QRj@^1E@Ai6(3sAp=S?OmEq%*q^iuukc%090q19A6JM^aBz5tI+#Db=oFt$E|0tF z<3US(I(u_eeC%}3F4X7avsZ1ErSrP|QUPBeYFn=hz+wB1g8uzN<>(@Z;`s9NR1rBo zJ3B8jw@(k-7e_4xIPYFSKW+83d(=@M&(Gc-T@)Y)RD3#VcUmi-oej>OE#|Ll{V&NOXt$Y zoNCdPHZG?YHl}1tZDeE4>7=rWWwMo5T9}iqR5oyt_p=Nvv6lSWz~{E4+Q8=(16L?; zoXT=pl9GL8R+}!HS5eSDf(UMk52)uop5M4$`{z$L47iw z|DyBdc|NzSmfE#`jZP@Z^86Q_Z=PRhX*r$`6MW&GPp$L=yS^2pJ~h=0H+HN2q64{z z_Y-94?r)V%$?a3~*T8(L{u-Evy>5!B0OBqSb#qHm=j;PH~BdCJ0%i!v<$O1bn9aCs4Xp9rX;d;*|~ z^3i1#MN-al{~4%~_w#VZGC>vP|SNJ@T80qJYW z`Q@~LrFx0MUl(S1KOjqY{}MM6!pHw>U_Jp*1M||Ts}iNDc_C24jiBWgKn~t5OH{de zIj9Tsf{-`{<_$4069+uo@X&!^3F~Dy5|kfPNc!rAf|?7nEFeMn>*7o-FlPC|P~t~o zctt}E&MO>haDIAq^`g`@Hy~>G5w;W&YU0W=NR^+Tv${Ax3`t~g{uqNZQNgoqUu0Cs zc|xqSn28B0AU{Ss^wmTKW4=X&RFeL?q^OVvS;BbP_HGi=-@}dF{V~Kr;!ITVZ1Wcx z6>2SHk*HwIx2PaTu%0DFg<80<3}U=gvGem*7w3l|4hH9sF*p+ya<%2b!@`o+udP>F zw1AZ4cB1rhpk;^|K+|4G&;x`PzV* zJj*Usj-HO|0zE+_lmRXPGC&g}SbKcn05PI^+K8tDf#m)~)^%8@>F3fm8L6+|RC2k~ykN?-ed;*{b=A}_rB}!BC zLZF5lK}#(`u|dPKM3tMDgSs#;2#I50-Vg&balkuD9y$;#VZH1|g7RYuNnhPiP`jNh z3rGUnRzKU3oOle3zPTY$?AEgkKzaCaVJ0F7viyK>xsd=~@lb_% zg+mqQrO_&k1f3fUGhl8Hi7l~=$t9PYw^tjOH-ri=VI~gLKEQ{L1;d*@d0CG#s>hU; zQrwtOMZo^iMdCuimLD4=qAM_^c*RFO)GJ2nq28LV3QPp&#!5X`hPv^h)V+)iOhmq< z;m-&HBC-(7a5eFxcFcak@uP~cVEic9xA-ByD7hmi;m`8oN2&WOiyt~X@X)bisy6T1 zuxe4a%_+`2EYjW(WcjgT%BEb-tDULByxN#5%uAzH7zsN!HfF%wc7-kR<@dw*G{r*) zf>lX**-g2Wg`*@l6y!OO#rj^1S$;5-R^slIaT@jb$nc$ABMDUaQ+yBGrcP;;XiOp7)kvsM^f75qi=3JK;{K|Qa~&{7EHNF zLVA26p^EZ}gDT2LmsJ!=Ij>QefpQ~&Ot6F|!R6)a$p+<%pmIx;@q9Wl_rR`iMX8Uy zNJ@T80qLvj{KYv=tLl*${B>bweu^MVcmEPM62iy-YhXSBPy_SQsH+mCsd*t#!;PS& zx!U5$rDcgKH!lZuVO|gt$H2TH2KLFE0j8s`-hn_AQ z1KUqTaI*NeasvPUfv&%D%f4e9XXy1;0lNRMOFJfFBYLpu$Q0SN5u{&Jk1nlRz{%88W1taxW zoqxt5Sl4pK`@bE4RbE{DpBDlp11NO4V@JPbvy2A9wVQX%ZeZRJDv5-d0nXt9CtxLZ zk$T*4q)&?=P4Ng>69lz~U|p0I1K$q7k{bD$=l-q^HOg%Pp(f{@x(n#On zW|6<#{j`*<%3V&^b*{R*;dh;bepb7n7T_X^_&qKnc%R067fO@|weD?K`gf`6x)?=bO{t9vkDaNLfQvLv$4_;ByO8ul?oBu2 zlPAL5hyh?BoczJ}Qr^u?E3Z?0WN+f`8r*P{moVb_bFl-qhDiY=<(NdiRYmbOg;iS+ zbZHKXU**;bda2f=6hGT)64YG2PBF8ZI>}7w=p-|q)k)UR+2}OY!Pg18-=kAZ3!szq zo++K8kGtv=bsmcsB6O-cW#XplLmDO@-R|IKLLuD*y@k=JTyOi(gv@fdl~h*pA?=cK zi67Re*_t{t#A+0+hfP*4^?`^+sF) z&}~A8N1cOKxBcdzd&D>Bv{apN5}}St;%sDJjziajoL!!FgC?rL4Us^)GLf?}ZtLPJ zY?u^oB6>Rs$4GRp8qtK_UL2g`uAtq5;(J_(LsbX=*QzS#-b3!_!+2r^dpXPZ1womO zb5}$?POoEJDFhRC>AJJYosh!QJzI2tle%37mm{f(g6o$uahb`x zRt~8C-nXu2O0`npCXE8t!0lXjxY>vAWujZC`m5p=H-3rM-SsUl{<-e;aLL3syFD`l^)11X*6qVchTI=Jzv!OduKk0N@X zBD+baxMUDjB&uoZpUOTxKHq&O+ts38MsE%Ey{_W4e&~`O+r70;2m*>ge?QT@*;u#M23QJNZ`IUA0cQvfFa>fz$+gTa{W}(uu1SM9~yGCsg?%6 z@}VK;=4)y2D<2xg5BMn}c3I>rA0jkGswlwGZ6bK(LxCrl3<;Y8z49R;N93A@O@d$f z(2$1#H4TfT?%=>Wc3JDQfVn2(sDnlpK7y$6MnT3djC$omMh#GE$f#F7WO%>5DNxfX z5{)+QA+q6QCQ2J(SN7VAs)^6u80xyF;)dxYM0ZcOPEM~gyvhRG+pLbVqyaX#fcGl1 zI>7@8()z5&P%aCENeJRJ2Sm9n&|sLRlb{w<6qv>1Y!)p0*Ce08tB4VXQ8o)TPH$(a zLb)`5H-K$r=DsCH5Oq8D9jUpj7p8=1+b$V`kVw{6(YA~cY>md4*N{N+Hq zQAZ==;ud7)mxXjwM@DMRlZ?zS?w44FKVsjo^_UD(1pw>s99X8vmu=xD%vt+w{x35I+k`8 zqT?>d$i8v@tXE&A=2(Ey#&J9(D4Li)9NrZd8jE#R^kkEmj0D zoNHgII37Q?XXUCZAI-mV-MjBBTv=2rL}`BUuVQE4Ci`-Tu~;j`N^v?A@1ncgbkcVe z5D#b=GxL%2h-I@;J!uyRjAh1npgXAp8kgd!!=frha&vcWO(2_w+}>ac8>DHuP155O zOSpP*Xwk|RhdR2vWT&oW&uGGO5{lL4+A956L1UvKqJ)>-qlsK@S9MN54GP};Q_5+qnW2g7(a6&KxlcOVr8XQ{xyMmBndGTehXFD*YnV8w zjXBe-{T1OMTOQ=yFp;@%Ydpw$w4S_1Tn#4cBjdi7dW zx}sUEAtdNh&R$0-mXCOike9>|$ksj`ERvz_{YYIBxpQYY;>9JUbX3a2(Y`niv9m|d z=F$2i&+lObO&JRwyz^(6N<7u(E{K-9C^w6OMcP3RGhsE-P{)JT?x3P9-)D%dALPQW z`0lxA{I=78*hEc=PM@UlU@L^z_hK6^+e?Xb?SeFOA;iW4g_L#<+jtB}!6%T~$yI?8clNtfp zVta0G%?jptEXa$hygt@)FZ$t|kgiIS$m-5T{cEnK*nb!N|OFBrBsrJL!Ig(svL7xz#?07pX(vm%MT`!wM0ys{P$8S zsfax%%iSWQ>GZOrB-<{Lm8n~$RAQ#qZx=4l^BQ98tcc5MV=}W`QZn>>s-;6`t9ye^ zS%-I(B#m6Wrj3aSO`s4x`{BH_mO^vpGq?3MXjIE3EWFIw%4f5p&vx%u ze|8N<*$`&|x0VbeXC|gzp*J+SIZ&8A?>OL-Rp2VEc%edMLh%FD~%bzEbjxi zAy$8zaHn%0J6*963R~WFf7|qW8-LCkza^_1B%au;ck1Xv4C&lP-}HT8@LztRpFY-B zK`)3>iVhHdI*vq?L!qZD^h4-b?4u7KJVB={0ScO!oGGMX=vn`u{ z{8?YYX5N!%lwz+TkNs&AVV1p8yB;N&VC`X20kbX`h8$u!6^jP{j*N|( z7c^5!%rD1k!`^8G2S@fsJISN#2-{c*>X2L%qe=E;#A5f;UGOREk4+5RwxuEj>C!E1eWlO zF$J2~7kcC7b^IRT%o`H39;TX${j_i5Y>E}oPCo6&DfD5s)IJ(d!fVVz--eR}ifO8o z5Fko?QSn%=RaPv`W1nA~ok%qoyPSm@c{*Ol(12_bkbVQo)Rcm*NrPE0A3dTHr~@5( zl=}*^u_Zc^1n)}ZIzjF8lVkkF&Sw>ady1^$s+nsTMkl*3Y2spJ(L%B)IEF0MW1I8EP8 z$D&I|ZxA#+%y5M`cLe4bO^@Ur`tXW2ND@g7AD)?In^*ykogTEQGE1kEUc^qtz9*Y7 zY~Dp-0zL#|0tLHw-eoigiX8)J5pxy+18UC9=KxSEpi$sW!xq137GBFWWEM$&MFo`K zjU$?-LDf3NgoU=JEMmY#RP!fhUWME|$i`9c*S#Nq!~rW(tJXZ#9wrI%6*d0PaYWN2 zJX?a^;ir1mau+bIUA;YNan%bxbcP5;N8%tIV!E0tMr*&c=ue?JRMf~2C;DWEGz*T6 z^{{G%7yN#!Cu8{*D}2}sO(fM`a$Eh-H0{O6<;*YaLp2EYZp4Ead&uLQDrJ-33O#ly zRwCET>596xiXl=5K=u)SWN1E|g20!FA$upnfW%`^40AiA3IJ~=uG4vuNP_@^IUw7VU=rg`&2 zxlNe;68cQgn<6v(^n-Xo`xemen3A%j;(KX763yttesRnX(~7(?|29U~4GO)D5g6#H zVC@_WjNk7`8j!;kL!N0lJn9~_k2@r#^5-a-jtalM>>LFz{)y8HG;;@);Gv}5pICNu zS4`UXdqvtF98z_WxPp@tnrK21EOg)l`;*_cPazjA%OF`bh2j|q{$+<&R@`*z7k$s^ zW|1lg$lHQI1OcrWb=zmBv64o7oP(mz0BY>NBzX^Upu;>>g9&OacY3 zPA^-aP2DeQ4kbaP&)|u(F_k>4&!)+{B)v_3Syk<6MY@7bEeC3kxWTWMQSL5RJqdZL zNuH)$N0k?#UQE%@qH5J=E?I85?nZSDe;vXWNs2u!)Hdh*4~Me&h$d4AxXV}^(I|%Itro1&NV8;5K84CFD<%7&t&vuDoS~P?h1I7LjAN;vgLV85%QsYy=rAa+>9h`x zkD)#2(mEAvhb}FS*u}uR_Axtvn+rCkHl*LTDXme}2xl-Y5V?la87&J`EHXhLb1D}S z7+u^W06T*9M+syoRpgQ5HYt&Fs--Mfp(r0!%v5$!Hjl!nn#n%PUHF3PU8stU>kPc3 zz0BluoXuXyLlaR~7^?l966-1;!Q2mPQKld^k)R7@f*WlsZDQr)FjTQ6MS{*+4O3ZF z$!JsskVm^Y9!&&l8m0?U-+zE)CNKGLp(g6iZ3telGVhHS)xDO2NW3YprC&3)mz@ZG Lcs+Q{-HHDN%`h}h diff --git a/src/wmc_tool/wmc_tool.cpp b/src/wmc_tool/wmc_tool.cpp index e9300e6..c2fdefc 100644 --- a/src/wmc_tool/wmc_tool.cpp +++ b/src/wmc_tool/wmc_tool.cpp @@ -82,7 +82,8 @@ static void usage() " -m filename [--rom filename]: add statistics about ROM and RAM consumption\n" " note: filename shall point to a .c file containing the print_mem() function\n" " -b [--no-backup]: no backup of original files\n" - " -c dirname [--generate-wmc-files dirname]: copy wmc_auto.h and wmc_auto.c to a user-specified directory\n\n", + " -c dirname [--generate-wmc-files dirname]: copy wmc_auto.h and wmc_auto.c to a user-specified directory\n", + " -f value [--frames-per-second value]: set the number of frames per second (default 50.0)\n\n", WMC_TOOL_VERSION_NO, VERSION_STL); return; @@ -95,7 +96,8 @@ static TOOL_ERROR Parse_Command_Line( int* Operation, unsigned int* Tool_Warning_Mask, char* Const_Data_PROM_File, - char* wmops_output_dir + char* wmops_output_dir, + float *frames_per_sec ) { int i; @@ -126,6 +128,8 @@ static TOOL_ERROR Parse_Command_Line( /* Parse all options */ *i_last_cmd__line_option = 0; + *frames_per_sec = 50.0; + i = 0; while (i < nargs && *args[i] == '-') { @@ -221,12 +225,24 @@ static TOOL_ERROR Parse_Command_Line( *Operation |= OUTPUT_WMOPS_FILES; } + else if (_stricmp(arg_name, "f") == 0 || _stricmp(arg_name, "frames-per-second") == 0) + { + /* get the next argument - must be a positive float number */ + i++; + + /* get the value */ + if ((*frames_per_sec = strtof(args[i], NULL)) <= 0.0 ) + { + fprintf(stderr, "Incorrect number of frames per second specified: %s!\n\n", args[i]); + return ERR_CMD_LINE; + } + } /* Move to the next argument */ i++; } - /* return the position of the first non-option argument */ + /* return the position of the first non-optional argument */ *i_last_cmd__line_option = i; return NO_ERR; @@ -1008,75 +1024,90 @@ static TOOL_ERROR Process_File( * Output_Wmops_File *-------------------------------------------------------------------*/ -static TOOL_ERROR Output_Wmops_File( char *PathName, bool Backup ) +static TOOL_ERROR Output_Wmops_File( char *PathName, float frames_per_sec, bool Backup ) { TOOL_ERROR ErrCode = NO_ERR; - FILE *file; - int i; - size_t file_size; - char LongFileName[MAX_PATH + 1]; /* +1 for NUL Char*/ + FILE *TargetFile; + int i, len, size; + char SrcFileName[MAX_PATH + 1]; /* +1 for NUL Char*/ + char TargetFileName[MAX_PATH + 1]; /* +1 for NUL Char*/ + char *text = NULL, *p_str, temp_str[50]; + const char* wmops_auto_files[] = { "wmc_auto.h", "wmc_auto.c" }; static const char wmops_auto_file_h[] = #include "wmc_auto_h.txt" ; static const char wmops_auto_file_c[] = #include "wmc_auto_c.txt" ; + for (i = 0; i < 2; i++) { - if (i == 0) + /* Copy the source file contents to a char * buffer for further manipulation */ + size = i == 0 ? sizeof(wmops_auto_file_h) : sizeof(wmops_auto_file_c); + + text = (char*)calloc(size, sizeof(char)); + if (text == NULL) { - /* Create Output Filename */ - strcpy(LongFileName, PathName); - strcat(LongFileName, "/wmc_auto.h"); + ErrCode = ERR_FILE_READ; + Error("Error reading file " DQUOTE("%s"), ErrCode, SrcFileName); + goto ret; + } - /* Try opening the target file wmc_auto.h */ - if ((file = fopen(LongFileName, "wb")) == NULL) - { - ErrCode = ERR_FILE_OPEN; - Error("Cannot Open " DQUOTE("%s"), ErrCode, "wmc_auto.h"); - goto ret; - } + strncpy(text, i == 0 ? wmops_auto_file_h : wmops_auto_file_c, size); - /* Write it */ - file_size = sizeof(wmops_auto_file_h) - 1; - if (fwrite(wmops_auto_file_h, 1, file_size, file) != file_size) - { - ErrCode = Write_Error(LongFileName); - goto ret; - } + /* Replace the constant FRAMES_PER_SECOND */ + p_str = strstr(text, "#define FRAMES_PER_SECOND 50.0"); - /* Close the File */ - fclose(file); - } - else + if (p_str != NULL) { - /* Create Output Filename */ - strcpy(LongFileName, PathName); - strcat(LongFileName, "/wmc_auto.c"); + sprintf(temp_str, "#define FRAMES_PER_SECOND %.1f", frames_per_sec); + strncpy(p_str, temp_str, sizeof(temp_str)); + } - /* Try opening the target file wmc_auto.c */ - if ((file = fopen(LongFileName, "wb")) == NULL) - { - ErrCode = ERR_FILE_OPEN; - Error("Cannot Open " DQUOTE("%s"), ErrCode, "wmc_auto.c"); - goto ret; - } + /* Create Target Filename */ + strcpy(TargetFileName, PathName); + + /* strip off surrounding quotes "" */ + strip(TargetFileName, '"'); + + /* Replace '\' Windows Directory Delimiter by UNIX '/' */ + strcsub(TargetFileName, '\\', '/'); - /* Write it */ - file_size = sizeof(wmops_auto_file_c) - 1; - if (fwrite(wmops_auto_file_c, 1, file_size, file) != file_size) + /* check that there is a proper trailing '/' */ + len = (int)strlen(TargetFileName); + if (TargetFileName[len - 1] != '/') + { + /* add a trailing '/' */ + strcat(TargetFileName, "/"); + } + else + { + /* remove all extra trailing '/' */ + while (TargetFileName[len - 2] == '/') { - ErrCode = Write_Error(LongFileName); - goto ret; + TargetFileName[len - 1] = '\0'; + len--; } + } + strcat(TargetFileName, wmops_auto_files[i]); - /* Close the File */ - fclose(file); + /* Try opening the target file */ + if ((TargetFile = fopen(TargetFileName, "wb")) == NULL) + { + ErrCode = ERR_FILE_OPEN; + Error("Cannot Open " DQUOTE("%s"), ErrCode, TargetFileName); + goto ret; } + + /* Write the whole content to the target file */ + fwrite(text, size, 1, TargetFile); + fclose(TargetFile); + free(text); } ret: + return ErrCode; } @@ -1096,6 +1127,7 @@ int main( int argc, char *argv[] ) char LongFileName[MAX_PATH]; char Const_Data_PROM_File[MAX_PATH] = ""; char wmops_output_dir[MAX_PATH]; + float frames_per_sec; T_FILE_BOOK file_book[MAX_RECORDS]; struct stat s; Parse_Context_def ParseContext; @@ -1122,7 +1154,7 @@ int main( int argc, char *argv[] ) if ( ( ErrCode = Parse_Command_Line( argc, argv, &i_cmd_line, &Operation, &Tool_Warning_Mask, Const_Data_PROM_File, - wmops_output_dir) ) != NO_ERR ) + wmops_output_dir, &frames_per_sec) ) != NO_ERR ) { if (ErrCode == ERR_HELP) { @@ -1254,6 +1286,7 @@ int main( int argc, char *argv[] ) { /* it's an existing directory without file mask -> use *.c as default */ strcpy(file_book[i].pathname, file_book[i].cmd_line_spec); + /* remove the trailing '/', if any */ size = (int)strlen(file_book[i].pathname); while (file_book[i].pathname[size - 1] == '/') @@ -1409,7 +1442,7 @@ int main( int argc, char *argv[] ) if (Operation & OUTPUT_WMOPS_FILES) { /* Yes */ - if ((ErrCode = Output_Wmops_File(wmops_output_dir, (Operation & NO_BACKUP) == 0)) != NO_ERR) + if ((ErrCode = Output_Wmops_File(wmops_output_dir, frames_per_sec, (Operation & NO_BACKUP) == 0)) != NO_ERR) { goto ret; } From cd7896ddff632ddd8169b558846b2969d0e93263 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Thu, 14 Sep 2023 15:42:54 +0200 Subject: [PATCH 18/67] prevent calling twice push_wmops() when WMOPS_DETAILS is activated --- src/wmc_tool/test_data/ref/wmc_auto.c | 54 ++++++++++++------------- src/wmc_tool/test_data/ref/wmc_auto.h | Bin 43832 -> 43846 bytes src/wmc_tool/wmc_auto_c.txt | 55 +++++++++++++------------- src/wmc_tool/wmc_auto_h.txt | 2 +- 4 files changed, 56 insertions(+), 55 deletions(-) diff --git a/src/wmc_tool/test_data/ref/wmc_auto.c b/src/wmc_tool/test_data/ref/wmc_auto.c index aefb696..955c7ca 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.c +++ b/src/wmc_tool/test_data/ref/wmc_auto.c @@ -1,5 +1,5 @@ /* - * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file @@ -349,28 +349,40 @@ void update_wmops( void ) void print_wmops( void ) { - int i; + int i, label_len, max_label_len; - char *sfmts = "%20s %8s %8s %7s %7s\n"; - char *dfmts = "%20s %8.2f %8.3f %7.3f %7.3f\n"; - char *sfmt = "%20s %8s %8s %7s %7s %7s %7s %7s\n"; - char *dfmt = "%20s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n"; + char *sfmts = "%*s %8s %8s %7s %7s\n"; + char *dfmts = "%*s %8.2f %8.3f %7.3f %7.3f\n"; + char *sfmt = "%*s %8s %8s %7s %7s %7s %7s %7s\n"; + char *dfmt = "%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n"; #ifdef WMOPS_WC_FRAME_ANALYSIS - int j, label_len, max_label_len; + int j; char *sfmtt = "%20s %4s %15s\n"; char *dfmtt = "%20s %4d "; #endif - fprintf( stdout, "\n\n --- Complexity analysis [WMOPS] --- \n\n" ); + /* calculate maximum label length for compact prinout */ + max_label_len = 0; + for ( i = 0; i < num_records; i++ ) + { + label_len = strlen( wmops[i].label ); + if ( label_len > max_label_len ) + { + max_label_len = label_len; + } + } + max_label_len += 4; - fprintf( stdout, "%54s %23s\n", "|------ SELF ------|", "|--- CUMULATIVE ---|" ); - fprintf( stdout, sfmt, " routine", " calls", " min ", " max ", " avg ", " min ", " max ", " avg " ); - fprintf( stdout, sfmt, "---------------", "------", "------", "------", "------", "------", "------", "------" ); + fprintf( stdout, "\n\n --- Complexity analysis [WMOPS] --- \n\n" ); + + fprintf( stdout, "%*s %33s %23s\n", max_label_len, "", "|------ SELF ------|", "|--- CUMULATIVE ---|" ); + fprintf( stdout, sfmt, max_label_len, " routine", " calls", " min ", " max ", " avg ", " min ", " max ", " avg " ); + fprintf( stdout, sfmt, max_label_len, "---------------", "------", "------", "------", "------", "------", "------", "------" ); for ( i = 0; i < num_records; i++ ) { - fprintf( stdout, dfmt, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt, + fprintf( stdout, dfmt, max_label_len, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt, wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt, FAC * wmops[i].max_selfcnt, wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt, @@ -379,25 +391,13 @@ void print_wmops( void ) wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt ); } - fprintf( stdout, sfmts, "---------------", "------", "------", "------", "------" ); - fprintf( stdout, dfmts, "total", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt ); + fprintf( stdout, sfmts, max_label_len, "---------------", "------", "------", "------", "------" ); + fprintf( stdout, dfmts, max_label_len, "total", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt ); fprintf( stdout, "\n" ); #ifdef WMOPS_WC_FRAME_ANALYSIS - /* calculate maximum label length for compact prinout */ - max_label_len = 0; - for ( i = 0; i < num_records; i++ ) - { - label_len = strlen( wmops[i].label ); - if ( label_len > max_label_len ) - { - max_label_len = label_len; - } - } - max_label_len += 4; - fprintf( stdout, "\nComplexity analysis for the worst-case frame %ld:\n", fnum_cnt_wc ); - fprintf( stdout, "%*s %8s %10s %12s\n", max_label_len, " routine", " calls", " SELF", " CUMULATIVE" ); + fprintf( stdout, "%*s %8s %10s %12s\n", max_label_len, " routine", " calls", " SELF", " CUMULATIVE" ); fprintf( stdout, "%*s %8s %10s %10s\n", max_label_len, "---------------", "------", "------", "----------" ); for ( i = 0; i < num_records; i++ ) diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index fda367732897571857b4b48204a6a2e4f99b16ae..4d7eee8275d3d876b1acd9d25bbe7d38d98bafb8 100644 GIT binary patch delta 28 kcmdmSjp^7mrVXE#^C~Gshx\r\n" "#endif\r\n" "\r\n" + "#include \"wmc_auto.h\"\r\n" "\r\n" "\r\n" @@ -349,28 +350,40 @@ "\r\n" "void print_wmops( void )\r\n" "{\r\n" -" int i;\r\n" +" int i, label_len, max_label_len;\r\n" "\r\n" -" char *sfmts = \"%20s %8s %8s %7s %7s\\n\";\r\n" -" char *dfmts = \"%20s %8.2f %8.3f %7.3f %7.3f\\n\";\r\n" -" char *sfmt = \"%20s %8s %8s %7s %7s %7s %7s %7s\\n\";\r\n" -" char *dfmt = \"%20s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\\n\";\r\n" +" char *sfmts = \"%*s %8s %8s %7s %7s\\n\";\r\n" +" char *dfmts = \"%*s %8.2f %8.3f %7.3f %7.3f\\n\";\r\n" +" char *sfmt = \"%*s %8s %8s %7s %7s %7s %7s %7s\\n\";\r\n" +" char *dfmt = \"%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\\n\";\r\n" "\r\n" "#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" int j, label_len, max_label_len;\r\n" +" int j;\r\n" " char *sfmtt = \"%20s %4s %15s\\n\";\r\n" " char *dfmtt = \"%20s %4d \";\r\n" "#endif\r\n" "\r\n" -" fprintf( stdout, \"\\n\\n --- Complexity analysis [WMOPS] --- \\n\\n\" );\r\n" +" /* calculate maximum label length for compact prinout */\r\n" +" max_label_len = 0;\r\n" +" for ( i = 0; i < num_records; i++ )\r\n" +" {\r\n" +" label_len = strlen( wmops[i].label );\r\n" +" if ( label_len > max_label_len )\r\n" +" {\r\n" +" max_label_len = label_len;\r\n" +" }\r\n" +" }\r\n" +" max_label_len += 4;\r\n" "\r\n" -" fprintf( stdout, \"%54s %23s\\n\", \"|------ SELF ------|\", \"|--- CUMULATIVE ---|\" );\r\n" -" fprintf( stdout, sfmt, \" routine\", \" calls\", \" min \", \" max \", \" avg \", \" min \", \" max \", \" avg \" );\r\n" -" fprintf( stdout, sfmt, \"---------------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\" );\r\n" +" fprintf( stdout, \"\\n\\n --- Complexity analysis [WMOPS] --- \\n\\n\" );\r\n" +" \r\n" +" fprintf( stdout, \"%*s %33s %23s\\n\", max_label_len, \"\", \"|------ SELF ------|\", \"|--- CUMULATIVE ---|\" );\r\n" +" fprintf( stdout, sfmt, max_label_len, \" routine\", \" calls\", \" min \", \" max \", \" avg \", \" min \", \" max \", \" avg \" );\r\n" +" fprintf( stdout, sfmt, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\" );\r\n" "\r\n" " for ( i = 0; i < num_records; i++ )\r\n" " {\r\n" -" fprintf( stdout, dfmt, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt,\r\n" +" fprintf( stdout, dfmt, max_label_len, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt,\r\n" " wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt,\r\n" " FAC * wmops[i].max_selfcnt,\r\n" " wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt,\r\n" @@ -379,25 +392,13 @@ " wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt );\r\n" " }\r\n" "\r\n" -" fprintf( stdout, sfmts, \"---------------\", \"------\", \"------\", \"------\", \"------\" );\r\n" -" fprintf( stdout, dfmts, \"total\", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt );\r\n" +" fprintf( stdout, sfmts, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\" );\r\n" +" fprintf( stdout, dfmts, max_label_len, \"total\", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt );\r\n" " fprintf( stdout, \"\\n\" );\r\n" "\r\n" "#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" /* calculate maximum label length for compact prinout */\r\n" -" max_label_len = 0;\r\n" -" for ( i = 0; i < num_records; i++ )\r\n" -" {\r\n" -" label_len = strlen( wmops[i].label );\r\n" -" if ( label_len > max_label_len )\r\n" -" {\r\n" -" max_label_len = label_len;\r\n" -" }\r\n" -" }\r\n" -" max_label_len += 4;\r\n" -"\r\n" " fprintf( stdout, \"\\nComplexity analysis for the worst-case frame %ld:\\n\", fnum_cnt_wc );\r\n" -" fprintf( stdout, \"%*s %8s %10s %12s\\n\", max_label_len, \" routine\", \" calls\", \" SELF\", \" CUMULATIVE\" );\r\n" +" fprintf( stdout, \"%*s %8s %10s %12s\\n\", max_label_len, \" routine\", \" calls\", \" SELF\", \" CUMULATIVE\" );\r\n" " fprintf( stdout, \"%*s %8s %10s %10s\\n\", max_label_len, \"---------------\", \"------\", \"------\", \"----------\" );\r\n" "\r\n" " for ( i = 0; i < num_records; i++ )\r\n" diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index 8284b88..cfd4a71 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -1012,7 +1012,7 @@ "int pop_stack( const char *filename, const char *fctname );\r\n" "\r\n" "#ifdef WMOPS_DETAIL\r\n" -"#define STACK_DEPTH_FCT_CALL ( push_wmops( __FUNCTION__ ), push_stack( __FILE__, __FUNCTION__ ) ) /* add push_wmops() in all function calls */\r\n" +"#define STACK_DEPTH_FCT_CALL ( push_wmops( __FUNCTION__ \" [WMC_AUTO]\" ), push_stack( __FILE__, __FUNCTION__ ) ) /* add push_wmops() in all function calls */\r\n" "#define STACK_DEPTH_FCT_RETURN ( pop_wmops(), pop_stack( __FILE__, __FUNCTION__ ) ) /* add pop_wmops() in all function returns */\r\n" "#else\r\n" "#define STACK_DEPTH_FCT_CALL push_stack( __FILE__, __FUNCTION__ )\r\n" From 1c4a14ed4f0d619b239686d86f2c29c59fba8ee8 Mon Sep 17 00:00:00 2001 From: malenov Date: Fri, 15 Sep 2023 09:49:38 +0200 Subject: [PATCH 19/67] raise error if matching #undef WMC_TOOL_SKIP cannot be found --- src/wmc_tool/c_parser.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index f6bc28a..1dfae62 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -6438,8 +6438,14 @@ TOOL_ERROR Setup_Regions( if ( ( end = Find_Identifier( ptr, WMC_TOOL_SKIP_STRING, ParseTbl_ptr, ITEM_PREPROC_ARGS | ITEM_PREPROC_UNDEF, ITEM_ENCLOSED, &idx ) ) == NULL ) { /* No */ + + /* Error - #undef WMC_TOOL_SKIP missing ! */ + ErrCode = ERR_EXPECTED_EOS; + Error("Unable to find matching #undef %s!", ErrCode, WMC_TOOL_SKIP_STRING); + goto ret; + /* Skipped Regon will End at EOF */ - end = file_ptr->Data + file_ptr->Size; + //end = file_ptr->Data + file_ptr->Size; } else { /* Yes */ From 83ecc3cd6a42e49b9a4f836de8e222321080e955 Mon Sep 17 00:00:00 2001 From: malenov Date: Fri, 15 Sep 2023 10:34:48 +0200 Subject: [PATCH 20/67] Python script for graphical analysis of the memory allocation tree based on the .csv memory output file generated by the WMC tool --- src/wmc_tool/mem_analysis.py | 130 +++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/wmc_tool/mem_analysis.py diff --git a/src/wmc_tool/mem_analysis.py b/src/wmc_tool/mem_analysis.py new file mode 100644 index 0000000..20b239d --- /dev/null +++ b/src/wmc_tool/mem_analysis.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 + +# (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. +# +# This software is protected by copyright law and by international treaties. The source code, and all of its derivations, +# is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file +# or refer to ITU-T Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS". +# +# Any use of this software is permitted provided that this notice is not removed and that neither the authors nor +# VoiceAge Corporation are deemed to have made any representations as to the suitability of this software +# for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE. +# +# Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca) + +# This script provides graphical analysis of the memory allocation tree based on the .csv memory output file generated by the WMC tool +# +# usage: python3 mem_analysis.py mem_analysis.csv +# +# where mem_analysis.csv is the per-frame and per-block memory allocation output file generated by the WMC tool +# by activating the MEM_COUNT_DETAILS macro + +import os +import argparse +import csv +import sys +import struct +import numpy as np +import pandas as pd +import matplotlib.pyplot as plt + + +# set matplotlib in interactive mode (plots figure and return control) +# plt.ion() +# plt.close('all') + +parser = argparse.ArgumentParser(description='Analyze memory output file') +parser.add_argument('input',type=str,help='Memory analysis file (e.g. mem_analysis.csv)') +args = parser.parse_args() +fileIn = args.input + +# read input .csv file +df = pd.read_csv(fileIn, header=None, names=['action_type', 'frame', 'name', 'line_no', 'mem_size']) +Nframes = max(df['frame']) + +# merge identical memory blocks -> create new column 'count' +df = df.groupby(df.columns.tolist(),as_index=False).size() +df = df.rename(columns={'size': 'count'}) + +# remove column 'action_type' +df.drop(columns = ['action_type']) + +# merge records with the same signature but different frame number -> create list of frames (sort in ascending order) +df = df.groupby(['name', 'line_no', 'mem_size', 'count'],as_index=False).agg({'frame': list}) +df['frame'] = df['frame'].apply(np.sort) +df['list_len'] = df['frame'].apply(len) # auxiliary column -> length of the list + +# merge records with the same name and frame but different line number -> sum memory sizes and counts +df = df.groupby(['name', 'list_len'],as_index=False).agg({'line_no': list, 'mem_size': sum, 'count':sum, 'frame':'first'}) + +# sort by memory size (put inter-frame memory blocks to the bottom) +select_inter = (df['list_len'] == 2) & (df.apply(lambda row : row['frame'][-1] - row['frame'][0], axis = 1) >= Nframes) +df_inter = df[select_inter] +df_inter = df_inter.sort_values(by=['mem_size'], ascending=False) +df_intra = df[~select_inter] +df_intra = df_intra.sort_values(by=['list_len'], ascending=True) + +# plot inter-frame memory blocks in horizontal bar graph (use .broken_barh method) +fig, ax = plt.subplots() +colors = iter(plt.cm.rainbow(np.linspace(0, 1, len(df.index)))) +y_ticks = [] +y_tick_labels = [] +y_low = 1 +for index, row in df_inter.iterrows(): + l = f"{row['name']} on lines: {row['line_no']}, total memory size: {row['count']}x{row['mem_size']}" + fms = row['frame'].reshape((-1,2)) # convert frame numbers to two-column format + fms[:,1] -= fms[:,0] # second column should now represent the duration of the segment + fmsT = fms.T + fms_list = list(zip(fmsT[0], fmsT[1])) + c = next(colors) + ax.broken_barh(xranges=fms_list, yrange=(y_low, row['count']), label=l, color=c) + y_ticks.append(y_low + 0.5 * row['count']) + y_tick_labels.append(row['name']) + y_low += row['count'] + 0.5 + print(l + f", {row['count'] * fms.shape[0]/Nframes:.3f} mallocs per frame") + +# plot intra-frame memory blocks in horizontal bar graph (use .broken_barh method) +df_intra = df_intra.groupby(['name'],as_index=False).agg({'list_len': list, 'line_no': list, 'mem_size': list, 'count': list, 'frame': list}) +for index, row in df_intra.iterrows(): + # repeat for all grouped memory records in the row + for j in range(len(row['list_len'])): + l = f"{row['name']} on lines: {row['line_no'][j]}, total memory size: {row['count'][j]}x{row['mem_size'][j]}" + fms = row['frame'][j].astype(float).reshape((-1,2)) # convert frame numbers to two-column format + fms[:,1] -= fms[:,0] # second column should now represent the duration of the segment + idx_zero = fms[:,1] == 0 # find zero-length segments -> these are intra-frame memory blocks + fms[idx_zero, 0] += 0.1 + fms[idx_zero, 1] = 0.8 + fmsT = fms.T + fms_list = list(zip(fmsT[0], fmsT[1])) + c = next(colors) + ax.broken_barh(xranges=fms_list, yrange=(y_low, row['count'][j]), label=l, color=c, alpha=0.6) + print(l + f", {row['count'][j] * fms.shape[0]/Nframes:.3f} mallocs per frame") + y_ticks.append(y_low + 0.5 * max(row['count'])) + y_tick_labels.append(row['name']) + y_low += max(row['count']) + 0.5 + +ax.set_yticks(y_ticks) +ax.set_yticklabels(y_tick_labels) +ax.set_ylabel('Memory size') +ax.set_xlabel('Frame') +ax.set_title('Memory analysis') + +# shrink current axis's height by 20% on the bottom to fit the legend +box = ax.get_position() +ax.set_position([box.x0, box.y0 + box.height * 0.2, box.width, box.height * 0.8]) + +# insert the legend below the graph +ax.legend(loc="upper left", bbox_to_anchor=(0, -0.1), ncol=2, borderaxespad=0, fontsize='small') + +# magnify to "almost" fullscreen size (select the alternative for your backend) +fig = plt.gcf() +fig.set_size_inches(15, 9) # we need to set the size manually, otherwise savefig will save the figure in the default size +mng = plt.get_current_fig_manager() +mng.full_screen_toggle() +# mng.frame.Maximize(True) +# mng.window.showMaximized() +# mng.window.state('zoomed') + +# show and save the figure (use block=True to wait until Figure is closed manually) +plt.savefig(os.path.splitext(args.input)[0] + '.png', dpi=100, bbox_inches='tight') +plt.show(block=True) From 154166eef9bbc8c9c276a647d03f3a522b33cb6e Mon Sep 17 00:00:00 2001 From: malenov Date: Fri, 15 Sep 2023 10:48:31 +0200 Subject: [PATCH 21/67] replace printf() with fprintf() for better portability --- src/wmc_tool/c_parser.cpp | 59 ++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 1dfae62..a37863e 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -4105,6 +4105,7 @@ static TOOL_ERROR Find_Constants( memset( str, 0, sizeof( str ) ); memmove( str, ptr2 - LEN, LEN ); memmove( str + LEN + 1, ptr, LEN ); + for ( temp = 0; temp < sizeof( str ); temp++ ) { if ( IS_EOL_CHAR( str[temp] ) || IS_RESERVED_CHAR( str[temp] ) ) @@ -4112,8 +4113,8 @@ static TOOL_ERROR Find_Constants( str[temp] = ' '; } } - printf( "%s: Number=%s#%s#\n", ptr2 == ptr4 ? "+/- is Oper" : "+/- is Cste", - str, memstr( ptr2, ptr ) /*, str+LEN+1*/ ); + + fprintf( stdout, "%s: Number=%s#%s#\n", ptr2 == ptr4 ? "+/- is Oper" : "+/- is Cste", str, memstr( ptr2, ptr ) /*, str+LEN+1*/ ); } #endif } @@ -8692,14 +8693,14 @@ static void Print_Words( const char *words, bool ds = false, int margin = 4 ) /* Terminate String */ temp[margin + lin_length] = NUL_CHAR; /* Print */ - printf("%s", temp); + fprintf(stdout, "%s", temp); /* Advance */ ptr += lin_length; /* Update Remaining Length */ str_length -= lin_length; } while ( str_length > 0 ); /* Print newline */ - printf( "\n" ); + fprintf(stdout, "\n" ); } } @@ -8710,34 +8711,34 @@ void Print_Information( void ) { int i; - printf( "\n Manual Macros Removed during Desintrumentation:\n" ); + fprintf(stdout, "\n Manual Macros Removed during Desintrumentation:\n" ); Print_Words( MANUAL_COUNTING_MACROS_STRING ); - printf( "\n WMOPS Library Functions that are not Instrumented:\n" ); + fprintf(stdout, "\n WMOPS Library Functions that are not Instrumented:\n" ); Print_Words( WMOPS_COUNTLIB_FUNCTS_STRING, true ); - printf( "\n Other Counting Functions that are not Instrumented:\n" ); + fprintf(stdout, "\n Other Counting Functions that are not Instrumented:\n" ); Print_Words( OTHER_COUNTLIB_FUNCTS_STRING ); - printf( "\n WMC_Tool Functions that are not Instrumented:\n" ); + fprintf(stdout, "\n WMC_Tool Functions that are not Instrumented:\n" ); Print_Words( TOOL_FUNCTS_STRING, true ); - printf( "\n System Functions that are not Instrumented:\n" ); + fprintf(stdout, "\n System Functions that are not Instrumented:\n" ); Print_Words( SYSTEM_FUNCTS_STRING ); - printf( "\n System Functions that are Instrumented:\n" ); + fprintf(stdout, "\n System Functions that are Instrumented:\n" ); Print_Words( SYSTEM_ALLOC_FUNCTS_STRING ); - printf( "\n Preprocessor Directives that are Ignored:\n" ); + fprintf(stdout, "\n Preprocessor Directives that are Ignored:\n" ); for (i = 0; Conditionnal_Directives[i] != NULL; i++) { - printf(" %c%s\n", PREPROC_CHAR, Conditionnal_Directives[i]); + fprintf(stdout, " %c%s\n", PREPROC_CHAR, Conditionnal_Directives[i]); } - printf( " %c%s\n", PREPROC_CHAR, Undefine_Directive ); + fprintf(stdout, " %c%s\n", PREPROC_CHAR, Undefine_Directive ); for (i = 0; Other_Directives[i] != NULL; i++) { - printf(" %c%s\n", PREPROC_CHAR, Other_Directives[i]); + fprintf(stdout, " %c%s\n", PREPROC_CHAR, Other_Directives[i]); } - printf( "\n Math Functions that are Instrumented:\n" ); + fprintf(stdout, "\n Math Functions that are Instrumented:\n" ); Print_Words( MATH_FUNCTS_STRING ); - printf( "\n Keywords that are Instrumented:\n" ); + fprintf(stdout, "\n Keywords that are Instrumented:\n" ); for ( i = 0; i < (int)(nitems( keywords )); i++ ) { if ( !( keywords[i].kw_type & ITEM_SKIPPED ) ) @@ -8746,7 +8747,7 @@ void Print_Information( void ) } } - printf( "\n Keywords that are not Instrumented:\n" ); + fprintf(stdout, "\n Keywords that are not Instrumented:\n" ); for ( i = 0; i < (int)(nitems( keywords )); i++ ) { if ( keywords[i].kw_type & ITEM_SKIPPED ) @@ -8755,22 +8756,22 @@ void Print_Information( void ) } } - printf( "\n Recognized Data Types:\n" ); + fprintf(stdout, "\n Recognized Data Types:\n" ); Print_Words( TYPES_STRING ); - printf( "\n Macros used to Instrument: \n" ); - printf( " switch/case: %s(n)\n", AUTO_CASE_COUNTING_MACRO_STRING ); - printf( " logical operators: %s\n", LOGICAL_INSTRUMENT_STRING ); - printf( " ternary operators: %s\n", TERNARY_INSTRUMENT_STRING ); - printf( " all other operators: %s(\"ops_string\")\n", AUTO_DEFAULT_COUNTING_MACRO_STRING ); + fprintf(stdout, "\n Macros used to Instrument: \n" ); + fprintf(stdout, " switch/case: %s(n)\n", AUTO_CASE_COUNTING_MACRO_STRING ); + fprintf(stdout, " logical operators: %s\n", LOGICAL_INSTRUMENT_STRING ); + fprintf(stdout, " ternary operators: %s\n", TERNARY_INSTRUMENT_STRING ); + fprintf(stdout, " all other operators: %s(\"ops_string\")\n", AUTO_DEFAULT_COUNTING_MACRO_STRING ); - printf( "\n Include File Required in Instrumented Source Files:\n" ); - printf( " %s\n", WMOPS_LIB_INCLUDE_STRING ); + fprintf(stdout, "\n Include File Required in Instrumented Source Files:\n" ); + fprintf(stdout, " %s\n", WMOPS_LIB_INCLUDE_STRING ); - printf( "\n Skip Instrumentation:\n" ); - printf( " Begin Uninstrumented Segment: #define " WMC_TOOL_SKIP_STRING "\n" ); - printf( " End of Uninstrumented Segment: #undef " WMC_TOOL_SKIP_STRING "\n" ); - printf( "\n" ); + fprintf(stdout, "\n Skip Instrumentation:\n" ); + fprintf(stdout, " Begin Uninstrumented Segment: #define " WMC_TOOL_SKIP_STRING "\n" ); + fprintf(stdout, " End of Uninstrumented Segment: #undef " WMC_TOOL_SKIP_STRING "\n" ); + fprintf(stdout, "\n" ); } /*-------------------------------------------------------------------* From 2a8f9766165befa804ad402df583cc045096eaed Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 19 Sep 2023 15:24:52 +0200 Subject: [PATCH 22/67] fix an EOL problem whjen replacing #define FRAMES_PER_SECOND --- src/wmc_tool/wmc_tool.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/wmc_tool/wmc_tool.cpp b/src/wmc_tool/wmc_tool.cpp index c2fdefc..0fbc89b 100644 --- a/src/wmc_tool/wmc_tool.cpp +++ b/src/wmc_tool/wmc_tool.cpp @@ -1028,7 +1028,7 @@ static TOOL_ERROR Output_Wmops_File( char *PathName, float frames_per_sec, bool { TOOL_ERROR ErrCode = NO_ERR; FILE *TargetFile; - int i, len, size; + int i, len; char SrcFileName[MAX_PATH + 1]; /* +1 for NUL Char*/ char TargetFileName[MAX_PATH + 1]; /* +1 for NUL Char*/ char *text = NULL, *p_str, temp_str[50]; @@ -1043,10 +1043,8 @@ static TOOL_ERROR Output_Wmops_File( char *PathName, float frames_per_sec, bool for (i = 0; i < 2; i++) { - /* Copy the source file contents to a char * buffer for further manipulation */ - size = i == 0 ? sizeof(wmops_auto_file_h) : sizeof(wmops_auto_file_c); - - text = (char*)calloc(size, sizeof(char)); + /* Allocate a char * buffer for further manipulation of the source file text */ + text = (char*)calloc(i == 0 ? sizeof(wmops_auto_file_h) : sizeof(wmops_auto_file_c), sizeof(char)); if (text == NULL) { ErrCode = ERR_FILE_READ; @@ -1054,15 +1052,16 @@ static TOOL_ERROR Output_Wmops_File( char *PathName, float frames_per_sec, bool goto ret; } - strncpy(text, i == 0 ? wmops_auto_file_h : wmops_auto_file_c, size); + /* copy the source file contents to a char * buffer for further manipulation */ + strcpy(text, i == 0 ? wmops_auto_file_h : wmops_auto_file_c); /* Replace the constant FRAMES_PER_SECOND */ - p_str = strstr(text, "#define FRAMES_PER_SECOND 50.0"); + p_str = strstr(text, "#define FRAMES_PER_SECOND"); if (p_str != NULL) { - sprintf(temp_str, "#define FRAMES_PER_SECOND %.1f", frames_per_sec); - strncpy(p_str, temp_str, sizeof(temp_str)); + sprintf(temp_str, "#define FRAMES_PER_SECOND %-8.1f", frames_per_sec); + strncpy(p_str, temp_str, strlen(temp_str)); } /* Create Target Filename */ @@ -1101,7 +1100,7 @@ static TOOL_ERROR Output_Wmops_File( char *PathName, float frames_per_sec, bool } /* Write the whole content to the target file */ - fwrite(text, size, 1, TargetFile); + fwrite(text, strlen(text), sizeof(char), TargetFile); fclose(TargetFile); free(text); } From 2c1c0a756a0aec98ac8cd47e406ca13eb26e7f21 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 19 Sep 2023 15:26:47 +0200 Subject: [PATCH 23/67] introduce dynamic allocation of internal WMOPS buffers and lists (repplacing constants MAX_RECORDS and MAX_RECORDABLE_CALLS), allows for re-allocation if max size is exceeded --- src/wmc_tool/test_data/ref/main1.c | 2 + src/wmc_tool/test_data/ref/test_basop.c | 2 + src/wmc_tool/test_data/ref/test_basop32.c | 1 + src/wmc_tool/test_data/ref/wmc_auto.c | 3905 +++++++++++---------- src/wmc_tool/test_data/ref/wmc_auto.h | Bin 43846 -> 42697 bytes src/wmc_tool/test_data/src/main1.c | 2 + src/wmc_tool/test_data/src/test_basop.c | 2 + src/wmc_tool/test_data/src/test_basop32.c | 1 + src/wmc_tool/wmc_auto_c.txt | 243 +- src/wmc_tool/wmc_auto_h.txt | 9 +- 10 files changed, 2139 insertions(+), 2028 deletions(-) diff --git a/src/wmc_tool/test_data/ref/main1.c b/src/wmc_tool/test_data/ref/main1.c index e7753d1..45657cd 100644 --- a/src/wmc_tool/test_data/ref/main1.c +++ b/src/wmc_tool/test_data/ref/main1.c @@ -65,3 +65,5 @@ int main( #endif return 0; } + +#undef WMC_TOOL_SKIP \ No newline at end of file diff --git a/src/wmc_tool/test_data/ref/test_basop.c b/src/wmc_tool/test_data/ref/test_basop.c index a3eef18..b090bf1 100644 --- a/src/wmc_tool/test_data/ref/test_basop.c +++ b/src/wmc_tool/test_data/ref/test_basop.c @@ -53,3 +53,5 @@ void weight_coef_a( const Word16 *a, Word16 *b, const Word16 ght ) return; } + +#undef WMC_TOOL_SKIP diff --git a/src/wmc_tool/test_data/ref/test_basop32.c b/src/wmc_tool/test_data/ref/test_basop32.c index 8a6875d..e0e733a 100644 --- a/src/wmc_tool/test_data/ref/test_basop32.c +++ b/src/wmc_tool/test_data/ref/test_basop32.c @@ -2427,5 +2427,6 @@ Word32 L_msu0 (Word32 L_var3, Word16 var1, Word16 var2) { return (L_var_out); } +#undef WMC_TOOL_SKIP /* end of file */ diff --git a/src/wmc_tool/test_data/ref/wmc_auto.c b/src/wmc_tool/test_data/ref/wmc_auto.c index 955c7ca..8e70ebe 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.c +++ b/src/wmc_tool/test_data/ref/wmc_auto.c @@ -1,1927 +1,1978 @@ -/* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. - * - * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, - * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file - * or refer to ITU-T Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS". - * - * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor - * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software - * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE. - * - * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca) - */ - -#include -#include -#include -#include -#include - -#ifndef _MSC_VER -#include -#include -#else -#include -#endif - -#include "wmc_auto.h" - - -#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */ - -#ifdef WMOPS - -/*-------------------------------------------------------------------* - * Complexity counting tool - *--------------------------------------------------------------------*/ - -#define MAX_RECORDS 1024 -#define MAX_CHAR 64 -#define MAX_STACK 64 -#define DOUBLE_MAX 0x80000000 - -struct wmops_record -{ - char label[MAX_CHAR]; - long call_number; - long update_cnt; - int call_tree[MAX_RECORDS]; - double start_selfcnt; - double current_selfcnt; - double max_selfcnt; - double min_selfcnt; - double tot_selfcnt; - double start_cnt; /* The following take into account the decendants */ - double current_cnt; - double max_cnt; - double min_cnt; - double tot_cnt; -#ifdef WMOPS_WC_FRAME_ANALYSIS - int32_t current_call_number; - double wc_cnt; - double wc_selfcnt; - int32_t wc_call_number; -#endif -}; - -double ops_cnt; -double prom_cnt; -double inst_cnt[NUM_INST]; - -static struct wmops_record wmops[MAX_RECORDS]; -static int stack[MAX_STACK]; -static int sptr; -static int num_records; -static int current_record; -static long update_cnt; -static double start_cnt; -static double max_cnt; -static double min_cnt; -static double inst_cnt_wc[NUM_INST]; -static long fnum_cnt_wc; - -static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0; - - -void reset_wmops( void ) -{ - int i, j; - - for ( i = 0; i < MAX_RECORDS; i++ ) - { - strcpy( &wmops[i].label[0], "\0" ); - wmops[i].call_number = 0; - wmops[i].update_cnt = 0; - for ( j = 0; j < MAX_RECORDS; j++ ) - { - wmops[i].call_tree[j] = -1; - } - wmops[i].start_selfcnt = 0.0; - wmops[i].current_selfcnt = 0.0; - wmops[i].max_selfcnt = 0.0; - wmops[i].min_selfcnt = DOUBLE_MAX; - wmops[i].tot_selfcnt = 0.0; - wmops[i].start_cnt = 0.0; - wmops[i].current_cnt = 0.0; - wmops[i].max_cnt = 0.0; - wmops[i].min_cnt = DOUBLE_MAX; - wmops[i].tot_cnt = 0.0; -#ifdef WMOPS_WC_FRAME_ANALYSIS - wmops[i].wc_cnt = 0.0; - wmops[i].wc_selfcnt = 0.0; - wmops[i].current_call_number = 0; -#endif - } - - for ( i = 0; i < MAX_STACK; i++ ) - { - stack[i] = -1; - } - sptr = 0; - num_records = 0; - current_record = -1; - update_cnt = 0; - - max_cnt = 0.0; - min_cnt = DOUBLE_MAX; - start_cnt = 0.0; - ops_cnt = 0.0; -} - - -void push_wmops( const char *label ) -{ - int new_flag; - int i, j; - - /* Check if new function record label */ - new_flag = 1; - for ( i = 0; i < num_records; i++ ) - { - if ( strcmp( wmops[i].label, label ) == 0 ) - { - new_flag = 0; - break; - } - } - - /* Configure new record */ - if ( new_flag ) - { - if ( num_records >= MAX_RECORDS ) - { - fprintf( stdout, "push_wmops(): exceeded MAX_RECORDS count.\n\n" ); - exit( -1 ); - } - strcpy( wmops[i].label, label ); - num_records++; - } - - /* Push current context onto stack */ - if ( current_record >= 0 ) - { - if ( sptr >= MAX_STACK ) - { - fprintf( stdout, "\r push_wmops(): stack exceeded, try inreasing MAX_STACK\n" ); - exit( -1 ); - } - stack[sptr++] = current_record; - - /* accumulate op counts */ - wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; - - /* update call tree */ - for ( j = 0; j < MAX_RECORDS; j++ ) - { - if ( wmops[i].call_tree[j] == current_record ) - { - break; - } - else if ( wmops[i].call_tree[j] == -1 ) - { - wmops[i].call_tree[j] = current_record; - break; - } - } - } - - /* init current record */ - current_record = i; - wmops[current_record].start_selfcnt = ops_cnt; - wmops[current_record].start_cnt = ops_cnt; - wmops[current_record].call_number++; -#ifdef WMOPS_WC_FRAME_ANALYSIS - wmops[current_record].current_call_number++; -#endif - - return; -} - - -void pop_wmops( void ) -{ - - /* Check for underflow */ - if ( current_record < 0 ) - { - fprintf( stdout, "\r pop_wmops(): stack underflow, too many calls to pop_wmops()\n" ); - exit( -1 ); - } - - /* update count of current record */ - wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; - wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt; - - /* Get back previous context from stack */ - if ( sptr > 0 ) - { - current_record = stack[--sptr]; - wmops[current_record].start_selfcnt = ops_cnt; - } - else - { - current_record = -1; - } - - return; -} - - -void update_wmops( void ) -{ - int i; - double current_cnt; -#ifdef WMOPS_PER_FRAME - static FILE *fid = NULL; - const char filename[] = "wmops_analysis"; - float tmpF; -#endif - - if ( sptr != 0 ) - { - fprintf( stdout, "update_wmops(): Stack must be empty!\n" ); - exit( -1 ); - } - -#ifdef WMOPS_PER_FRAME - /* Check, if the output file has already been opened */ - if ( fid == NULL ) - { - fid = fopen( filename, "wb" ); - - if ( fid == NULL ) - { - fprintf( stderr, "\nCannot open %s!\n\n", filename ); - exit( -1 ); - } - } - - /* Write current complexity to the external file */ - tmpF = (float) ( FAC * wmops[0].current_cnt ); - fwrite( &tmpF, sizeof( float ), 1, fid ); -#endif - -#ifdef WMOPS_WC_FRAME_ANALYSIS - if ( ops_cnt - start_cnt > max_cnt ) - { - for ( i = 0; i < num_records; i++ ) - { - wmops[i].wc_cnt = wmops[i].current_cnt; - wmops[i].wc_selfcnt = wmops[i].current_selfcnt; - wmops[i].wc_call_number = wmops[i].current_call_number; - } - } -#endif - - for ( i = 0; i < num_records; i++ ) - { - wmops[i].tot_selfcnt += wmops[i].current_selfcnt; - wmops[i].tot_cnt += wmops[i].current_cnt; - - if ( wmops[i].current_selfcnt > 0 ) - { - if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt ) - { - wmops[i].max_selfcnt = wmops[i].current_selfcnt; - } - - if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt ) - { - wmops[i].min_selfcnt = wmops[i].current_selfcnt; - } - } - - wmops[i].current_selfcnt = 0; - - if ( wmops[i].current_cnt > 0 ) - { - if ( wmops[i].current_cnt > wmops[i].max_cnt ) - { - wmops[i].max_cnt = wmops[i].current_cnt; - } - - if ( wmops[i].current_cnt < wmops[i].min_cnt ) - { - wmops[i].min_cnt = wmops[i].current_cnt; - } - - wmops[i].update_cnt++; - } - - wmops[i].current_cnt = 0; -#ifdef WMOPS_WC_FRAME_ANALYSIS - wmops[i].current_call_number = 0; -#endif - } - - current_cnt = ops_cnt - start_cnt; - if ( current_cnt > max_cnt ) - { - max_cnt = current_cnt; - - for ( i = 0; i < NUM_INST; i++ ) - { - inst_cnt_wc[i] = inst_cnt[i]; - } - - fnum_cnt_wc = update_cnt + 1; - } - - if ( current_cnt < min_cnt ) - { - min_cnt = current_cnt; - } - - for ( i = 0; i < NUM_INST; i++ ) - { - inst_cnt[i] = 0.0; - } - - start_cnt = ops_cnt; - - /* increment frame counter */ - update_cnt++; - - return; -} - - -void print_wmops( void ) -{ - int i, label_len, max_label_len; - - char *sfmts = "%*s %8s %8s %7s %7s\n"; - char *dfmts = "%*s %8.2f %8.3f %7.3f %7.3f\n"; - char *sfmt = "%*s %8s %8s %7s %7s %7s %7s %7s\n"; - char *dfmt = "%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n"; - -#ifdef WMOPS_WC_FRAME_ANALYSIS - int j; - char *sfmtt = "%20s %4s %15s\n"; - char *dfmtt = "%20s %4d "; -#endif - - /* calculate maximum label length for compact prinout */ - max_label_len = 0; - for ( i = 0; i < num_records; i++ ) - { - label_len = strlen( wmops[i].label ); - if ( label_len > max_label_len ) - { - max_label_len = label_len; - } - } - max_label_len += 4; - - fprintf( stdout, "\n\n --- Complexity analysis [WMOPS] --- \n\n" ); - - fprintf( stdout, "%*s %33s %23s\n", max_label_len, "", "|------ SELF ------|", "|--- CUMULATIVE ---|" ); - fprintf( stdout, sfmt, max_label_len, " routine", " calls", " min ", " max ", " avg ", " min ", " max ", " avg " ); - fprintf( stdout, sfmt, max_label_len, "---------------", "------", "------", "------", "------", "------", "------", "------" ); - - for ( i = 0; i < num_records; i++ ) - { - fprintf( stdout, dfmt, max_label_len, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt, - wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt, - FAC * wmops[i].max_selfcnt, - wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt, - wmops[i].min_cnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_cnt, - FAC * wmops[i].max_cnt, - wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt ); - } - - fprintf( stdout, sfmts, max_label_len, "---------------", "------", "------", "------", "------" ); - fprintf( stdout, dfmts, max_label_len, "total", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt ); - fprintf( stdout, "\n" ); - -#ifdef WMOPS_WC_FRAME_ANALYSIS - fprintf( stdout, "\nComplexity analysis for the worst-case frame %ld:\n", fnum_cnt_wc ); - fprintf( stdout, "%*s %8s %10s %12s\n", max_label_len, " routine", " calls", " SELF", " CUMULATIVE" ); - fprintf( stdout, "%*s %8s %10s %10s\n", max_label_len, "---------------", "------", "------", "----------" ); - - for ( i = 0; i < num_records; i++ ) - { - fprintf( stdout, "%*s %8d %10.3f %12.3f\n", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt ); - } - - fprintf( stdout, "\nCall Tree:\n\n" ); - fprintf( stdout, sfmtt, " function", "num", "called by: " ); - fprintf( stdout, sfmtt, "---------------", "---", "--------------" ); - - for ( i = 0; i < num_records; i++ ) - { - fprintf( stdout, dfmtt, wmops[i].label, i ); - for ( j = 0; wmops[i].call_tree[j] != -1; j++ ) - { - if ( j != 0 ) - { - fprintf( stdout, ", " ); - } - fprintf( stdout, "%d", wmops[i].call_tree[j] ); - } - fprintf( stdout, "\n" ); - } - - fprintf( stdout, sfmtt, "---------------", "---", "--------------" ); - fprintf( stdout, "\n\n" ); - - fprintf( stdout, "\nInstruction type analysis for the worst-case frame %ld:\n\n", fnum_cnt_wc ); /* added -- JPA */ - for ( i = 0; i < NUM_INST; i++ ) - { - switch ( (enum instructions) i ) - { - case _ADD: - fprintf( stdout, "\tAdds: %12.1f\n", inst_cnt_wc[i] ); - break; - case _ABS: - fprintf( stdout, "\tAbsolutes: %12.1f\n", inst_cnt_wc[i] ); - break; - case _MULT: - fprintf( stdout, "\tMultiplies: %12.1f\n", inst_cnt_wc[i] ); - break; - case _MAC: - fprintf( stdout, "\tMACs: %12.1f\n", inst_cnt_wc[i] ); - break; - case _MOVE: - fprintf( stdout, "\tMoves: %12.1f\n", inst_cnt_wc[i] ); - break; - case _STORE: - fprintf( stdout, "\tStores: %12.1f\n", inst_cnt_wc[i] ); - break; - case _LOGIC: - fprintf( stdout, "\tLogicals: %12.1f\n", inst_cnt_wc[i] ); - break; - case _SHIFT: - fprintf( stdout, "\tShifts: %12.1f\n", inst_cnt_wc[i] ); - break; - case _BRANCH: - fprintf( stdout, "\tBranches: %12.1f\n", inst_cnt_wc[i] ); - break; - case _DIV: - fprintf( stdout, "\tDivisions: %12.1f\n", inst_cnt_wc[i] ); - break; - case _SQRT: - fprintf( stdout, "\tSquare Root: %12.1f\n", inst_cnt_wc[i] ); - break; - case _TRANS: - fprintf( stdout, "\tTrans: %12.1f\n", inst_cnt_wc[i] ); - break; - case _FUNC: - fprintf( stdout, "\tFunc Call: %12.1f\n", inst_cnt_wc[i] ); - break; - case _LOOP: - fprintf( stdout, "\tLoop Init: %12.1f\n", inst_cnt_wc[i] ); - break; - case _INDIRECT: - fprintf( stdout, "\tIndirect Addr: %12.1f\n", inst_cnt_wc[i] ); - break; - case _PTR_INIT: - fprintf( stdout, "\tPointer Init: %12.1f\n", inst_cnt_wc[i] ); - break; - case _TEST: - fprintf( stdout, "\tExtra condit.: %12.1f\n", inst_cnt_wc[i] ); - break; - case _POWER: - fprintf( stdout, "\tExponential: %12.1f\n", inst_cnt_wc[i] ); - break; - case _LOG: - fprintf( stdout, "\tLogarithm: %12.1f\n", inst_cnt_wc[i] ); - break; - case _MISC: - fprintf( stdout, "\tAll other op.: %12.1f\n", inst_cnt_wc[i] ); - break; - default: - fprintf( stdout, "\tERROR: Invalid instruction type: %d\n\n", i ); - } - } -#endif - - return; -} - - -/*-------------------------------------------------------------------* - * Memory counting tool measuring RAM usage (stack and heap) - * - * Maximum RAM is measured by monitoring the total allocated memory (stack and heap) in each frame. - * - * Maximum stack is measured by monitoring the difference between the 'top' and 'bottom' of the stack. The 'bottom' of the stack is updated in each function - * with a macro 'func_start_' which is inserted automatically to all functions during the instrumentation process. - * - * Maximum heap is measured by summing the sizes of all memory blocks allocated by malloc() or calloc() and deallocated by free(). The maximum heap size is - * updated each time when the macros malloc_() or calloc_() is invoked. The macros 'malloc_ and calloc_' are inserted automatically during the instrumentation process. - * As part of heap measurements, intra-frame heap and inter-frame heap are measured separately. Intra-frame heap refers to heap memory which is allocated and deallocated - * within a single frame. Inter-frame heap, on the contrary, refers to heap memory which is reserved for more than one frame. - * - * In order to run the memory counting tool the function reset_mem(cnt_size) must be called at the beginning of the encoding/decoding process. - * The unit in which memory consumption is reported is set via the parameter 'cnt_size'. It can be set to 0 (bytes), 1 (32b words) or 2 (64b words). - * At the end of the encoding/decoding process, 'print_mem()' function may be called to print basic information about memory consumption. If the macro 'MEM_COUNT_DETAILS' - * is activated, detailed information is printed - * - * The macro 'WMOPS' needs to be activated to enable memory counting. To avoid the instrumentation of malloc()/calloc()/free() calls, use - * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free(). - *--------------------------------------------------------------------*/ - -#define MAX_RECORDABLE_CALLS 100 -#define MAX_FUNCTION_NAME_LENGTH 35 /* Maximum length that the function string will be truncated to */ -#define MAX_PARAMS_LENGTH 50 /* Maximum length that the parameter string will be truncated to */ -#define MAX_NUM_RECORDS 300 /* Initial maximum number of memory records -> mightb be increased during runtime, if needed */ -#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of memory records, increase the number of records by this number */ - -/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using - a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */ -#ifdef MEM_ALIGN_64BITS -#define BLOCK_ROUNDING 8 /* Align on 64 Bits */ -#else -#define BLOCK_ROUNDING 4 /* Align on 32 Bits */ -#endif - -#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) ) - -#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */ -#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */ -#define OOB_START 0x1 /* Flag indicating out-of-bounds access before memory block */ -#define OOB_END 0x2 /* Flag indicating out-of-bounds access after memory block */ - -#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) ) -#define IS_CALLOC( str ) ( str[0] == 'c' ) - -#ifdef MEM_COUNT_DETAILS -const char *csv_filename = "mem_analysis.csv"; -static FILE *fid_csv_filename = NULL; -#endif - -typedef struct -{ - char function_name[MAX_FUNCTION_NAME_LENGTH + 1]; - int16_t *stack_ptr; -} caller_info; - -caller_info stack_callers[2][MAX_RECORDABLE_CALLS]; - -typedef struct -{ - char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */ - char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */ - unsigned long hash; - int lineno; - void *block_ptr; - int block_size; - unsigned long total_block_size; /* Cumulative sum of the allocated size in the session */ - unsigned long total_used_size; /* Cumulative sum of the used size in the session */ - int wc_heap_size_intra_frame; /* Worst-Case Intra-Frame Heap Size */ - int wc_heap_size_inter_frame; /* Worst-Case Inter-Frame Heap Size */ - int frame_allocated; /* Frame number in which the Memory Block has been allocated (-1 if not allocated at the moment) */ - int OOB_Flag; - int noccurances; /* Number of times that the memory block has been allocated in a frame */ -} allocator_record; - -allocator_record *allocation_list = NULL; - -static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */ -static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */ -static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */ -static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */ -static int32_t wc_ram_size, wc_ram_frame; -static int32_t current_heap_size; -static int current_calls = 0; -static char location_max_stack[256] = "undefined"; -static int Num_Records, Max_Num_Records; -static size_t Stat_Cnt_Size = USE_BYTES; -static const char *Count_Unit[] = { "bytes", "words", "words" }; - -static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap; -static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap; -static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap; - -/* Local Functions */ -static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str ); -allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record ); -static void *mem_alloc_block( size_t size, const char *size_str ); - -/*-------------------------------------------------------------------* - * reset_mem() - * - * Initialize/reset memory counting tool (stack and heap) - *--------------------------------------------------------------------*/ - -void reset_mem( Counting_Size cnt_size ) -{ - int16_t something; - size_t tmp_size; - - /* initialize stack pointers */ - ptr_base_stack = &something; - ptr_max_stack = ptr_base_stack; - ptr_current_stack = ptr_base_stack; - - Stat_Cnt_Size = cnt_size; - - /* Check, if sizeof(int32_t) is 4 bytes */ - tmp_size = sizeof( int32_t ); - if ( tmp_size != 4 ) - { - fprintf( stderr, "Error: Expecting 'int32_t' to be a 32 Bits Integer!" ); - exit( -1 ); - } - - /* create allocation list for malloc() memory blocks */ - if ( allocation_list == NULL ) - { - allocation_list = malloc( MAX_NUM_RECORDS * sizeof( allocator_record ) ); - } - - if ( allocation_list == NULL ) - { - fprintf( stderr, "Error: Unable to Create List of Memory Blocks!" ); - exit( -1 ); - } - - Num_Records = 0; - Max_Num_Records = MAX_NUM_RECORDS; - - wc_ram_size = 0; - wc_ram_frame = -1; - current_heap_size = 0; - - /* heap allocation tree */ - heap_allocation_call_tree_max_size = MAX_NUM_RECORDS; - if ( heap_allocation_call_tree == NULL ) - { - heap_allocation_call_tree = (int *) malloc( heap_allocation_call_tree_max_size * sizeof( int ) ); - memset( heap_allocation_call_tree, -1, heap_allocation_call_tree_max_size * sizeof( int ) ); - } - heap_allocation_call_tree_size = 0; - - /* wc intra-frame heap */ - max_items_wc_intra_frame_heap = MAX_NUM_RECORDS; - if ( list_wc_intra_frame_heap == NULL ) - { - list_wc_intra_frame_heap = (int *) malloc( max_items_wc_intra_frame_heap * sizeof( int ) ); - memset( list_wc_intra_frame_heap, -1, max_items_wc_intra_frame_heap * sizeof( int ) ); - } - n_items_wc_intra_frame_heap = 0; - size_wc_intra_frame_heap = 0; - location_wc_intra_frame_heap = -1; - - /* current inter-frame heap */ - max_items_current_inter_frame_heap = MAX_NUM_RECORDS; - if ( list_current_inter_frame_heap == NULL ) - { - list_current_inter_frame_heap = (int *) malloc( max_items_current_inter_frame_heap * sizeof( int ) ); - memset( list_current_inter_frame_heap, -1, max_items_current_inter_frame_heap * sizeof( int ) ); - } - n_items_current_inter_frame_heap = 0; - size_current_inter_frame_heap = 0; - - /* wc inter-frame heap */ - max_items_wc_inter_frame_heap = MAX_NUM_RECORDS; - if ( list_wc_inter_frame_heap == NULL ) - { - list_wc_inter_frame_heap = (int *) malloc( max_items_wc_inter_frame_heap * sizeof( int ) ); - memset( list_wc_inter_frame_heap, -1, max_items_wc_inter_frame_heap * sizeof( int ) ); - } - n_items_wc_inter_frame_heap = 0; - size_wc_inter_frame_heap = 0; - location_wc_inter_frame_heap = -1; - -#ifdef MEM_COUNT_DETAILS - /* Check, if the .csv file has already been opened */ - if ( fid_csv_filename == NULL ) - { - fid_csv_filename = fopen( csv_filename, "wb" ); - - if ( fid_csv_filename == NULL ) - { - fprintf( stderr, "\nCannot open %s!\n\n", csv_filename ); - exit( -1 ); - } - } - else - { - /* reset file */ - rewind( fid_csv_filename ); - } -#endif - - return; -} - -/*-------------------------------------------------------------------* - * reset_stack() - * - * Reset stack pointer - *--------------------------------------------------------------------*/ - -void reset_stack( void ) -{ - int16_t something; - - /* initialize/reset stack pointers */ - ptr_base_stack = &something; - ptr_max_stack = ptr_base_stack; - ptr_current_stack = ptr_base_stack; - - return; -} - -/*-------------------------------------------------------------------* - * push_stack() - * - * Check the current stack pointer and update the maximum stack pointer, if new maximum found. - *--------------------------------------------------------------------*/ - -int push_stack( const char *filename, const char *fctname ) -{ - int16_t something; - int32_t current_stack_size; - - ptr_current_stack = &something; - - (void) *filename; /* to avoid compilation warning */ - - /* Is there room to save the caller's information? */ - if ( current_calls >= MAX_RECORDABLE_CALLS ) - { /* No */ - fprintf( stderr, "No more room to store call stack info. Please increase MAX_RECORDABLE_CALLS" ); - exit( -1 ); - } - - /* Valid Function Name? */ - if ( fctname[0] == 0 ) - { /* No */ - fprintf( stderr, "Invalid function name for call stack info." ); - exit( -1 ); - } - - /* Save the Name of the Calling Function in the Table */ - strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FUNCTION_NAME_LENGTH ); - stack_callers[0][current_calls].function_name[MAX_FUNCTION_NAME_LENGTH] = 0; /* Nul Terminate */ - - /* Save the Stack Pointer */ - stack_callers[0][current_calls].stack_ptr = ptr_current_stack; - - /* Increase Stack Calling Tree Level */ - current_calls++; - - /* Is this the First Time or the Worst Case? */ - if ( ptr_current_stack < ptr_max_stack || ptr_max_stack == NULL ) - { /* Yes */ - /* Save Info about it */ - ptr_max_stack = ptr_current_stack; - - wc_stack_frame = update_cnt; /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */ - strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 ); - location_max_stack[sizeof( location_max_stack ) - 1] = '\0'; - - /* Save Call Tree */ - memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls ); - - /* Terminate the List (Unless Full) */ - if ( current_calls < MAX_RECORDABLE_CALLS ) - { - stack_callers[1][current_calls].function_name[0] = 0; - } - } - - /* Check, if This is the New Worst-Case RAM (stack + heap) */ - current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); - - if ( current_stack_size < 0 ) - { - /* prevent negative stack size */ - current_stack_size = 0; - } - - if ( current_stack_size + current_heap_size > wc_ram_size ) - { - wc_ram_size = current_stack_size + current_heap_size; - wc_ram_frame = update_cnt; - } - - return 0 /* for Now */; -} - -/*-------------------------------------------------------------------* - * pop_stack() - * - * Remove stack caller entry from the list - *--------------------------------------------------------------------*/ - -int pop_stack( const char *filename, const char *fctname ) -{ - caller_info *caller_info_ptr; - - (void) *filename; /* to avoid compilation warning */ - - /* Decrease Stack Calling */ - current_calls--; - - /* Get Pointer to Caller Information */ - caller_info_ptr = &stack_callers[0][current_calls]; - - /* Check, if Names Match */ - if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 ) - { - fprintf( stderr, "Invalid usage of pop_stack()" ); - exit( -1 ); - } - - /* Erase Entry */ - caller_info_ptr->function_name[0] = 0; - - /* Retrieve previous stack pointer */ - if ( current_calls == 0 ) - { - ptr_current_stack = ptr_base_stack; - } - else - { - ptr_current_stack = stack_callers[0][current_calls - 1].stack_ptr; - } - - return 0 /* for Now */; -} - -#ifdef MEM_COUNT_DETAILS -/*-------------------------------------------------------------------* - * print_stack_call_tree() - * - * Print detailed information about worst-case stack usage - *--------------------------------------------------------------------*/ - -static void print_stack_call_tree( void ) -{ - caller_info *caller_info_ptr; - int call_level; - char fctname[MAX_FUNCTION_NAME_LENGTH + 1]; - - fprintf( stdout, "\nList of functions when maximum stack size is reached:\n\n" ); - - caller_info_ptr = &stack_callers[1][0]; - for ( call_level = 0; call_level < MAX_RECORDABLE_CALLS; call_level++ ) - { - /* Done? */ - if ( caller_info_ptr->function_name[0] == 0 ) - { - break; - } - - /* Print Name */ - strncpy( fctname, caller_info_ptr->function_name, MAX_FUNCTION_NAME_LENGTH ); - strcat( fctname, "()" ); - fprintf( stdout, "%-42s", fctname ); - - /* Print Stack Usage (Based on Difference) */ - if ( call_level != 0 ) - { - fprintf( stdout, "%lu %s\n", ( ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); - } - else - { - fprintf( stdout, "%lu %s\n", ( ( ptr_base_stack - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); - } - - /* Advance */ - caller_info_ptr++; - } - - fprintf( stdout, "\n" ); - - return; -} -#endif - - -/*-------------------------------------------------------------------* - * mem_alloc() - * - * Creates new record, stores auxiliary information about which function allocated the memory, line number, parameters, etc. - * Finally, it allocates physical memory using malloc() - * The function also updates worst-case heap size and worst-case RAM size - *--------------------------------------------------------------------*/ - -void *mem_alloc( - const char *func_name, - int func_lineno, - size_t size, - char *size_str /* the first char indicates m-alloc or c-alloc */ ) -{ - int index_record; - int32_t current_stack_size; - unsigned long hash; - allocator_record *ptr_record; - - if ( size == 0 ) - { - fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Size of Zero not Supported" ); - exit( -1 ); - } - - /* Search for an existing record (that has been de-allocated before) */ - index_record = 0; - while ( ( ptr_record = get_mem_record( &hash, func_name, func_lineno, size_str, &index_record ) ) != NULL ) - { - if ( ptr_record->frame_allocated == -1 ) - { - break; - } - else - { - index_record++; - } - } - - /* Create new record */ - if ( ptr_record == NULL ) - { - if ( Num_Records >= Max_Num_Records ) - { - /* There is no room for a new record -> reallocate memory */ - Max_Num_Records += MAX_NUM_RECORDS_REALLOC_STEP; - allocation_list = realloc( allocation_list, Max_Num_Records * sizeof( allocator_record ) ); - } - - ptr_record = &( allocation_list[Num_Records] ); - - /* Initialize new record */ - ptr_record->hash = hash; - ptr_record->noccurances = 0; - ptr_record->total_block_size = 0; - ptr_record->total_used_size = 0; - ptr_record->frame_allocated = -1; - ptr_record->OOB_Flag = 0; - ptr_record->wc_heap_size_intra_frame = -1; - ptr_record->wc_heap_size_inter_frame = -1; - - index_record = Num_Records; - Num_Records++; - } - - /* Allocate memory block for the new record, add signature before the beginning and after the memory block and fill it with magic value */ - ptr_record->block_ptr = mem_alloc_block( size, size_str ); - - if ( ptr_record->block_ptr == NULL ) - { - fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Cannot Allocate Memory!" ); - exit( -1 ); - } - - /* Save all auxiliary information about the memory block */ - strncpy( ptr_record->name, func_name, MAX_FUNCTION_NAME_LENGTH ); - ptr_record->name[MAX_FUNCTION_NAME_LENGTH] = '\0'; - strncpy( ptr_record->params, size_str, MAX_PARAMS_LENGTH ); /* Note: The size string starts with either 'm' or 'c' to indicate 'm'alloc or 'c'alloc */ - ptr_record->params[MAX_PARAMS_LENGTH] = '\0'; - ptr_record->lineno = func_lineno; - ptr_record->block_size = size; - ptr_record->total_block_size += size; - -#ifdef MEM_COUNT_DETAILS - /* Export heap memory allocation record to the .csv file */ - fprintf( fid_csv_filename, "A,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); -#endif - - if ( ptr_record->frame_allocated != -1 ) - { - fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Attempt to Allocate the Same Memory Block with Freeing it First!" ); - exit( -1 ); - } - - ptr_record->frame_allocated = update_cnt; /* Store the current frame number -> later it will be used to determine the total duration */ - - /* Update Heap Size in the current frame */ - current_heap_size += ptr_record->block_size; - - /* Check, if this is the new Worst-Case RAM (stack + heap) */ - current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); - if ( current_stack_size + current_heap_size > wc_ram_size ) - { - wc_ram_size = current_stack_size + current_heap_size; - wc_ram_frame = update_cnt; - } - - /* Add new entry to the heap allocation call tree */ - if ( heap_allocation_call_tree == NULL ) - { - fprintf( stderr, "Error: Heap allocation call tree not created!" ); - exit( -1 ); - } - - /* check, if the maximum size of the call tree has been reached -> resize if so */ - if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size ) - { - heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP; - heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) ); - } - - /* push new entry (positive number means push op, neagtive number means pop op; zero index must be converted to 0.01 :-) */ - heap_allocation_call_tree[heap_allocation_call_tree_size++] = index_record; - - return ptr_record->block_ptr; -} - -/*-------------------------------------------------------------------* - * mem_alloc_block() - * - * Physical allocation of memory using malloc(). Appends 'signature' before and after the block, - * pre-fills memory block with magic value - *--------------------------------------------------------------------*/ - -static void *mem_alloc_block( size_t size, const char *size_str ) -{ - size_t rounded_size; - void *block_ptr; - char *tmp_ptr; - size_t n, f; - int32_t fill_value; - int32_t *ptr32; - int32_t mask, temp; - - /* Round Up Block Size */ - rounded_size = ROUND_BLOCK_SIZE( size ); - - /* Allocate memory using the standard malloc() by adding room for Signature Values */ - block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 ); - - if ( block_ptr == NULL ) - { - return NULL; - } - - /* Add Signature Before the Start of the Block */ - ptr32 = (int32_t *) block_ptr; - n = N_32BITS_BLOCKS; - do - { - *ptr32++ = MAGIC_VALUE_OOB; - } while ( --n ); - - /* Fill Memory Block with Magic Value or 0 */ - fill_value = MAGIC_VALUE_USED; - if ( IS_CALLOC( size_str ) ) - { - fill_value = 0x00000000; - } - n = size / sizeof( int32_t ); - while ( n-- ) - { - *ptr32++ = fill_value; - } - - /* Fill the Reminder of the Memory Block - After Rounding */ - n = rounded_size - size; - f = n % sizeof( int32_t ); - if ( f != 0 ) - { - /* when filling with '0' need to adapt the magic value */ - /* shift by [1->24, 2->16, 3->8] */ - mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */ - temp = MAGIC_VALUE_OOB & mask; - if ( fill_value != 0x0 ) - { /* for malloc merge fill value */ - temp += ( ~mask ) & MAGIC_VALUE_USED; - } /* for calloc the code in (1) above already introduces zeros */ - *ptr32++ = temp; - } - n /= sizeof( int32_t ); - n += N_32BITS_BLOCKS; - - /* Add Signature After the End of Block */ - do - { - *ptr32++ = MAGIC_VALUE_OOB; - } while ( --n ); - - /* Adjust the Memory Block Pointer (Magic Value Before and After the Memory Block Requested) */ - tmp_ptr = (char *) block_ptr; - tmp_ptr += BLOCK_ROUNDING; - block_ptr = (void *) tmp_ptr; - - return block_ptr; -} - -/*-------------------------------------------------------------------* - * mem_set_usage() - * - * Calculates actual usage of memory block by checking the magic value that was used to pre-fill - * each memory block during its allocation - *--------------------------------------------------------------------*/ - -static int mem_set_usage( allocator_record *record_ptr ) -{ - int total_bytes_used; - - size_t n; - int32_t *ptr32; - char *ptr8; - size_t total_bytes; - int32_t fill_value; - - fill_value = MAGIC_VALUE_USED; - if ( ( record_ptr->params[0] ) == 'c' ) - { - fill_value = 0x00000000; - } - - total_bytes = record_ptr->block_size; - - /* Check 4 bytes at a time */ - ptr32 = (int32_t *) record_ptr->block_ptr; - total_bytes_used = 0; - for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- ) - { - if ( *ptr32++ != fill_value ) - { - total_bytes_used += sizeof( int32_t ); - } - } - - /* Check remaining bytes (If Applicable) 1 byte at a time */ - ptr8 = (char *) ptr32; - for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- ) - { - if ( *ptr8++ != (char) fill_value ) - { - total_bytes_used++; - } - - /* Update Value */ - fill_value >>= 8; - } - - return total_bytes_used; -} - -/*-------------------------------------------------------------------* - * mem_check_OOB() - * - * Checks, if out-of-bounds access has occured. This is done by inspecting the 'signature' value - * taht has been added before and after the memory block during its allocation - *--------------------------------------------------------------------*/ - -static unsigned int mem_check_OOB( allocator_record *record_ptr ) -{ - int32_t *ptr32; - unsigned int OOB_Flag = 0x0; - int32_t mask; - size_t i; - int f; - - ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS; - - /* Check the Signature at the Beginning of Memory Block */ - i = N_32BITS_BLOCKS; - do - { - if ( *ptr32++ ^ MAGIC_VALUE_OOB ) - { - OOB_Flag |= OOB_START; - } - } while ( --i ); - - /* Advance to End (Snap to lowest 32 Bits) */ - ptr32 += record_ptr->block_size / sizeof( int32_t ); - - /* Calculate Unused Space That has been added to get to the rounded Block Size */ - i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size; - - /* Partial Check of Signature at the End of Memory Block (for block size that has been rounded) */ - f = i % sizeof( int32_t ); - if ( f != 0 ) - { - mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); - if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask ) - { - OOB_Flag |= OOB_END; - } - } - - /* Full Check of Signature at the End of Memory Block, i.e. all 32 Bits (for the remainder after rounding) */ - i /= sizeof( int32_t ); - i += N_32BITS_BLOCKS; - do - { - if ( *ptr32++ ^ MAGIC_VALUE_OOB ) - { - OOB_Flag |= OOB_END; - } - } while ( --i ); - - return OOB_Flag; -} - -/*-------------------------------------------------------------------* - * malloc_hash() - * - * Calculate hash from function name, line number and malloc size - *--------------------------------------------------------------------*/ - -static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str ) -{ - unsigned long hash = 5381; - const char *ptr_str; - - ptr_str = func_name; - while ( ptr_str != NULL && *ptr_str != '\0' ) - { - hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */ - } - - hash = ( ( hash << 5 ) + hash ) + func_lineno; /* hash * 33 + func_lineno */ - - ptr_str = size_str; - while ( ptr_str != NULL && *ptr_str != '\0' ) - { - hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */ - } - - return hash; -} - -/*-------------------------------------------------------------------* - * get_mem_record() - * - * Search for memory record in the internal list, return NULL if not found - * Start from index_record - *--------------------------------------------------------------------*/ - -allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record ) -{ - int i; - - if ( *index_record < 0 || *index_record > Num_Records ) - { - return NULL; - } - - /* calculate hash */ - *hash = malloc_hash( func_name, func_lineno, size_str ); - - for ( i = *index_record; i < Num_Records; i++ ) - { - /* check, if memory block is not allocated at the moment and the hash matches */ - if ( allocation_list[i].block_ptr == NULL && *hash == allocation_list[i].hash ) - { - *index_record = i; - return &( allocation_list[i] ); - } - } - - /* not found */ - *index_record = -1; - return NULL; -} - - -/*-------------------------------------------------------------------* - * mem_free() - * - * This function de-allocatesd the memory block and frees the mphysical memory with free(). - * It also updates actual and average usage of the memory block. - * - * Note: The record is not removed from the list and may be reused later on in mem_alloc()! - *--------------------------------------------------------------------*/ - -void mem_free( const char *func_name, int func_lineno, void *ptr ) -{ - int i, index_record; - char *tmp_ptr; - allocator_record *ptr_record; - - /* Search for the Block Pointer in the List */ - ptr_record = NULL; - index_record = -1; - for ( i = 0; i < Num_Records; i++ ) - { - if ( ptr == allocation_list[i].block_ptr ) - { /* Yes, Found it */ - ptr_record = &( allocation_list[i] ); - index_record = i; - break; - } - } - - if ( ptr_record == NULL ) - { - fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Unable to Find Record Corresponding to the Allocated Memory Block!" ); - exit( -1 ); - } - - /* Update the Heap Size */ - current_heap_size -= ptr_record->block_size; - - /* Calculate the Actual Usage of the Memory Block (Look for Signature) */ - ptr_record->total_used_size += mem_set_usage( ptr_record ); - - /* Check, if Out-Of-Bounds Access has been Detected */ - ptr_record->OOB_Flag = mem_check_OOB( ptr_record ); - -#ifdef MEM_COUNT_DETAILS - /* Export heap memory de-allocation record to the .csv file */ - fprintf( fid_csv_filename, "D,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); -#endif - - /* De-Allocate Memory Block */ - tmp_ptr = (char *) ptr; - tmp_ptr -= BLOCK_ROUNDING; - ptr = (void *) tmp_ptr; - free( ptr ); - - /* Add new entry to the heap allocation call tree */ - if ( heap_allocation_call_tree == NULL ) - { - fprintf( stderr, "Error: Heap allocation call tree not created!" ); - exit( -1 ); - } - - /* check, if the maximum size of the call tree has been reached -> resize if so */ - if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size ) - { - heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP; - heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) ); - } - - heap_allocation_call_tree[heap_allocation_call_tree_size++] = -index_record; - - /* Reset memory block pointer (this is checked when updating wc intra-frame and inter-frame memory) */ - ptr_record->block_ptr = NULL; - - return; -} - - -/*-------------------------------------------------------------------* - * update_mem() - * - * This function updates the worst-case intra-frame memory and the worst-case inter-frame memory. - *--------------------------------------------------------------------*/ - -void update_mem( void ) -{ - int i, j, flag_alloc = -1, i_record; - int size_current_intra_frame_heap; - int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap; - allocator_record *ptr_record; - - /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */ - n_items_current_intra_frame_heap = 0; - size_current_intra_frame_heap = 0; - for ( i = 0; i < heap_allocation_call_tree_size; i++ ) - { - /* get the record */ - i_record = heap_allocation_call_tree[i]; - - if ( i_record > 0 ) - { - flag_alloc = 1; - } - else if ( i_record < 0 ) - { - flag_alloc = 0; - i_record = -i_record; - } - ptr_record = &( allocation_list[i_record] ); - - if ( ptr_record->frame_allocated == update_cnt && ptr_record->block_ptr == NULL ) - { - /* intra-frame heap memory */ - if ( list_current_intra_frame_heap == NULL ) - { - list_current_intra_frame_heap = (int *) malloc( heap_allocation_call_tree_size * sizeof( int ) ); - memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) ); - } - - /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ - if ( i_record == 0 ) - { - flag_alloc = 1; - for ( j = 0; j < n_items_current_intra_frame_heap; j++ ) - { - if ( list_current_intra_frame_heap[j] == i_record ) - { - flag_alloc = 0; - break; - } - } - } - - if ( flag_alloc ) - { - /* add to list */ - list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record; - size_current_intra_frame_heap += ptr_record->block_size; - - /* no need to re-size the list -> the initially allocated size should be large enough */ - } - else - { - /* remove from list */ - for ( j = 0; j < n_items_current_intra_frame_heap; j++ ) - { - if ( list_current_intra_frame_heap[j] == i_record ) - { - break; - } - } - memmove( &list_current_intra_frame_heap[j], &list_current_intra_frame_heap[j + 1], ( n_items_current_intra_frame_heap - j ) * sizeof( int ) ); - n_items_current_intra_frame_heap--; - size_current_intra_frame_heap -= ptr_record->block_size; - - /* reset block size */ - ptr_record->frame_allocated = -1; - ptr_record->block_size = 0; - } - } - else - { - /* inter-frame heap memory */ - - /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ - if ( i_record == 0 ) - { - flag_alloc = 1; - for ( j = 0; j < n_items_current_inter_frame_heap; j++ ) - { - if ( list_current_inter_frame_heap[j] == i_record ) - { - flag_alloc = 0; - break; - } - } - } - - if ( flag_alloc ) - { - /* add to list */ - if ( n_items_current_inter_frame_heap >= max_items_current_inter_frame_heap ) - { - /* resize list, if needed */ - max_items_current_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; - list_current_inter_frame_heap = realloc( list_current_inter_frame_heap, max_items_current_inter_frame_heap * sizeof( int ) ); - } - - list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record; - size_current_inter_frame_heap += ptr_record->block_size; - } - else - { - /* remove from list */ - for ( j = 0; j < n_items_current_inter_frame_heap; j++ ) - { - if ( list_current_inter_frame_heap[j] == i_record ) - { - break; - } - } - memmove( &list_current_inter_frame_heap[j], &list_current_inter_frame_heap[j + 1], ( n_items_current_inter_frame_heap - j ) * sizeof( int ) ); - n_items_current_inter_frame_heap--; - size_current_inter_frame_heap -= ptr_record->block_size; - - /* reset block size */ - ptr_record->frame_allocated = -1; - ptr_record->block_size = 0; - } - } - } - - /* check, if this is the new worst-case for intra-frame heap memory */ - if ( size_current_intra_frame_heap > size_wc_intra_frame_heap ) - { - if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap ) - { - /* resize the list, if needed */ - max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; - list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) ); - } - - /* copy current-frame list to worst-case list */ - memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) ); - n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap; - size_wc_intra_frame_heap = size_current_intra_frame_heap; - location_wc_intra_frame_heap = update_cnt; - - /* update the wc numbers in all individual records */ - for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) - { - i_record = list_wc_intra_frame_heap[i]; - ptr_record = &( allocation_list[i_record] ); - ptr_record->wc_heap_size_intra_frame = ptr_record->block_size; - } - } - - /* check, if this is the new worst-case for inter-frame heap memory */ - if ( size_current_inter_frame_heap > size_wc_inter_frame_heap ) - { - if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap ) - { - /* resize list, if needed */ - max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; - list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) ); - } - - /* copy current-frame list to worst-case list */ - memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) ); - n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap; - size_wc_inter_frame_heap = size_current_inter_frame_heap; - location_wc_inter_frame_heap = update_cnt; - - /* update the wc numbers in all individual records */ - for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) - { - i_record = list_wc_inter_frame_heap[i]; - ptr_record = &( allocation_list[i_record] ); - ptr_record->wc_heap_size_inter_frame = ptr_record->block_size; - } - } - - /* reset heap allocation call tree */ - heap_allocation_call_tree_size = 0; - - /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */ - if ( list_current_intra_frame_heap ) - { - free( list_current_intra_frame_heap ); - } - - return; -} - -#ifdef MEM_COUNT_DETAILS -/*-------------------------------------------------------------------* - * subst() - * - * Substitute character in string - *--------------------------------------------------------------------*/ - -static void subst( char *s, char from, char to ) -{ - while ( *s == from ) - { - *s++ = to; - } - - return; -} - - -/*-------------------------------------------------------------------* - * mem_count_summary() - * - * Print detailed (per-item) information about heap memory usage - *--------------------------------------------------------------------*/ - -static void mem_count_summary( void ) -{ - int i, j, index, index_record; - size_t length; - char buf[300], format_str[50], name_str[MAX_FUNCTION_NAME_LENGTH + 3], parms_str[MAX_PARAMS_LENGTH + 1], type_str[10], usage_str[20], size_str[20], line_str[10]; - allocator_record *ptr_record, *ptr; - - /* Prepare format string */ - sprintf( format_str, "%%-%ds %%5s %%6s %%-%ds %%20s %%6s ", MAX_FUNCTION_NAME_LENGTH, MAX_PARAMS_LENGTH ); - - if ( n_items_wc_intra_frame_heap > 0 ) - { - /* Intra-Frame Heap Size */ - fprintf( stdout, "\nList of memory blocks when maximum intra-frame heap size is reached:\n\n" ); - - /* Find duplicate records (same hash and worst-case heap size) */ - for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) - { - index_record = list_wc_intra_frame_heap[i]; - if ( index_record == -1 ) - { - continue; - } - - ptr_record = &( allocation_list[index_record] ); - for ( j = i + 1; j < n_items_wc_intra_frame_heap; j++ ) - { - index = list_wc_intra_frame_heap[j]; - if ( index == -1 ) - { - continue; - } - ptr = &( allocation_list[index] ); - - if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_intra_frame == ptr_record->wc_heap_size_intra_frame ) - { - ptr_record->noccurances++; - list_wc_intra_frame_heap[j] = -1; - } - } - } - - /* Print Header */ - sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Maximum Size", "Usage" ); - puts( buf ); - length = strlen( buf ); - sprintf( buf, "%0*d\n", (int) length - 1, 0 ); - subst( buf, '0', '-' ); - puts( buf ); - - for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) - { - index_record = list_wc_intra_frame_heap[i]; - - if ( index_record != -1 ) - { - /* get the record */ - ptr_record = &( allocation_list[index_record] ); - - /* prepare information strings */ - strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH ); - strcat( name_str, "()" ); - name_str[MAX_FUNCTION_NAME_LENGTH] = '\0'; - strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH ); - parms_str[MAX_PARAMS_LENGTH] = '\0'; - - if ( ptr_record->params[0] == 'm' ) - { - strcpy( type_str, "malloc" ); - } - else - { - strcpy( type_str, "calloc" ); - } - - sprintf( line_str, "%d", ptr_record->lineno ); - - /* prepare average usage & memory size strings */ - sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) ); - - if ( ptr_record->noccurances > 1 ) - { - sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); - } - else - { - sprintf( size_str, "%d %s", (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); - } - - sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str ); - puts( buf ); - } - } - - fprintf( stdout, "\n" ); - } - - if ( n_items_wc_inter_frame_heap > 0 ) - { - /* Inter-Frame Heap Size */ - fprintf( stdout, "\nList of memory blocks when maximum inter-frame heap size is reached:\n\n" ); - - /* Find duplicate records (same hash and worst-case heap size) */ - for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) - { - index_record = list_wc_inter_frame_heap[i]; - if ( index_record == -1 ) - { - continue; - } - ptr_record = &( allocation_list[index_record] ); - ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */ - for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ ) - { - index = list_wc_inter_frame_heap[j]; - if ( index == -1 ) - { - continue; - } - ptr = &( allocation_list[index] ); - - if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_inter_frame == ptr_record->wc_heap_size_inter_frame ) - { - ptr_record->noccurances++; - list_wc_inter_frame_heap[j] = -1; - } - } - } - - /* Print Header */ - sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Memory Size", "Usage" ); - puts( buf ); - length = strlen( buf ); - sprintf( buf, "%0*d\n", (int) length - 1, 0 ); - subst( buf, '0', '-' ); - puts( buf ); - - for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) - { - index_record = list_wc_inter_frame_heap[i]; - - if ( index_record != -1 ) - { - /* get the record */ - ptr_record = &( allocation_list[index_record] ); - - /* prepare information strings */ - strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH ); - strcat( name_str, "()" ); - name_str[MAX_FUNCTION_NAME_LENGTH] = '\0'; - strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH ); - parms_str[MAX_PARAMS_LENGTH] = '\0'; - - if ( ptr_record->params[0] == 'm' ) - { - strcpy( type_str, "malloc" ); - } - else - { - strcpy( type_str, "calloc" ); - } - - sprintf( line_str, "%d", ptr_record->lineno ); - - /* prepare average usage & memory size strings */ - sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) ); - - if ( ptr_record->noccurances > 1 ) - { - sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); - } - else - { - sprintf( size_str, "%d %s", (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); - } - - sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str ); - puts( buf ); - } - } - - fprintf( stdout, "\n" ); - } - - return; -} - -#endif - -/*-------------------------------------------------------------------* - * print_mem() - * - * Print information about ROM and RAM memory usage - *--------------------------------------------------------------------*/ - -void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) -{ - int i, nElem; - - fprintf( stdout, "\n\n --- Memory usage --- \n\n" ); - - if ( Const_Data_PROM_Table != NULL ) - { - nElem = 0; - while ( strcmp( Const_Data_PROM_Table[nElem].file_spec, "" ) != 0 ) - nElem++; - - for ( i = 0; i < nElem; i++ ) - { - fprintf( stdout, "Program ROM size (%s): %d instruction words\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size ); - } - - for ( i = 0; i < nElem; i++ ) - { - if ( Const_Data_PROM_Table[i].Get_Const_Data_Size_Func == NULL ) - { - fprintf( stdout, "Error: Cannot retrieve or calculate Table ROM size of (%s)!\n", Const_Data_PROM_Table[i].file_spec ); - } - - fprintf( stdout, "Table ROM (const data) size (%s): %d %s\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].Get_Const_Data_Size_Func() >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); - } - } - else - { - fprintf( stdout, "Program ROM size: not available\n" ); - fprintf( stdout, "Table ROM (const data) size: not available\n" ); - } - - if ( wc_ram_size > 0 ) - { - fprintf( stdout, "Maximum RAM (stack + heap) size: %d %s in frame %d\n", wc_ram_size >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], wc_ram_frame ); - } - else - { - fprintf( stdout, "Maximum RAM (stack + heap) size: not available\n" ); - } - - /* check, if the stack is empty */ - if ( ptr_current_stack != ptr_base_stack ) - { - fprintf( stderr, "Warning: Stack is not empty.\n" ); - } - - if ( ptr_base_stack - ptr_max_stack > 0 ) - { - fprintf( stdout, "Maximum stack size: %lu %s in frame %d\n", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], - wc_stack_frame ); - } - else - { - fprintf( stdout, "Maximum stack size: not available\n" ); - } - - /* last update of intra-frame memory and inter-frame memory, if needed */ - if ( heap_allocation_call_tree_size > 0 ) - { - update_mem(); - } - - /* check, if all memory blocks have been deallocated (freed) */ - for ( i = 0; i < Num_Records; i++ ) - { - if ( allocation_list[i].block_ptr != NULL ) - { - fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", allocation_list[i].name, allocation_list[i].lineno, "Error: Memory Block has not been De-Allocated with free()!" ); - exit( -1 ); - } - } - - if ( n_items_wc_intra_frame_heap > 0 ) - { - fprintf( stdout, "Maximum intra-frame heap size: %d %s in frame %d\n", size_wc_intra_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_intra_frame_heap ); - } - else - { - fprintf( stdout, "Maximum intra-frame heap size: 0\n" ); - } - - if ( n_items_wc_inter_frame_heap > 0 ) - { - fprintf( stdout, "Maximum inter-frame heap size: %d %s in frame %d\n", size_wc_inter_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_inter_frame_heap ); - } - else - { - fprintf( stdout, "Maximum inter-frame heap size: 0\n" ); - } - -#ifdef MEM_COUNT_DETAILS - /* Print detailed information about worst-case stack usage */ - if ( ptr_base_stack - ptr_max_stack > 0 ) - { - print_stack_call_tree(); - } - - /* Print detailed information about worst-case heap usage */ - mem_count_summary(); -#endif - - if ( Stat_Cnt_Size > 0 ) - { - fprintf( stdout, "\nNote: 1 word = %d bits\n", 8 << Stat_Cnt_Size ); - fprintf( stdout, "This is an optimistic estimate of memory consumption assuming that each variable type is stored with sizeof(type) bits\n" ); - } - - if ( n_items_wc_intra_frame_heap > 0 ) - { - fprintf( stdout, "Intra-frame heap memory is allocated and de-allocated in the same frame\n" ); - } - - /* De-allocate list of heap memory blocks */ - if ( allocation_list != NULL ) - { - free( allocation_list ); - } - - /* De-allocate heap allocation call tree */ - if ( heap_allocation_call_tree != NULL ) - { - free( heap_allocation_call_tree ); - } - - /* De-allocate intra-frame and inter-frame heap lists */ - if ( list_wc_intra_frame_heap != NULL ) - { - free( list_wc_intra_frame_heap ); - } - - if ( list_current_inter_frame_heap != NULL ) - { - free( list_current_inter_frame_heap ); - } - - if ( list_wc_inter_frame_heap != NULL ) - { - free( list_wc_inter_frame_heap ); - } - -#ifdef MEM_COUNT_DETAILS - if ( fid_csv_filename != NULL ) - { - fclose( fid_csv_filename ); - } -#endif - - return; -} - -#endif /* WMOPS */ - -#ifndef WMOPS -int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */ -#endif - - \ No newline at end of file +/* + * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * + * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, + * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file + * or refer to ITU-T Recommendation G.191 on "SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS". + * + * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor + * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software + * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE. + * + * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca) + */ + +#include +#include +#include +#include +#include + +#ifndef _MSC_VER +#include +#include +#else +#include +#endif + +#include "wmc_auto.h" + +#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */ + +#ifdef WMOPS + +/*-------------------------------------------------------------------* + * Complexity counting tool + *--------------------------------------------------------------------*/ + +#define MAX_FUNCTION_NAME_LENGTH 50 /* Maximum length of the function name */ +#define MAX_PARAMS_LENGTH 50 /* Maximum length of the function parameter string */ +#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> mightb be increased during runtime, if needed */ +#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */ + +#define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */ +#define DOUBLE_MAX 0x80000000 + +typedef struct +{ + char label[MAX_FUNCTION_NAME_LENGTH]; + long call_number; + long update_cnt; + int call_tree[MAX_CALL_TREE_DEPTH]; + double start_selfcnt; + double current_selfcnt; + double max_selfcnt; + double min_selfcnt; + double tot_selfcnt; + double start_cnt; + double current_cnt; + double max_cnt; + double min_cnt; + double tot_cnt; +#ifdef WMOPS_WC_FRAME_ANALYSIS + int32_t current_call_number; + double wc_cnt; + double wc_selfcnt; + int32_t wc_call_number; +#endif +} wmops_record; + +double ops_cnt; +double prom_cnt; +double inst_cnt[NUM_INST]; + +static wmops_record *wmops = NULL; +static int num_wmops_records, max_num_wmops_records; +static int current_record; +static long update_cnt; +static double start_cnt; +static double max_cnt; +static double min_cnt; +static double inst_cnt_wc[NUM_INST]; +static long fnum_cnt_wc; +static int *wmops_caller_stack = NULL, wmops_caller_stack_index, max_wmops_caller_stack_index = 0; +static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0; + +void reset_wmops( void ) +{ + int i, j; + + num_wmops_records = 0; + max_num_wmops_records = MAX_NUM_RECORDS; + current_record = -1; + update_cnt = 0; + + max_cnt = 0.0; + min_cnt = DOUBLE_MAX; + start_cnt = 0.0; + ops_cnt = 0.0; + + /* allocate the list of wmops records */ + if ( wmops == NULL ) + { + wmops = (wmops_record *)malloc( max_num_wmops_records * sizeof( wmops_record ) ); + } + + if ( wmops == NULL ) + { + fprintf( stderr, "Error: Unable to Allocate List of WMOPS Records!" ); + exit( -1 ); + } + + for ( i = 0; i < max_num_wmops_records; i++ ) + { + strcpy( &wmops[i].label[0], "\0" ); + wmops[i].call_number = 0; + wmops[i].update_cnt = 0; + for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ ) + { + wmops[i].call_tree[j] = -1; + } + wmops[i].start_selfcnt = 0.0; + wmops[i].current_selfcnt = 0.0; + wmops[i].max_selfcnt = 0.0; + wmops[i].min_selfcnt = DOUBLE_MAX; + wmops[i].tot_selfcnt = 0.0; + wmops[i].start_cnt = 0.0; + wmops[i].current_cnt = 0.0; + wmops[i].max_cnt = 0.0; + wmops[i].min_cnt = DOUBLE_MAX; + wmops[i].tot_cnt = 0.0; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[i].wc_cnt = 0.0; + wmops[i].wc_selfcnt = 0.0; + wmops[i].current_call_number = 0; + wmops[i].wc_call_number = -1; +#endif + } + + /* allocate the list of wmops callers to track the sequence of function calls */ + wmops_caller_stack_index = 0; + max_wmops_caller_stack_index = MAX_NUM_RECORDS; + if ( wmops_caller_stack == NULL ) + { + wmops_caller_stack = malloc( max_wmops_caller_stack_index * sizeof( int ) ); + } + + if ( wmops_caller_stack == NULL ) + { + fprintf( stderr, "Error: Unable to Allocate List of WMOPS Callers!" ); + exit( -1 ); + } + + for ( i = 0; i < max_wmops_caller_stack_index; i++ ) + { + wmops_caller_stack[i] = -1; + } + + return; +} + + +void push_wmops( const char *label ) +{ + int new_flag; + int i, j; + + /* Check, if this is a new function label */ + new_flag = 1; + for ( i = 0; i < num_wmops_records; i++ ) + { + if ( strcmp( wmops[i].label, label ) == 0 ) + { + new_flag = 0; + break; + } + } + + /* Create a new record in the list */ + if ( new_flag ) + { + if ( num_wmops_records >= max_num_wmops_records ) + { + /* There is no room for a new wmops record -> reallocate the list */ + max_num_wmops_records += MAX_NUM_RECORDS_REALLOC_STEP; + wmops = realloc( wmops, max_num_wmops_records * sizeof( wmops_record ) ); + } + + strcpy( wmops[i].label, label ); + num_wmops_records++; + } + + /* Push the current context info to the new record */ + if ( current_record >= 0 ) + { + if ( wmops_caller_stack_index >= max_wmops_caller_stack_index ) + { + /* There is no room for a new record -> reallocate the list */ + max_wmops_caller_stack_index += MAX_NUM_RECORDS_REALLOC_STEP; + wmops_caller_stack = realloc( wmops_caller_stack, max_wmops_caller_stack_index * sizeof( int ) ); + } + wmops_caller_stack[wmops_caller_stack_index++] = current_record; + + /* accumulate op counts */ + wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; + + /* update call tree */ + for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ ) + { + if ( wmops[i].call_tree[j] == current_record ) + { + break; + } + else if ( wmops[i].call_tree[j] == -1 ) + { + wmops[i].call_tree[j] = current_record; + break; + } + } + } + + /* update the current context info */ + current_record = i; + wmops[current_record].start_selfcnt = ops_cnt; + wmops[current_record].start_cnt = ops_cnt; + wmops[current_record].call_number++; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[current_record].current_call_number++; +#endif + + return; +} + + +void pop_wmops( void ) +{ + + /* Check for underflow */ + if ( current_record < 0 ) + { + fprintf( stdout, "\r pop_wmops(): stack underflow, too many calls to pop_wmops()\n" ); + exit( -1 ); + } + + /* update count of current record */ + wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; + wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt; + + /* Get back previous context from stack */ + if ( wmops_caller_stack_index > 0 ) + { + current_record = wmops_caller_stack[--wmops_caller_stack_index]; + wmops[current_record].start_selfcnt = ops_cnt; + } + else + { + current_record = -1; + } + + return; +} + + +void update_wmops( void ) +{ + int i; + double current_cnt; +#ifdef WMOPS_PER_FRAME + static FILE *fid = NULL; + const char filename[] = "wmops_analysis"; + float tmpF; +#endif + + if ( wmops_caller_stack_index != 0 ) + { + fprintf( stdout, "update_wmops(): WMOPS caller stack corrupted - check that all push_wmops() are matched with pop_wmops()!\n" ); + exit( -1 ); + } + +#ifdef WMOPS_PER_FRAME + /* Check, if the output file has already been opened */ + if ( fid == NULL ) + { + fid = fopen( filename, "wb" ); + + if ( fid == NULL ) + { + fprintf( stderr, "\nCannot open %s!\n\n", filename ); + exit( -1 ); + } + } + + /* Write current complexity to the external file */ + tmpF = (float) ( FAC * wmops[0].current_cnt ); + fwrite( &tmpF, sizeof( float ), 1, fid ); +#endif + +#ifdef WMOPS_WC_FRAME_ANALYSIS + if ( ops_cnt - start_cnt > max_cnt ) + { + for ( i = 0; i < num_wmops_records; i++ ) + { + wmops[i].wc_cnt = wmops[i].current_cnt; + wmops[i].wc_selfcnt = wmops[i].current_selfcnt; + wmops[i].wc_call_number = wmops[i].current_call_number; + } + } +#endif + + for ( i = 0; i < num_wmops_records; i++ ) + { + wmops[i].tot_selfcnt += wmops[i].current_selfcnt; + wmops[i].tot_cnt += wmops[i].current_cnt; + + if ( wmops[i].current_selfcnt > 0 ) + { + if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt ) + { + wmops[i].max_selfcnt = wmops[i].current_selfcnt; + } + + if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt ) + { + wmops[i].min_selfcnt = wmops[i].current_selfcnt; + } + } + + wmops[i].current_selfcnt = 0; + + if ( wmops[i].current_cnt > 0 ) + { + if ( wmops[i].current_cnt > wmops[i].max_cnt ) + { + wmops[i].max_cnt = wmops[i].current_cnt; + } + + if ( wmops[i].current_cnt < wmops[i].min_cnt ) + { + wmops[i].min_cnt = wmops[i].current_cnt; + } + + wmops[i].update_cnt++; + } + + wmops[i].current_cnt = 0; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[i].current_call_number = 0; +#endif + } + + current_cnt = ops_cnt - start_cnt; + if ( current_cnt > max_cnt ) + { + max_cnt = current_cnt; + + for ( i = 0; i < NUM_INST; i++ ) + { + inst_cnt_wc[i] = inst_cnt[i]; + } + + fnum_cnt_wc = update_cnt + 1; + } + + if ( current_cnt < min_cnt ) + { + min_cnt = current_cnt; + } + + for ( i = 0; i < NUM_INST; i++ ) + { + inst_cnt[i] = 0.0; + } + + start_cnt = ops_cnt; + + /* increment frame counter */ + update_cnt++; + + return; +} + + +void print_wmops( void ) +{ + int i, label_len, max_label_len; + + char *sfmts = "%*s %8s %8s %7s %7s\n"; + char *dfmts = "%*s %8.2f %8.3f %7.3f %7.3f\n"; + char *sfmt = "%*s %8s %8s %7s %7s %7s %7s %7s\n"; + char *dfmt = "%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n"; + +#ifdef WMOPS_WC_FRAME_ANALYSIS + int j; + char *sfmtt = "%20s %4s %15s\n"; + char *dfmtt = "%20s %4d "; +#endif + + /* calculate maximum label length for compact prinout */ + max_label_len = 0; + for ( i = 0; i < num_wmops_records; i++ ) + { + label_len = strlen( wmops[i].label ); + if ( label_len > max_label_len ) + { + max_label_len = label_len; + } + } + max_label_len += 4; + + fprintf( stdout, "\n\n --- Complexity analysis [WMOPS] --- \n\n" ); + + fprintf( stdout, "%*s %33s %23s\n", max_label_len, "", "|------ SELF ------|", "|--- CUMULATIVE ---|" ); + fprintf( stdout, sfmt, max_label_len, " routine", " calls", " min ", " max ", " avg ", " min ", " max ", " avg " ); + fprintf( stdout, sfmt, max_label_len, "---------------", "------", "------", "------", "------", "------", "------", "------" ); + + for ( i = 0; i < num_wmops_records; i++ ) + { + fprintf( stdout, dfmt, max_label_len, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt, + wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt, + FAC * wmops[i].max_selfcnt, + wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt, + wmops[i].min_cnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_cnt, + FAC * wmops[i].max_cnt, + wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt ); + } + + fprintf( stdout, sfmts, max_label_len, "---------------", "------", "------", "------", "------" ); + fprintf( stdout, dfmts, max_label_len, "total", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt ); + fprintf( stdout, "\n" ); + +#ifdef WMOPS_WC_FRAME_ANALYSIS + fprintf( stdout, "\nComplexity analysis for the worst-case frame %ld:\n\n", fnum_cnt_wc ); + fprintf( stdout, "%*s %8s %10s %12s\n", max_label_len, " routine", " calls", " SELF", " CUMULATIVE" ); + fprintf( stdout, "%*s %8s %10s %10s\n", max_label_len, "---------------", "------", "------", "----------" ); + + for ( i = 0; i < num_wmops_records; i++ ) + { + if ( wmops[i].wc_call_number > 0 ) + { + fprintf( stdout, "%*s %8d %10.3f %12.3f\n", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt ); + } + } + + fprintf( stdout, "\nCall tree for the worst-case frame %ld:\n\n", fnum_cnt_wc ); + fprintf( stdout, sfmtt, " function", "num", "called by " ); + fprintf( stdout, sfmtt, "---------------", "---", "--------------" ); + + for ( i = 0; i < num_wmops_records; i++ ) + { + if ( wmops[i].wc_call_number > 0 ) + { + fprintf( stdout, dfmtt, wmops[i].label, i ); + for ( j = 0; wmops[i].call_tree[j] != -1 && j < MAX_CALL_TREE_DEPTH; j++ ) + { + if ( j != 0 ) + { + fprintf( stdout, ", " ); + } + fprintf( stdout, "%d", wmops[i].call_tree[j] ); + } + fprintf( stdout, "\n" ); + } + } + + fprintf( stdout, "\n\n" ); + + fprintf( stdout, "\nInstruction type analysis for the worst-case frame %ld:\n\n", fnum_cnt_wc ); + for ( i = 0; i < NUM_INST; i++ ) + { + switch ( (enum instructions) i ) + { + case _ADD: + fprintf( stdout, "\tAdds: %12.1f\n", inst_cnt_wc[i] ); + break; + case _ABS: + fprintf( stdout, "\tAbsolutes: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MULT: + fprintf( stdout, "\tMultiplies: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MAC: + fprintf( stdout, "\tMACs: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MOVE: + fprintf( stdout, "\tMoves: %12.1f\n", inst_cnt_wc[i] ); + break; + case _STORE: + fprintf( stdout, "\tStores: %12.1f\n", inst_cnt_wc[i] ); + break; + case _LOGIC: + fprintf( stdout, "\tLogicals: %12.1f\n", inst_cnt_wc[i] ); + break; + case _SHIFT: + fprintf( stdout, "\tShifts: %12.1f\n", inst_cnt_wc[i] ); + break; + case _BRANCH: + fprintf( stdout, "\tBranches: %12.1f\n", inst_cnt_wc[i] ); + break; + case _DIV: + fprintf( stdout, "\tDivisions: %12.1f\n", inst_cnt_wc[i] ); + break; + case _SQRT: + fprintf( stdout, "\tSquare Root: %12.1f\n", inst_cnt_wc[i] ); + break; + case _TRANS: + fprintf( stdout, "\tTrans: %12.1f\n", inst_cnt_wc[i] ); + break; + case _FUNC: + fprintf( stdout, "\tFunc Call: %12.1f\n", inst_cnt_wc[i] ); + break; + case _LOOP: + fprintf( stdout, "\tLoop Init: %12.1f\n", inst_cnt_wc[i] ); + break; + case _INDIRECT: + fprintf( stdout, "\tIndirect Addr: %12.1f\n", inst_cnt_wc[i] ); + break; + case _PTR_INIT: + fprintf( stdout, "\tPointer Init: %12.1f\n", inst_cnt_wc[i] ); + break; + case _TEST: + fprintf( stdout, "\tExtra condit.: %12.1f\n", inst_cnt_wc[i] ); + break; + case _POWER: + fprintf( stdout, "\tExponential: %12.1f\n", inst_cnt_wc[i] ); + break; + case _LOG: + fprintf( stdout, "\tLogarithm: %12.1f\n", inst_cnt_wc[i] ); + break; + case _MISC: + fprintf( stdout, "\tAll other op.: %12.1f\n", inst_cnt_wc[i] ); + break; + default: + fprintf( stdout, "\tERROR: Invalid instruction type: %d\n\n", i ); + } + } +#endif + + return; +} + + +/*-------------------------------------------------------------------* + * Memory counting tool measuring RAM usage (stack and heap) + * + * Maximum RAM is measured by monitoring the total allocated memory (stack and heap) in each frame. + * + * Maximum stack is measured by monitoring the difference between the 'top' and 'bottom' of the stack. The 'bottom' of the stack is updated in each function + * with a macro 'func_start_' which is inserted automatically to all functions during the instrumentation process. + * + * Maximum heap is measured by summing the sizes of all memory blocks allocated by malloc() or calloc() and deallocated by free(). The maximum heap size is + * updated each time when the macros malloc_() or calloc_() is invoked. The macros 'malloc_ and calloc_' are inserted automatically during the instrumentation process. + * As part of heap measurements, intra-frame heap and inter-frame heap are measured separately. Intra-frame heap refers to heap memory which is allocated and deallocated + * within a single frame. Inter-frame heap, on the contrary, refers to heap memory which is reserved for more than one frame. + * + * In order to run the memory counting tool the function reset_mem(cnt_size) must be called at the beginning of the encoding/decoding process. + * The unit in which memory consumption is reported is set via the parameter 'cnt_size'. It can be set to 0 (bytes), 1 (32b words) or 2 (64b words). + * At the end of the encoding/decoding process, 'print_mem()' function may be called to print basic information about memory consumption. If the macro 'MEM_COUNT_DETAILS' + * is activated, detailed information is printed + * + * The macro 'WMOPS' needs to be activated to enable memory counting. To avoid the instrumentation of malloc()/calloc()/free() calls, use + * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free(). + *--------------------------------------------------------------------*/ + +/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using + a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */ +#ifdef MEM_ALIGN_64BITS +#define BLOCK_ROUNDING 8 /* Align on 64 Bits */ +#else +#define BLOCK_ROUNDING 4 /* Align on 32 Bits */ +#endif + +#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) ) +#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) ) + +#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */ +#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */ +#define OOB_START 0x1 /* Flag indicating out-of-bounds access before memory block */ +#define OOB_END 0x2 /* Flag indicating out-of-bounds access after memory block */ + +#ifdef MEM_COUNT_DETAILS +const char *csv_filename = "mem_analysis.csv"; +static FILE *fid_csv_filename = NULL; +#endif + +typedef struct +{ + char function_name[MAX_FUNCTION_NAME_LENGTH + 1]; + int16_t *stack_ptr; +} caller_info; + +static caller_info *stack_callers[2] = {NULL, NULL}; + +static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */ +static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */ +static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */ +static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */ +static int current_calls = 0, max_num_calls = MAX_NUM_RECORDS; +static char location_max_stack[256] = "undefined"; + +/* Heap-related variables */ +typedef struct +{ + char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */ + char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */ + unsigned long hash; + int lineno; + void *block_ptr; + int block_size; + unsigned long total_block_size; /* Cumulative sum of the allocated size in the session */ + unsigned long total_used_size; /* Cumulative sum of the used size in the session */ + int wc_heap_size_intra_frame; /* Worst-Case Intra-Frame Heap Size */ + int wc_heap_size_inter_frame; /* Worst-Case Inter-Frame Heap Size */ + int frame_allocated; /* Frame number in which the Memory Block has been allocated (-1 if not allocated at the moment) */ + int OOB_Flag; + int noccurances; /* Number of times that the memory block has been allocated in a frame */ +} allocator_record; + +allocator_record *allocation_list = NULL; + +static int Num_Records, Max_Num_Records; +static size_t Stat_Cnt_Size = USE_BYTES; +static const char *Count_Unit[] = { "bytes", "words", "words" }; + +static int32_t wc_ram_size, wc_ram_frame; +static int32_t current_heap_size; +static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap; +static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap; +static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap; + +/* Local Functions */ +static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str ); +allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record ); +static void *mem_alloc_block( size_t size, const char *size_str ); + +/*-------------------------------------------------------------------* + * reset_mem() + * + * Initialize/reset memory counting tool (stack and heap) + *--------------------------------------------------------------------*/ + +void reset_mem( Counting_Size cnt_size ) +{ + int16_t something; + size_t tmp_size; + + /* initialize list of stack records */ + if ( stack_callers[0] == NULL ) + { + stack_callers[0] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) ); + stack_callers[1] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) ); + } + + if ( stack_callers[0] == NULL || stack_callers[1] == NULL ) + { + fprintf( stderr, "Error: Unable to Allocate List of Stack Records!" ); + exit( -1 ); + } + + current_calls = 0; + max_num_calls = MAX_NUM_RECORDS; + + /* initialize stack pointers */ + ptr_base_stack = &something; + ptr_max_stack = ptr_base_stack; + ptr_current_stack = ptr_base_stack; + + /* initialize the unit of memory block size */ + Stat_Cnt_Size = cnt_size; + + /* Check, if sizeof(int32_t) is 4 bytes */ + tmp_size = sizeof( int32_t ); + if ( tmp_size != 4 ) + { + fprintf( stderr, "Error: Expecting 'int32_t' to be a 32 Bits Integer!" ); + exit( -1 ); + } + + /* create allocation list for malloc() memory blocks */ + if ( allocation_list == NULL ) + { + allocation_list = malloc( MAX_NUM_RECORDS * sizeof( allocator_record ) ); + } + + if ( allocation_list == NULL ) + { + fprintf( stderr, "Error: Unable to Create List of Memory Blocks!" ); + exit( -1 ); + } + + Num_Records = 0; + Max_Num_Records = MAX_NUM_RECORDS; + + wc_ram_size = 0; + wc_ram_frame = -1; + current_heap_size = 0; + + /* heap allocation tree */ + heap_allocation_call_tree_max_size = MAX_NUM_RECORDS; + if ( heap_allocation_call_tree == NULL ) + { + heap_allocation_call_tree = (int *) malloc( heap_allocation_call_tree_max_size * sizeof( int ) ); + memset( heap_allocation_call_tree, -1, heap_allocation_call_tree_max_size * sizeof( int ) ); + } + heap_allocation_call_tree_size = 0; + + /* wc intra-frame heap */ + max_items_wc_intra_frame_heap = MAX_NUM_RECORDS; + if ( list_wc_intra_frame_heap == NULL ) + { + list_wc_intra_frame_heap = (int *) malloc( max_items_wc_intra_frame_heap * sizeof( int ) ); + memset( list_wc_intra_frame_heap, -1, max_items_wc_intra_frame_heap * sizeof( int ) ); + } + n_items_wc_intra_frame_heap = 0; + size_wc_intra_frame_heap = 0; + location_wc_intra_frame_heap = -1; + + /* current inter-frame heap */ + max_items_current_inter_frame_heap = MAX_NUM_RECORDS; + if ( list_current_inter_frame_heap == NULL ) + { + list_current_inter_frame_heap = (int *) malloc( max_items_current_inter_frame_heap * sizeof( int ) ); + memset( list_current_inter_frame_heap, -1, max_items_current_inter_frame_heap * sizeof( int ) ); + } + n_items_current_inter_frame_heap = 0; + size_current_inter_frame_heap = 0; + + /* wc inter-frame heap */ + max_items_wc_inter_frame_heap = MAX_NUM_RECORDS; + if ( list_wc_inter_frame_heap == NULL ) + { + list_wc_inter_frame_heap = (int *) malloc( max_items_wc_inter_frame_heap * sizeof( int ) ); + memset( list_wc_inter_frame_heap, -1, max_items_wc_inter_frame_heap * sizeof( int ) ); + } + n_items_wc_inter_frame_heap = 0; + size_wc_inter_frame_heap = 0; + location_wc_inter_frame_heap = -1; + +#ifdef MEM_COUNT_DETAILS + /* Check, if the .csv file has already been opened */ + if ( fid_csv_filename == NULL ) + { + fid_csv_filename = fopen( csv_filename, "wb" ); + + if ( fid_csv_filename == NULL ) + { + fprintf( stderr, "\nCannot open %s!\n\n", csv_filename ); + exit( -1 ); + } + } + else + { + /* reset file */ + rewind( fid_csv_filename ); + } +#endif + + return; +} + +/*-------------------------------------------------------------------* + * reset_stack() + * + * Reset stack pointer + *--------------------------------------------------------------------*/ + +void reset_stack( void ) +{ + int16_t something; + + /* initialize/reset stack pointers */ + ptr_base_stack = &something; + ptr_max_stack = ptr_base_stack; + ptr_current_stack = ptr_base_stack; + + return; +} + +/*-------------------------------------------------------------------* + * push_stack() + * + * Check the current stack pointer and update the maximum stack pointer, if new maximum found. + *--------------------------------------------------------------------*/ + +int push_stack( const char *filename, const char *fctname ) +{ + int16_t something; + int32_t current_stack_size; + + ptr_current_stack = &something; + + (void) *filename; /* to avoid compilation warning */ + + if ( current_calls >= max_num_calls ) + { + /* There is no room for a new record -> reallocate the list */ + max_num_calls += MAX_NUM_RECORDS_REALLOC_STEP; + stack_callers[0] = realloc( stack_callers[0], max_num_calls * sizeof( caller_info ) ); + stack_callers[1] = realloc( stack_callers[1], max_num_calls * sizeof( caller_info ) ); + } + + /* Valid Function Name? */ + if ( fctname[0] == 0 ) + { /* No */ + fprintf( stderr, "Invalid function name for call stack info." ); + exit( -1 ); + } + + /* Save the Name of the Calling Function in the Table */ + strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FUNCTION_NAME_LENGTH ); + stack_callers[0][current_calls].function_name[MAX_FUNCTION_NAME_LENGTH] = 0; /* Nul Terminate */ + + /* Save the Stack Pointer */ + stack_callers[0][current_calls].stack_ptr = ptr_current_stack; + + /* Increase the Number of Calls in the List */ + current_calls++; + + /* Is this the First Time or the Worst Case? */ + if ( ptr_current_stack < ptr_max_stack || ptr_max_stack == NULL ) + { /* Yes */ + /* Save Info about it */ + ptr_max_stack = ptr_current_stack; + + /* save the worst-case frame number */ + /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */ + wc_stack_frame = update_cnt; + strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 ); + location_max_stack[sizeof( location_max_stack ) - 1] = '\0'; + + /* Save Call Tree */ + memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls ); + + /* Terminate the List with 0 (for printing purposes) */ + if ( current_calls < max_num_calls ) + { + stack_callers[1][current_calls].function_name[0] = 0; + } + } + + /* Check, if This is the New Worst-Case RAM (stack + heap) */ + current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); + + if ( current_stack_size < 0 ) + { + /* prevent negative stack size */ + current_stack_size = 0; + } + + if ( current_stack_size + current_heap_size > wc_ram_size ) + { + wc_ram_size = current_stack_size + current_heap_size; + wc_ram_frame = update_cnt; + } + + return 0 /* for Now */; +} + +/*-------------------------------------------------------------------* + * pop_stack() + * + * Remove stack caller entry from the list + *--------------------------------------------------------------------*/ + +int pop_stack( const char *filename, const char *fctname ) +{ + caller_info *caller_info_ptr; + + (void) *filename; /* to avoid compilation warning */ + + /* Decrease the Number of Records */ + current_calls--; + + /* Get Pointer to Caller Information */ + caller_info_ptr = &stack_callers[0][current_calls]; + + /* Check, if the Function Names Match */ + if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 ) + { + fprintf( stderr, "Invalid usage of pop_stack()" ); + exit( -1 ); + } + + /* Erase Entry */ + caller_info_ptr->function_name[0] = 0; + + /* Retrieve previous stack pointer */ + if ( current_calls == 0 ) + { + ptr_current_stack = ptr_base_stack; + } + else + { + ptr_current_stack = stack_callers[0][current_calls - 1].stack_ptr; + } + + return 0 /* for Now */; +} + +#ifdef MEM_COUNT_DETAILS +/*-------------------------------------------------------------------* + * print_stack_call_tree() + * + * Print detailed information about worst-case stack usage + *--------------------------------------------------------------------*/ + +static void print_stack_call_tree( void ) +{ + caller_info *caller_info_ptr; + int call_level; + char fctname[MAX_FUNCTION_NAME_LENGTH + 1]; + + fprintf( stdout, "\nList of functions when maximum stack size is reached:\n\n" ); + + caller_info_ptr = &stack_callers[1][0]; + for ( call_level = 0; call_level < max_num_calls; call_level++ ) + { + /* Done? */ + if ( caller_info_ptr->function_name[0] == 0 ) + { + break; + } + + /* Print Name */ + strncpy( fctname, caller_info_ptr->function_name, MAX_FUNCTION_NAME_LENGTH ); + strcat( fctname, "()" ); + fprintf( stdout, "%-42s", fctname ); + + /* Print Stack Usage (Based on Difference) */ + if ( call_level != 0 ) + { + fprintf( stdout, "%lu %s\n", ( ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); + } + else + { + fprintf( stdout, "%lu %s\n", ( ( ptr_base_stack - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); + } + + /* Advance */ + caller_info_ptr++; + } + + fprintf( stdout, "\n" ); + + return; +} +#endif + + +/*-------------------------------------------------------------------* + * mem_alloc() + * + * Creates new record, stores auxiliary information about which function allocated the memory, line number, parameters, etc. + * Finally, it allocates physical memory using malloc() + * The function also updates worst-case heap size and worst-case RAM size + *--------------------------------------------------------------------*/ + +void *mem_alloc( + const char *func_name, + int func_lineno, + size_t size, + char *size_str /* the first char indicates m-alloc or c-alloc */ ) +{ + int index_record; + int32_t current_stack_size; + unsigned long hash; + allocator_record *ptr_record; + + if ( size == 0 ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Size of Zero not Supported" ); + exit( -1 ); + } + + /* Search for an existing record (that has been de-allocated before) */ + index_record = 0; + while ( ( ptr_record = get_mem_record( &hash, func_name, func_lineno, size_str, &index_record ) ) != NULL ) + { + if ( ptr_record->frame_allocated == -1 ) + { + break; + } + else + { + index_record++; + } + } + + /* Create new record */ + if ( ptr_record == NULL ) + { + if ( Num_Records >= Max_Num_Records ) + { + /* There is no room for a new record -> reallocate memory */ + Max_Num_Records += MAX_NUM_RECORDS_REALLOC_STEP; + allocation_list = realloc( allocation_list, Max_Num_Records * sizeof( allocator_record ) ); + } + + ptr_record = &( allocation_list[Num_Records] ); + + /* Initialize new record */ + ptr_record->hash = hash; + ptr_record->noccurances = 0; + ptr_record->total_block_size = 0; + ptr_record->total_used_size = 0; + ptr_record->frame_allocated = -1; + ptr_record->OOB_Flag = 0; + ptr_record->wc_heap_size_intra_frame = -1; + ptr_record->wc_heap_size_inter_frame = -1; + + index_record = Num_Records; + Num_Records++; + } + + /* Allocate memory block for the new record, add signature before the beginning and after the memory block and fill it with magic value */ + ptr_record->block_ptr = mem_alloc_block( size, size_str ); + + if ( ptr_record->block_ptr == NULL ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Cannot Allocate Memory!" ); + exit( -1 ); + } + + /* Save all auxiliary information about the memory block */ + strncpy( ptr_record->name, func_name, MAX_FUNCTION_NAME_LENGTH ); + ptr_record->name[MAX_FUNCTION_NAME_LENGTH] = '\0'; + strncpy( ptr_record->params, size_str, MAX_PARAMS_LENGTH ); /* Note: The size string starts with either 'm' or 'c' to indicate 'm'alloc or 'c'alloc */ + ptr_record->params[MAX_PARAMS_LENGTH] = '\0'; + ptr_record->lineno = func_lineno; + ptr_record->block_size = size; + ptr_record->total_block_size += size; + +#ifdef MEM_COUNT_DETAILS + /* Export heap memory allocation record to the .csv file */ + fprintf( fid_csv_filename, "A,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); +#endif + + if ( ptr_record->frame_allocated != -1 ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Attempt to Allocate the Same Memory Block with Freeing it First!" ); + exit( -1 ); + } + + ptr_record->frame_allocated = update_cnt; /* Store the current frame number -> later it will be used to determine the total duration */ + + /* Update Heap Size in the current frame */ + current_heap_size += ptr_record->block_size; + + /* Check, if this is the new Worst-Case RAM (stack + heap) */ + current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); + if ( current_stack_size + current_heap_size > wc_ram_size ) + { + wc_ram_size = current_stack_size + current_heap_size; + wc_ram_frame = update_cnt; + } + + /* Add new entry to the heap allocation call tree */ + if ( heap_allocation_call_tree == NULL ) + { + fprintf( stderr, "Error: Heap allocation call tree not created!" ); + exit( -1 ); + } + + /* check, if the maximum size of the call tree has been reached -> resize if so */ + if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size ) + { + heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP; + heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) ); + } + + /* push new entry (positive number means push op, neagtive number means pop op; zero index must be converted to 0.01 :-) */ + heap_allocation_call_tree[heap_allocation_call_tree_size++] = index_record; + + return ptr_record->block_ptr; +} + +/*-------------------------------------------------------------------* + * mem_alloc_block() + * + * Physical allocation of memory using malloc(). Appends 'signature' before and after the block, + * pre-fills memory block with magic value + *--------------------------------------------------------------------*/ + +static void *mem_alloc_block( size_t size, const char *size_str ) +{ + size_t rounded_size; + void *block_ptr; + char *tmp_ptr; + size_t n, f; + int32_t fill_value; + int32_t *ptr32; + int32_t mask, temp; + + /* Round Up Block Size */ + rounded_size = ROUND_BLOCK_SIZE( size ); + + /* Allocate memory using the standard malloc() by adding room for Signature Values */ + block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 ); + + if ( block_ptr == NULL ) + { + return NULL; + } + + /* Add Signature Before the Start of the Block */ + ptr32 = (int32_t *) block_ptr; + n = N_32BITS_BLOCKS; + do + { + *ptr32++ = MAGIC_VALUE_OOB; + } while ( --n ); + + /* Fill Memory Block with Magic Value or 0 */ + fill_value = MAGIC_VALUE_USED; + if ( size_str[0] == 'c' ) + { + fill_value = 0x00000000; + } + n = size / sizeof( int32_t ); + while ( n-- ) + { + *ptr32++ = fill_value; + } + + /* Fill the Reminder of the Memory Block - After Rounding */ + n = rounded_size - size; + f = n % sizeof( int32_t ); + if ( f != 0 ) + { + /* when filling with '0' need to adapt the magic value */ + /* shift by [1->24, 2->16, 3->8] */ + mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */ + temp = MAGIC_VALUE_OOB & mask; + if ( fill_value != 0x0 ) + { /* for malloc merge fill value */ + temp += ( ~mask ) & MAGIC_VALUE_USED; + } /* for calloc the code in (1) above already introduces zeros */ + *ptr32++ = temp; + } + n /= sizeof( int32_t ); + n += N_32BITS_BLOCKS; + + /* Add Signature After the End of Block */ + do + { + *ptr32++ = MAGIC_VALUE_OOB; + } while ( --n ); + + /* Adjust the Memory Block Pointer (Magic Value Before and After the Memory Block Requested) */ + tmp_ptr = (char *) block_ptr; + tmp_ptr += BLOCK_ROUNDING; + block_ptr = (void *) tmp_ptr; + + return block_ptr; +} + +/*-------------------------------------------------------------------* + * mem_set_usage() + * + * Calculates actual usage of memory block by checking the magic value that was used to pre-fill + * each memory block during its allocation + *--------------------------------------------------------------------*/ + +static int mem_set_usage( allocator_record *record_ptr ) +{ + int total_bytes_used; + + size_t n; + int32_t *ptr32; + char *ptr8; + size_t total_bytes; + int32_t fill_value; + + fill_value = MAGIC_VALUE_USED; + if ( ( record_ptr->params[0] ) == 'c' ) + { + fill_value = 0x00000000; + } + + total_bytes = record_ptr->block_size; + + /* Check 4 bytes at a time */ + ptr32 = (int32_t *) record_ptr->block_ptr; + total_bytes_used = 0; + for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- ) + { + if ( *ptr32++ != fill_value ) + { + total_bytes_used += sizeof( int32_t ); + } + } + + /* Check remaining bytes (If Applicable) 1 byte at a time */ + ptr8 = (char *) ptr32; + for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- ) + { + if ( *ptr8++ != (char) fill_value ) + { + total_bytes_used++; + } + + /* Update Value */ + fill_value >>= 8; + } + + return total_bytes_used; +} + +/*-------------------------------------------------------------------* + * mem_check_OOB() + * + * Checks, if out-of-bounds access has occured. This is done by inspecting the 'signature' value + * taht has been added before and after the memory block during its allocation + *--------------------------------------------------------------------*/ + +static unsigned int mem_check_OOB( allocator_record *record_ptr ) +{ + int32_t *ptr32; + unsigned int OOB_Flag = 0x0; + int32_t mask; + size_t i; + int f; + + ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS; + + /* Check the Signature at the Beginning of Memory Block */ + i = N_32BITS_BLOCKS; + do + { + if ( *ptr32++ ^ MAGIC_VALUE_OOB ) + { + OOB_Flag |= OOB_START; + } + } while ( --i ); + + /* Advance to End (Snap to lowest 32 Bits) */ + ptr32 += record_ptr->block_size / sizeof( int32_t ); + + /* Calculate Unused Space That has been added to get to the rounded Block Size */ + i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size; + + /* Partial Check of Signature at the End of Memory Block (for block size that has been rounded) */ + f = i % sizeof( int32_t ); + if ( f != 0 ) + { + mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); + if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask ) + { + OOB_Flag |= OOB_END; + } + } + + /* Full Check of Signature at the End of Memory Block, i.e. all 32 Bits (for the remainder after rounding) */ + i /= sizeof( int32_t ); + i += N_32BITS_BLOCKS; + do + { + if ( *ptr32++ ^ MAGIC_VALUE_OOB ) + { + OOB_Flag |= OOB_END; + } + } while ( --i ); + + return OOB_Flag; +} + +/*-------------------------------------------------------------------* + * malloc_hash() + * + * Calculate hash from function name, line number and malloc size + *--------------------------------------------------------------------*/ + +static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str ) +{ + unsigned long hash = 5381; + const char *ptr_str; + + ptr_str = func_name; + while ( ptr_str != NULL && *ptr_str != '\0' ) + { + hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */ + } + + hash = ( ( hash << 5 ) + hash ) + func_lineno; /* hash * 33 + func_lineno */ + + ptr_str = size_str; + while ( ptr_str != NULL && *ptr_str != '\0' ) + { + hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */ + } + + return hash; +} + +/*-------------------------------------------------------------------* + * get_mem_record() + * + * Search for memory record in the internal list, return NULL if not found + * Start from index_record + *--------------------------------------------------------------------*/ + +allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record ) +{ + int i; + + if ( *index_record < 0 || *index_record > Num_Records ) + { + return NULL; + } + + /* calculate hash */ + *hash = malloc_hash( func_name, func_lineno, size_str ); + + for ( i = *index_record; i < Num_Records; i++ ) + { + /* check, if memory block is not allocated at the moment and the hash matches */ + if ( allocation_list[i].block_ptr == NULL && *hash == allocation_list[i].hash ) + { + *index_record = i; + return &( allocation_list[i] ); + } + } + + /* not found */ + *index_record = -1; + return NULL; +} + + +/*-------------------------------------------------------------------* + * mem_free() + * + * This function de-allocatesd the memory block and frees the mphysical memory with free(). + * It also updates actual and average usage of the memory block. + * + * Note: The record is not removed from the list and may be reused later on in mem_alloc()! + *--------------------------------------------------------------------*/ + +void mem_free( const char *func_name, int func_lineno, void *ptr ) +{ + int i, index_record; + char *tmp_ptr; + allocator_record *ptr_record; + + /* Search for the Block Pointer in the List */ + ptr_record = NULL; + index_record = -1; + for ( i = 0; i < Num_Records; i++ ) + { + if ( ptr == allocation_list[i].block_ptr ) + { /* Yes, Found it */ + ptr_record = &( allocation_list[i] ); + index_record = i; + break; + } + } + + if ( ptr_record == NULL ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", func_name, func_lineno, "Error: Unable to Find Record Corresponding to the Allocated Memory Block!" ); + exit( -1 ); + } + + /* Update the Heap Size */ + current_heap_size -= ptr_record->block_size; + + /* Calculate the Actual Usage of the Memory Block (Look for Signature) */ + ptr_record->total_used_size += mem_set_usage( ptr_record ); + + /* Check, if Out-Of-Bounds Access has been Detected */ + ptr_record->OOB_Flag = mem_check_OOB( ptr_record ); + +#ifdef MEM_COUNT_DETAILS + /* Export heap memory de-allocation record to the .csv file */ + fprintf( fid_csv_filename, "D,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); +#endif + + /* De-Allocate Memory Block */ + tmp_ptr = (char *) ptr; + tmp_ptr -= BLOCK_ROUNDING; + ptr = (void *) tmp_ptr; + free( ptr ); + + /* Add new entry to the heap allocation call tree */ + if ( heap_allocation_call_tree == NULL ) + { + fprintf( stderr, "Error: Heap allocation call tree not created!" ); + exit( -1 ); + } + + /* check, if the maximum size of the call tree has been reached -> resize if so */ + if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size ) + { + heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP; + heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) ); + } + + heap_allocation_call_tree[heap_allocation_call_tree_size++] = -index_record; + + /* Reset memory block pointer (this is checked when updating wc intra-frame and inter-frame memory) */ + ptr_record->block_ptr = NULL; + + return; +} + + +/*-------------------------------------------------------------------* + * update_mem() + * + * This function updates the worst-case intra-frame memory and the worst-case inter-frame memory. + *--------------------------------------------------------------------*/ + +void update_mem( void ) +{ + int i, j, flag_alloc = -1, i_record; + int size_current_intra_frame_heap; + int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap; + allocator_record *ptr_record; + + /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */ + n_items_current_intra_frame_heap = 0; + size_current_intra_frame_heap = 0; + for ( i = 0; i < heap_allocation_call_tree_size; i++ ) + { + /* get the record */ + i_record = heap_allocation_call_tree[i]; + + if ( i_record > 0 ) + { + flag_alloc = 1; + } + else if ( i_record < 0 ) + { + flag_alloc = 0; + i_record = -i_record; + } + ptr_record = &( allocation_list[i_record] ); + + if ( ptr_record->frame_allocated == update_cnt && ptr_record->block_ptr == NULL ) + { + /* intra-frame heap memory */ + if ( list_current_intra_frame_heap == NULL ) + { + list_current_intra_frame_heap = (int *) malloc( heap_allocation_call_tree_size * sizeof( int ) ); + memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) ); + } + + /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ + if ( i_record == 0 ) + { + flag_alloc = 1; + for ( j = 0; j < n_items_current_intra_frame_heap; j++ ) + { + if ( list_current_intra_frame_heap[j] == i_record ) + { + flag_alloc = 0; + break; + } + } + } + + if ( flag_alloc ) + { + /* add to list */ + list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record; + size_current_intra_frame_heap += ptr_record->block_size; + + /* no need to re-size the list -> the initially allocated size should be large enough */ + } + else + { + /* remove from list */ + for ( j = 0; j < n_items_current_intra_frame_heap; j++ ) + { + if ( list_current_intra_frame_heap[j] == i_record ) + { + break; + } + } + memmove( &list_current_intra_frame_heap[j], &list_current_intra_frame_heap[j + 1], ( n_items_current_intra_frame_heap - j ) * sizeof( int ) ); + n_items_current_intra_frame_heap--; + size_current_intra_frame_heap -= ptr_record->block_size; + + /* reset block size */ + ptr_record->frame_allocated = -1; + ptr_record->block_size = 0; + } + } + else + { + /* inter-frame heap memory */ + + /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */ + if ( i_record == 0 ) + { + flag_alloc = 1; + for ( j = 0; j < n_items_current_inter_frame_heap; j++ ) + { + if ( list_current_inter_frame_heap[j] == i_record ) + { + flag_alloc = 0; + break; + } + } + } + + if ( flag_alloc ) + { + /* add to list */ + if ( n_items_current_inter_frame_heap >= max_items_current_inter_frame_heap ) + { + /* resize list, if needed */ + max_items_current_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_current_inter_frame_heap = realloc( list_current_inter_frame_heap, max_items_current_inter_frame_heap * sizeof( int ) ); + } + + list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record; + size_current_inter_frame_heap += ptr_record->block_size; + } + else + { + /* remove from list */ + for ( j = 0; j < n_items_current_inter_frame_heap; j++ ) + { + if ( list_current_inter_frame_heap[j] == i_record ) + { + break; + } + } + memmove( &list_current_inter_frame_heap[j], &list_current_inter_frame_heap[j + 1], ( n_items_current_inter_frame_heap - j ) * sizeof( int ) ); + n_items_current_inter_frame_heap--; + size_current_inter_frame_heap -= ptr_record->block_size; + + /* reset block size */ + ptr_record->frame_allocated = -1; + ptr_record->block_size = 0; + } + } + } + + /* check, if this is the new worst-case for intra-frame heap memory */ + if ( size_current_intra_frame_heap > size_wc_intra_frame_heap ) + { + if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap ) + { + /* resize the list, if needed */ + max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) ); + } + + /* copy current-frame list to worst-case list */ + memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) ); + n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap; + size_wc_intra_frame_heap = size_current_intra_frame_heap; + location_wc_intra_frame_heap = update_cnt; + + /* update the wc numbers in all individual records */ + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + i_record = list_wc_intra_frame_heap[i]; + ptr_record = &( allocation_list[i_record] ); + ptr_record->wc_heap_size_intra_frame = ptr_record->block_size; + } + } + + /* check, if this is the new worst-case for inter-frame heap memory */ + if ( size_current_inter_frame_heap > size_wc_inter_frame_heap ) + { + if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap ) + { + /* resize list, if needed */ + max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP; + list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) ); + } + + /* copy current-frame list to worst-case list */ + memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) ); + n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap; + size_wc_inter_frame_heap = size_current_inter_frame_heap; + location_wc_inter_frame_heap = update_cnt; + + /* update the wc numbers in all individual records */ + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + i_record = list_wc_inter_frame_heap[i]; + ptr_record = &( allocation_list[i_record] ); + ptr_record->wc_heap_size_inter_frame = ptr_record->block_size; + } + } + + /* reset heap allocation call tree */ + heap_allocation_call_tree_size = 0; + + /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */ + if ( list_current_intra_frame_heap ) + { + free( list_current_intra_frame_heap ); + } + + return; +} + +#ifdef MEM_COUNT_DETAILS +/*-------------------------------------------------------------------* + * subst() + * + * Substitute character in string + *--------------------------------------------------------------------*/ + +static void subst( char *s, char from, char to ) +{ + while ( *s == from ) + { + *s++ = to; + } + + return; +} + + +/*-------------------------------------------------------------------* + * mem_count_summary() + * + * Print detailed (per-item) information about heap memory usage + *--------------------------------------------------------------------*/ + +static void mem_count_summary( void ) +{ + int i, j, index, index_record; + size_t length; + char buf[300], format_str[50], name_str[MAX_FUNCTION_NAME_LENGTH + 3], parms_str[MAX_PARAMS_LENGTH + 1], type_str[10], usage_str[20], size_str[20], line_str[10]; + allocator_record *ptr_record, *ptr; + + /* Prepare format string */ + sprintf( format_str, "%%-%ds %%5s %%6s %%-%ds %%20s %%6s ", MAX_FUNCTION_NAME_LENGTH, MAX_PARAMS_LENGTH ); + + if ( n_items_wc_intra_frame_heap > 0 ) + { + /* Intra-Frame Heap Size */ + fprintf( stdout, "\nList of memory blocks when maximum intra-frame heap size is reached:\n\n" ); + + /* Find duplicate records (same hash and worst-case heap size) */ + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + index_record = list_wc_intra_frame_heap[i]; + if ( index_record == -1 ) + { + continue; + } + + ptr_record = &( allocation_list[index_record] ); + for ( j = i + 1; j < n_items_wc_intra_frame_heap; j++ ) + { + index = list_wc_intra_frame_heap[j]; + if ( index == -1 ) + { + continue; + } + ptr = &( allocation_list[index] ); + + if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_intra_frame == ptr_record->wc_heap_size_intra_frame ) + { + ptr_record->noccurances++; + list_wc_intra_frame_heap[j] = -1; + } + } + } + + /* Print Header */ + sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Maximum Size", "Usage" ); + puts( buf ); + length = strlen( buf ); + sprintf( buf, "%0*d\n", (int) length - 1, 0 ); + subst( buf, '0', '-' ); + puts( buf ); + + for ( i = 0; i < n_items_wc_intra_frame_heap; i++ ) + { + index_record = list_wc_intra_frame_heap[i]; + + if ( index_record != -1 ) + { + /* get the record */ + ptr_record = &( allocation_list[index_record] ); + + /* prepare information strings */ + strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH ); + strcat( name_str, "()" ); + name_str[MAX_FUNCTION_NAME_LENGTH] = '\0'; + strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH ); + parms_str[MAX_PARAMS_LENGTH] = '\0'; + + if ( ptr_record->params[0] == 'm' ) + { + strcpy( type_str, "malloc" ); + } + else + { + strcpy( type_str, "calloc" ); + } + + sprintf( line_str, "%d", ptr_record->lineno ); + + /* prepare average usage & memory size strings */ + sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) ); + + if ( ptr_record->noccurances > 1 ) + { + sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + else + { + sprintf( size_str, "%d %s", (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + + sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str ); + puts( buf ); + } + } + + fprintf( stdout, "\n" ); + } + + if ( n_items_wc_inter_frame_heap > 0 ) + { + /* Inter-Frame Heap Size */ + fprintf( stdout, "\nList of memory blocks when maximum inter-frame heap size is reached:\n\n" ); + + /* Find duplicate records (same hash and worst-case heap size) */ + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + index_record = list_wc_inter_frame_heap[i]; + if ( index_record == -1 ) + { + continue; + } + ptr_record = &( allocation_list[index_record] ); + ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */ + for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ ) + { + index = list_wc_inter_frame_heap[j]; + if ( index == -1 ) + { + continue; + } + ptr = &( allocation_list[index] ); + + if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_inter_frame == ptr_record->wc_heap_size_inter_frame ) + { + ptr_record->noccurances++; + list_wc_inter_frame_heap[j] = -1; + } + } + } + + /* Print Header */ + sprintf( buf, format_str, "Function Name", "Line", "Type", "Function Parameters", "Memory Size", "Usage" ); + puts( buf ); + length = strlen( buf ); + sprintf( buf, "%0*d\n", (int) length - 1, 0 ); + subst( buf, '0', '-' ); + puts( buf ); + + for ( i = 0; i < n_items_wc_inter_frame_heap; i++ ) + { + index_record = list_wc_inter_frame_heap[i]; + + if ( index_record != -1 ) + { + /* get the record */ + ptr_record = &( allocation_list[index_record] ); + + /* prepare information strings */ + strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH ); + strcat( name_str, "()" ); + name_str[MAX_FUNCTION_NAME_LENGTH] = '\0'; + strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH ); + parms_str[MAX_PARAMS_LENGTH] = '\0'; + + if ( ptr_record->params[0] == 'm' ) + { + strcpy( type_str, "malloc" ); + } + else + { + strcpy( type_str, "calloc" ); + } + + sprintf( line_str, "%d", ptr_record->lineno ); + + /* prepare average usage & memory size strings */ + sprintf( usage_str, "%d%%", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) ); + + if ( ptr_record->noccurances > 1 ) + { + sprintf( size_str, "%dx%d %s", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + else + { + sprintf( size_str, "%d %s", (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] ); + } + + sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str ); + puts( buf ); + } + } + + fprintf( stdout, "\n" ); + } + + return; +} + +#endif + +/*-------------------------------------------------------------------* + * print_mem() + * + * Print information about ROM and RAM memory usage + *--------------------------------------------------------------------*/ + +void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) +{ + int i, nElem; + + fprintf( stdout, "\n\n --- Memory usage --- \n\n" ); + + if ( Const_Data_PROM_Table != NULL ) + { + nElem = 0; + while ( strcmp( Const_Data_PROM_Table[nElem].file_spec, "" ) != 0 ) + nElem++; + + for ( i = 0; i < nElem; i++ ) + { + fprintf( stdout, "Program ROM size (%s): %d instruction words\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size ); + } + + for ( i = 0; i < nElem; i++ ) + { + if ( Const_Data_PROM_Table[i].Get_Const_Data_Size_Func == NULL ) + { + fprintf( stdout, "Error: Cannot retrieve or calculate Table ROM size of (%s)!\n", Const_Data_PROM_Table[i].file_spec ); + } + + fprintf( stdout, "Table ROM (const data) size (%s): %d %s\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].Get_Const_Data_Size_Func() >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] ); + } + } + else + { + fprintf( stdout, "Program ROM size: not available\n" ); + fprintf( stdout, "Table ROM (const data) size: not available\n" ); + } + + if ( wc_ram_size > 0 ) + { + fprintf( stdout, "Maximum RAM (stack + heap) size: %d %s in frame %d\n", wc_ram_size >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], wc_ram_frame ); + } + else + { + fprintf( stdout, "Maximum RAM (stack + heap) size: not available\n" ); + } + + /* check, if the stack is empty */ + if ( ptr_current_stack != ptr_base_stack ) + { + fprintf( stderr, "Warning: Stack is not empty.\n" ); + } + + if ( ptr_base_stack - ptr_max_stack > 0 ) + { + fprintf( stdout, "Maximum stack size: %lu %s in frame %d\n", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], + wc_stack_frame ); + } + else + { + fprintf( stdout, "Maximum stack size: not available\n" ); + } + + /* last update of intra-frame memory and inter-frame memory, if needed */ + if ( heap_allocation_call_tree_size > 0 ) + { + update_mem(); + } + + /* check, if all memory blocks have been deallocated (freed) */ + for ( i = 0; i < Num_Records; i++ ) + { + if ( allocation_list[i].block_ptr != NULL ) + { + fprintf( stderr, "Fct=%s, Ln=%i: %s!\n", allocation_list[i].name, allocation_list[i].lineno, "Error: Memory Block has not been De-Allocated with free()!" ); + exit( -1 ); + } + } + + if ( n_items_wc_intra_frame_heap > 0 ) + { + fprintf( stdout, "Maximum intra-frame heap size: %d %s in frame %d\n", size_wc_intra_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_intra_frame_heap ); + } + else + { + fprintf( stdout, "Maximum intra-frame heap size: 0\n" ); + } + + if ( n_items_wc_inter_frame_heap > 0 ) + { + fprintf( stdout, "Maximum inter-frame heap size: %d %s in frame %d\n", size_wc_inter_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_inter_frame_heap ); + } + else + { + fprintf( stdout, "Maximum inter-frame heap size: 0\n" ); + } + +#ifdef MEM_COUNT_DETAILS + /* Print detailed information about worst-case stack usage */ + if ( ptr_base_stack - ptr_max_stack > 0 ) + { + print_stack_call_tree(); + } + + /* Print detailed information about worst-case heap usage */ + mem_count_summary(); +#endif + + if ( Stat_Cnt_Size > 0 ) + { + fprintf( stdout, "\nNote: 1 word = %d bits\n", 8 << Stat_Cnt_Size ); + fprintf( stdout, "This is an optimistic estimate of memory consumption assuming that each variable type is stored with sizeof(type) bits\n" ); + } + + if ( n_items_wc_intra_frame_heap > 0 ) + { + fprintf( stdout, "Intra-frame heap memory is allocated and de-allocated in the same frame\n" ); + } + + /* De-allocate list of heap memory blocks */ + if ( allocation_list != NULL ) + { + free( allocation_list ); + } + + /* De-allocate heap allocation call tree */ + if ( heap_allocation_call_tree != NULL ) + { + free( heap_allocation_call_tree ); + } + + /* De-allocate intra-frame and inter-frame heap lists */ + if ( list_wc_intra_frame_heap != NULL ) + { + free( list_wc_intra_frame_heap ); + } + + if ( list_current_inter_frame_heap != NULL ) + { + free( list_current_inter_frame_heap ); + } + + if ( list_wc_inter_frame_heap != NULL ) + { + free( list_wc_inter_frame_heap ); + } + +#ifdef MEM_COUNT_DETAILS + if ( fid_csv_filename != NULL ) + { + fclose( fid_csv_filename ); + } +#endif + + return; +} + +#endif /* WMOPS */ + +#ifndef WMOPS +int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */ +#endif + + diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index 4d7eee8275d3d876b1acd9d25bbe7d38d98bafb8..767a02dc6dfef1c23d0bf774511f53b4cafa3891 100644 GIT binary patch literal 42697 zcmeHQYf~FZmi^AJ$i_1k*nok4#5A^h1_QPg%WIIZXQI2eLP#a3wWQMMVa#~FzkScS zSy`D`RYEB@Y^)uw4gCCqYMdS%?7ddI$NOsce7}C8_D=Te$FEeQiKN}L{l>D<@b2J7O~Dsh zn3R+qkNU}k%7)stCMH*{iOx7kClHxx!Y9buPhmGvs^l5O3G||s)0$4M(h)O`ShPx2 z(!QNI?t=zOeARj%tA48!gWwH_4@Yo}!9<%!wZ_atwU4LCq;-+>lF3b}1Z35P8cAU| zg}qtwYR@uupz}7op{Ne{&+7xIxZY65Ckom=+dXdnQ*_;Y zjYMOET&=puJL=W+2F~5SYK=N;>P@fJN&3l19kqJ#Abmf6ccWHJ;)YH9+j#@JyBMYE zyLhABT18QwEG<1qy70HIdV6$o+K65+J;0Y_5a-|X3SOY8fFtNCuZXs`jUvN(Ks%Hkc&c1Wp4{2GjmUJX%)$csy>Q#?Ybm zYHv@ZOS)7<6umk=-;1K92g6b8vfomCJ-!)F;(m06z=}tCIl%iYZuQnDNk4|+d)kw( zlHpkBWtx0>wtIBYh)xgAqQ=4A38Lr6&5cckr=aW?CnpW6cn_~u)YiskSFMUx+pQkT zq`Iy41ceZt{%eY~e>0UH3#}rm;{ihFBA#5w@jxLw(mn)gOZ4Dewu*N#_ z=LSA?CCv?dS~75nf<&z@mm?|dtFyXv#k__>?jwlc74-qNa=`PO)N&sKa=KYGiYbdA zEsDr=IF8zA3?Dy7Gm_Oh=sAnvt52CjKR$|W17W`s@w*12s80SWRH&3bFH#z_4Qiu} zn5ZGxmiRDF8I^QVknaeXZG|!_M9MOX5(uZ~YO7MbN(luuO8W&9oTAmtO;G0biLg13 zj|xGMphbluEb5c>{1=Tc&-0~ab=02g*Xo2xj_1EFu@n@`D~@{+4Y?m z4XLSSxUpaDXC25zyq}OecYmjBM(&WBzXBFg^;f`xH0oCfM$ma7P{EB*%xk!{f7Z=& zEK%kbR5kmsAPB{=uwaOV*%ko((t8dAD`=3-C?p<>;w8 z_`JwIBm&B)kN_y7LUdV1QObGlKLb_pei_aNN&`eVF6@fZVzJ7r0S~5dW`$g#MDvvEBzxttI=E58cXb}GT zI2#Lsx%*%!@S_+((NKX43Wo|@m|lIo73p0 zu{awQGTZh=Munay#M+0Qm|y|rvD)ER8x?~278P1a`QJN=3T==(7%#itO(DZQ+}b@H zLk=2eqe5nzzsRUCYaxq7g!pTWn78`4Fbp|ZTsX$!Y*gsg zmU|BiN8Yfu-e}PQGRf~m<;#JNA!Yz=d!a%15E=zhDM(m9ssb3+k*WX&YS+3?t}lF; zA08DPNubb|%9rpQyOcQwI<5~41W_mpTmWQ&Hb$`ac+UZ1MGdqc#dHeDZ+>X#HE~D( z%p#BF#jiFlfVlIZ@OhD6NJNxTA>mL)h3K-3qLlLjVFt>dXVOd7jtR=B5XbaUAqbYh zqCycCWj&wk>-X&Xj-(;>qLlL30`jZx{MpVANA((mzdp=*KOuMS{snFnBEmd5X{{NLxCT~2#SUZTu?Yv;KKCk>&2*RZa`G|=Cc(L}Qq5JMe!LiU z-^B(dk}qiZGlGCb7J^x>Hh#>G*)KSLOc5509|QXqKlF=&J4zD%++F+_b$?~?!@~pj z9Xqya3$6{z7WLbl?99U=?F}J!A1k(O#^r+AnKCS>jVZ%|G+KsH*txMW1Ln6YVu>%m zA10?M?mG~iN-D^1#-$t_ll)N7=Rg+gdkN<5gP|ZNWetjk3S3Y)RN%t&I>WPh4&#>7 z5i=VZKO)S*9H(+B^9$?v__#0(wQh0Y7>l#LD=gvPb4*xC!z@QB-SY999}kdu!JZTl zcODD2T$GScNFT%1FpB6#d;t^R91eJ$ieUuXe-wwc1jq=QMe_w|=%5MSm@A>@UQH{?l)R8SJ z6v0wxlRBi3K70y`D0d8NdCK@{jKntpf;ic7t}~p;KFJfUoR#w z?kFm>G47(FD3mX}_hZW!j-eJb&gnBPbOKhR!z^HQZn^T)Vpv;BVk_DT{<7)tBGVFu|d zINZ0t$mu?;2yj_ZctF{?7}6LSMz83o-DO9PZm+ z=ycy_27;r}g(AVh(F)~In03H!RxErw+-JPm{XaJ#3U)BqLPUH8hx?Y|54>1LbyD2r zg8NeRFLysJB%5*<)AKsl+&A!ho`XNDol%Q$ZA9`O7ZJQq6S5$sclG z@iRVttX6H_yr}vI-wS!y*PXmx@sWK6_sQVap-BOwoT(tsLWKr+R(|3_|Hm zJR0+M7JWTWb`=l+IZ=FuE3c`GHPx1I!8iPW3eI_A%E9c{Ik;DjMsv zXyjK8Nd>?ge)bOV%^hb<`jk_uZ>(csUolSC=L_JI|6I=iU6E=AT+2}@T;d%EJ?^H6k%izKy^AYaLI#fv29+_rf zI2qweq_H|5>$_HVS%2?1S0<&oQlOVw2CL!5tQ*`aBzGn8W~k1xy2dSBYVYRq8W${G zw%gEQe~25#&{jNI%4RLI2F+!Tg8~mTqP9NHHKJ`*xLadIc?9G_i*)$lfjcv`W`9*D z9omUmZS+Tf^m#(hIX*#svSWH73;%~!Kt#!9akcAyJL>jYmr+ge9}RNZOD|wxUVkG^ zYA0^@TA6!7!?@WBMmI#d(}7&5B-c9Cw6<#&3*`8Ut)fu$x$4 z0ml2VaE(wR(alSQRBaEsW|r)Jx6@JjU$~DgE2l{EN8JQOXk&XbpS~IHmA33l8X8%g z8U5T15EYx~n*n?`brNg5(0VEBX3K&BtDrUMn-mRa$2L!kuk3f7NopNa4dtPo)t-gQ zP9uajWoECa`U&DssFk6bP@ZZjvec|C^}Td3!oI%!j#oGywc4X}EP<3xC#v?bhB~6cDEsVpK5%SPI2)csz_AR?4RmBJwD%jr`y%6Uf#uJ7}6)ug5>()B|W$c4Gjvb zzb6%!s~MGYH{mP_xK}NJg6xR1BwQKzDu@L36Ilw%BZ1r7LWJOU087H7fL9?T^!jN| z!zCfFLTKpKrb-&}Dujlfo3ErHuR>^KKj3GGxMk6=LWppR)KGwbxkT_Pgn~>kSrRS< zz6v3sN8~vTmxR0up`i~0<}@6Vc?Sp9am!kr15M zLB_laAtU?kZGl$2B5|~F3z0Q1Gbyd9E!}I+swO#mW2xsgl{8F8Ep+$t*2(L2wl2nz z>upX)Sc;nge1k2h{DQ=_slMWd#=TB%1>p|7$dv z!7Gaqfiatd8m8B?RAF3NV94j7&;SLYkk3K&(#u&W9UH<4xqQslX06z7IMGOwV+f+-DFpG3HGb6~arsn&;ENFCLW!$~3YZKQVpu>h&vf80iD z5nUbKs;i?#bcM_nQo%JExYrmrX>-)a>(i_3i)t6e&n5~g?aSi^xIdXTMP@Q$Zr8Al zMQ9*%C5^wIh0B3_YvHE63EeHFEBkp#p+KivafN`8pjdmGiRx6MLB(lY>Wvj zG6XH&Wo4|1x7(4?634|=2DzO&@GfOosEH{cJBjo>pKG~&`m+~zC+nC^?qJp!v%~z~ z#p+WZSHN?c09VFyzWAy&R)bW_$Tx6Ou{Vn!oOGj}otR+cdr5)(rC=QX8) zZutyJP0^^XN^LnApJWECq6r6@qCLIE&@*UeK$j*XC7vj>8c$H&yDc~3wPIa9Qv z^kj$B1^EbBzR3x6sohbMnUc3N|gGGKSZYB|^zqoqJIt0X z^tjP1R%9zok+WD4!EnBPS#dmk=+4TOS3Xw$Ds}IUw{Yc9EfMAX;$PL~j!X7s4`Z>t z6f4DPPrZw8uG3M+Q$W(?FlOeX=Mjr$V?F5>2#j^cq?>nAyBwF|sluWvMe@ql>Z(Gv z9CCeyDQuADa+{_nDUNW};&9Q*6^9*NS+XEF z+-~ZeP8wyrJE>-@d49~LjB=s$8<+Fb4C`;KcFJOxT`$uKSj~K@OFC2Wq?Su~fuY5_ z*|ZlVE!1+_*fxQ!3e$K7`2}ekYB~8)JeiJUj672_!7paZvSQmGG#ps7Xupdlqd1Ow zSYYWzYpT)Q-TRMd|KPOwI(oU+jLr_4=V!-oOXHYYPHW9En#eXsmch?$(z!0R=E*8O zj?Bq4&s=pFAhTJ+#6e}u*=Fsp2oK%zAn%%u9QkIm>1`Z4T(-dK4OYETr|XG(TkPGv zJ++-nfL@W>lBzLZy*8DuTFKTB2Ix}GUPs85k7SKdmc$Uq&ORM1lA-SX$S#TAxzp>* z;*wE1D&<~(M;*4XvnQX;C0{YFc!D(#C@&xcn=7a+u1;=Ha(&qt8=;Gl5SV zomEv^uW5cdP5(u8%F0iEvu^V#_ecGTFTZnBPVJZ4Q@-(-xmceE-^kJxi9O_4(-Xk} zS@A%~jt|xXKCTc@EVk|E&RM}64;8(r%C2E6}d6^tY`h?1!R0yprq;l zQb?sV66&mrSYxr;Sl{}+!g-igLOvdi(otCwsm%Oj;ko{oAN|Tor~dS_pGxwxY-H9U zD`S0TX^7@<_=er7-vuS0_-uq=IkC_HIsv?w6KP^D0Q9;P8kuT;GrxldULM3`o zixK;^Kunwb_d+UFB%U*#_(ew38DvLIwq78sQ#T5!WM;hg!*ZGAP4%4_*r$_4hau%C&A zmpNPcTvq(-_I~rvzQLFcaTcLl6k)$1`hU*1a#r*kSJd)yF=Qm9ebu0Q-J15YJ|wxA zrz?A@}3JKQ|Fh(zJ*4KTds}BL=wZ!2lDiZA>a))&;|m zeJrP9(cs^)wb9BMXG+QZd}uc89mjBRWUtk+RrfN+HdbQ1y;a!8{BNv{B$F6{h)zEA zgM<`*ktIF03Fxw~YNKPbRh~^!9~Hhsz1i3TTy_I}vj+T1}{ zp-`AOZjJONuz}1NGtktI$~SIaChrl>vLSKY##D2*pY}~Mo?->GF`0If6#B4RY998U$;gBC}zc+gaA?UMaAQ|R#CB>$38tfInrv*b~!6E^7On;pb>2nQNIy0t!P14 zwZWX14<4`t=0Hb2%6)~|*a96*LUtueonZF)=`sFd=d-fGJtHeSIm01ffnns!W~QA8 zdL)~+Gclge0g6I|k4qPDBI@s3o(U13;~SMnN_WJN%~O z)}>xU7LoK1tMt&VFgtnL=}@ zsF5KV0^MGrzD8YY^<+NV*C3 zkS7yX$~M0fdg4-|M5&qSMc%v^+Lua|yHRLq{EBHAHc21(2lGD58yio0$wh>j=_mYw zHT>UbqXFMsQ^)6rho9C8`7j1}@~AooQ0rS6jHpkrAY|3eGy7Q(-OP9&9UMiwhg>iI z>4z8fW&^J|Z@#a$35#Dsp9A!!XojDDP%pS|0sW3Cm8BKmPCKz$i9hUQ$NVs@C>!&y z6Lj66(CY+&fu0K1&auGw{kEn7IeannnU?*7=5GD4K`D(t$Af7<^V{>rLGaS-1H>$sV04z@)4@M2=!u$h89(8e&$l-*6VJpYvgMWwiu+?)55lSBL8qGOO9v? zg-E)L*)dJh?PAhCoUGJNkJxFK8SPAkeN9?-r(g~|j>tyASf`E->&FKXRtG2^dg1+@ zW%Yoc9eZ$pd@3u7IveQCA*N^SdCE+a0^v3Z4-|s9%z!0E*H{WcQSn$sR0%6Ny_2!X zzv71jr-dWU-kgEWTdM_YG-{UilvAj(vQn@Q+8S+j&l%biy|DUJgK;eNbFiNOVflvj zNFD~oHJ!cP!$W8fx^zwjyP*s1|B7}h+C6Wc{EiXanpY^~tRIRyco;4bu|?^0T)L~Q zDB&8mJ))y{UDKj?*^(2)vuAW6fz`|{0*G5Ue~dtuQb`^?iqjH#XIzSMWomQnJ4=$8 zs?W+6P#9BBxhK0b&oF%rQ_V>Yf_L26Ob?W7?y?>ljH<%0E$~X5R|o^l1c?@P3L+H= zd7*5mqow7RRyiEQYHpAvt1B)Yo2CHzptnS)jmMmZ?T}RWCLo#3OOMXf#LnHC hlI1J=-g;5hYb}Vz+wwa4wIhAqrO1!6N3W%G@xRt776AYN literal 43846 zcmeHQZF3tplD^NW%6~xQ-B6Zg*-~C=tBcF?K_W5zbT_)ucn9%hM z$h+C@MW&j?WL!+rGA~A3YIiVDr}TcRPP1t?d6)IJhy!!!T;@|XE&AnEI>{71k0(W$ zb<3=$&aVaQL3*Xq5hv!OGMkK;c{)(#B*VvSx}`do892=*-3+*1w#oDQy$%CeY(#c0S0v>HroP zO|!Kvbu!4(DYSroJ!XK{^h)*fLB{fn310SzeW5h-)2v$zhuNsdYN}UT+uv=gVx-pE z$1giS?Vj$d&hha7=)*-VD-SKFlZTFdby0;@$M^wOY4{TQ2e6&)Trx z`J^b`W?S9#A?4=D=bwH4*@L`~lGj&19Uh;wlh;VVw|tbj1V^*~_f{u)x!XE8JKd+$ zQFkzdO@Ek{y+MAyb@`)uvZ3@B_GFe(i6>KJ@AGo~A&Y!~QkVCo=>6lD9=E)3%<{tH z)gMm~nf*C-pMM7FokE>VvUhN&E@quKC0o2;o} zHl3!ZN^}6eYBsf&d7rG3B(ILnnn?ov#*_47m?|QeUQf$xm|P;@GL%7=BPej1rGv+1 zKFm-Y2D*S<=HsbmYE1j`boX$-ot*5SChh&^F#_wGr&~||E$}oC_S*{2cJ?jg)I9Uz z__$5pXyWy{+TMEFR}b0#-E@FltA5%okxjP#KW9k$7o}1uhxt(%WFy4ec~)L!*+?O# ziXpV^a>xzS5dbjRw4BUPOXxtUXMyFCYW7)I^Vxc$4qFEYt>dGl`47&@hACD~d6Yz( zucNcWq;=HpSdI$SKIN!Wl+Z@|i|bg{t4o!>DzC@cRIS6i83>S{L2;$anJHo9MK0T) zf5sF#Qw*Md{@HJc13by@-X2xe{P9KGemp!o=v1F~o7KnTH~aQ;yK{V6eK|OO)vBo4 zuUjuG^b3S{^R)%-wcgl|?Z2H?L>&-SvR|GZRjdw~>E{SFnz z5h^umF4A646v=dQ!GThb^Mo8{z+VZT)`xhtBa*Evku1$Y9<>@sYI3eluPF@c8EREa zC#Rbi;4T=E<4?kl4lrF7Ej%V6> zGW%VpOKRhQ5u}pDz$j@IsDKf)7*CTf+VV%w(Z-o73L^s6{o(gSp&t)Ml|12o zCdjWEjqD0Q5EiSbCyjVbsg3NS$t=|vg6AX=O#qhnk(n!NG zQWTGX(N`}fco-%;KqUNlFxNgHr*|I_o;1=RCLjW^n0N@lVk{bfk)q3@VG+y=1|Am) zPXu5wWz>VkKqwOe77GzD83-82-FGBNZDSlqn(`xZN#DI#&~p#M1sa6E9!>-UFn1pf zzC6++CLBVzn0N@`qU`F~#oB9GM19%bQb^#UF#;#Tf+sTW zJualeQ4S z3KDIl`ro?>6783}7<$*rIw>1p-bDe32ayN^6hXq1+<(*{u}d>61qp*b1ql@g|GBFm zu`4ISFQUj=sc}Wu1IB?!gaF2a1W*KtUh=vBD3LnHbqTC3C6dzWJ+5l4QaEH0(zPZU zbsv%9YfHMsb-F^xxL#KX8EIotk}9j=!}4ee$s`V5$E#XV6z&Pgj4Z_-G7?2<3FHbW zffONw<e{6Hl92x;`)g$W>cA0wVLk{A;p0a#3Q1Yj{1 z4ZujzWpS|xR-eJr>*>N10a#2a^H zY*`U5&>;Nva4r}KbNA8U%OgEv!Xbo`OvB@qq@$crki z9xe()3JF{^M&LwP@CKNBj|-`Almkgwend{`dp$DjrY+$Kjly3K=t6@*_YfPtMA9TG zI6}av=m-Jhtm_%a8f|HOgd`H!3lO`jO86xpF|Oo#z&H@;B!KZC0Te+(`}poXMufg` zP9$CN2poN_M~K;hC>%jF{CGGQAcVPx`0(VB4pHF|z(qwz02gJ~0FHEB8XJpn_3jiq z)~UKekYr*h`(>=+k^zMSqUfPig2aD7uy;-wGUkt+z<##K%gl5n=8jbUZyt z*Qiz~fQxE@0=Ou<25_Y7(w1ituHNdfLq3vD8=oM#_qdP+Jj#LOEq*+Y)FVS5e_64k z#-MwM4Vg!)eN=FSfKkyA0>)X_v#M2hX?%nv64)E?+ha+h$_hw~>mzxWPLqp_^l%yvnFaofcun53nEE<53qRT>J z5v<-~kSFew z7=c4rxRZl)LO41wh>3oT3Q_K`nEHQ_iCc0J9Ef#2Y|MH0M=CkI#m0F;|N7|B_jQ#6 z-#i^e2;RK)-m&sH+`<+f2Vxx+mJ4;D7f}IvBZn1p637LyUmCPG>cAZ8Et)wJZwtm< zG;U4>8Jd*3Qg~`M!Vb4U6A#0o7Up{^9F;ft75!($k_M|lMScldi{c&3WG^@^@4;N) zeL5*mW)#n|2=XjxkzT6@vwjpE!M#;Z2;VXiZW{^`M{bypg$0L%Jr}xQ_;f(n7H9c? zSw#4Luvjl7KBfc0dn=p}zGYO1LVBm|1N~&r{7jmVM(z_K@#%oDEzkP@vS{!uX~BLl zd?W{i_h`5fJ0QAcB*^+@l~9m4azmhf2#<9<7m8rGd6eSeqILCfq-)fOB!G(=hXim@ zx(0Bh>#~UO{XiIc{E#4L+{yUD(=&QpAaKzb%80><`Ln&1P6!)(ln+Q=^$3Mm0}CKA zn~#h|hlD+#3yn_)gsXB;xyO818XvX*%>nB}@sI6*@E&H%ThX&={||$N^js1_syjA}wcz_=>Nt3hm;zpEh8KDm=-#Lr`Vn;`NS4fn=DCrSdrLTdOg!Eq}NIo49p0g@hmY%x`l8^0x@ZJi?9Zi8?Sx9)6v^a0<@v)qC+*{?i<1HgWR{5)hg2a&<0!@Yfk#4b6%5G0wl{hF>PYC9 z(G9}{H-^)(Sl2bo>#*aKF3G^HP^jVli6mhffToZ;O{jvxz}UQF9b%4(WIB+eV!bx;MF zG&Pc|o1zeM!?dfuRKw{^tsmjupH_7@5yI|GHkslwpsBfF%G_uLgky~_DDs=?d{cEf zu<#B4A0ZIV@t=B{lujkwNVOMZ)!9sEAvTW}vjIbS!xmpswYT5iZFX93c02ogAyd;< zB!?NQw^2SF*6v!OJ7kW}jylOYYS2wJA}#0m9FK839AAmV+;GR$Pm^?v#QK#q6|bL8 zcTaEu)wW^!4mT`OeZ&8q*?jUHkZ1456Ins{G+!B(nvTf>`W_S)Ic}8 z9MH{fbTgT)68Y{edq)u$aH@n2!^VbfQpV*3cYICN*;HT8vrFy3GjRu4QP~Hjr(s|X z6sv1o8pW4?(XD5_HFbrX=2Y|g;tF?4U39y+VsJRdMS5s-pp}_RH4UVcuAZwe4Oda2 zSGLiv^R8T3S2YfN$w@JO@IX$IZMr4+V(ey&Z5i13y$>>l=sG$^?eom`Z&v7(-zTJy1Vr*!e zHyjwy=_R$h?5ct<1{@Z>*#I|zDaVB`4zzdF@oj|q!ZyAaacfB)D_xe*-Tb=Z(xGeD zT%P$pKxrq==oOV8zNt=XD{@2^I%2U@UvEb@x#1G3oMRr>3#O{kgu#i#+-7((DgFzW z51OoMU4CzIAujA|cO9j^3GtQo@Jn(y5s6iYsyrY@o+3CHe@FEdRfy4bmhI2;!Uk1O zo7~y)eJI9K-}~>}cSEIXBU@Wl@ouVDuP!tgmQR{fS1bI)=|EVaN0?QWDtJ=nb!BQV zV?_Aw>5CufCey>TJ1M3dV8yIdjo%ums2d*|-1wU7J<+>W)5~Ipn=es=qAsT%uct|biRU8lO z*l{dWjR!6Xj8cPkI5-|P7I+oKLoWhXOe7C}6~#m^k_DOYt0*RV5h2KgUqvx7zrAR= z$n5A>QCw*H*0MlBlU(pBiUm)1IUbS)y^7+YX9OxHk_W$vVxrGfR!js>*E@ofWPTUW zKz_xhW)m8-MCoEjGKP=LkbM=!#}0i0eC(?zK71I#%^d+otbt zDl0y!L?&V5;%bpSYyoE+=p+mcR1^$!5;iC< z7Qu9=uq;q{pzWt&i_}5eXs=!Db&G|bwsFYPKqq0-e6&c#8Vqz2R;F<<&`DUTwG5S! znlz%T;k25|ah{r~)^j<|*Aw4&!ak_$NpwbsZRHf4+TRECb%2?O*+Zb5pE%;j=Alsf(*4VO^KlH3z<*W1|VKX#|Bd-RIw7GHb)3?EAUF+ z-^A;%brjDF#5eNV{rd{McK?1OuT|`Ic(c6@SFsm}Lwcczv~jODE}y5tV-D{I-HiGe zCNL8ZK{wM)&bUCFTnl0nMbtI_wpU>S;xLoHoyKc|CMC#Z%2_simS>0T6Xc^!7s*Ex zhxz>NZ1>dm<(KKxX5tzj@?w603)pY;At-KARgWgL2SHjBV8flHMDifgFpt(NicKmW z!K?~B+90j*aK-hsD9R=IMIWMngCM`Z(f1{_Mwn14ZG0>jn2+8iDEnokOiS*IJw|ow zOadKIsC5^E|NS%>^`Gkf4`tl_8*rk337 z)bnco=H?mJLDnxHWBR&>S!&Eh)Bir!$cDp|=YX>*&C#pNbgD*$%KCjwO|9|W(l^ey z+MFg6Op^DE5rf&R)WkGX^?6fiU@eQ5r)Fu*7cyPNr_R#=gG^D7W@v10aQ6bH23TWC zQInMl&B+rq1GV;>))sGU!)fkmUFk^^t{bW$Hh<&e{ao*J&9Au;Vo@W{0&i-#Ru{Oi zWkV0guJ+ut(qo2ephjNZ>Q2a$blT0dav+z~qDznErIi@fSA*=b%u6$UUGHzvq&Aq3 z(qXo_uqJThTCDSclKO(&8$2+}C3@6ZEs~g}rP?A%0w300O?AnaU!vt|3#X!ByuCIzouWpUJPlKR^kD03U9Z8j_ z%o?N{%DnH??9=!bPY8{g7Rl?|4<9O!In321CeFc~76A=QP7)d}(1}*iq)ya9=A}g1 zC@{)0WE_*ClT@v(KU|}qhiGgzR5s$x1KGrE8n87|uSl%;UZG_hvA;Q8lS(u5PKy8D z;_Lg(WuAEA*M!bRQ9|UxXF;A9`+@j5P0ukvdApeX%G{ZsV~-sn*nct07D!l`z2)a5 zOtNw|;eq!;6GgwcL7jEiV4h;cWyg_x8G#-nQs|5`Ox zpxtyK#orv6-kn|-?I{Hn&|hLLKM=|3u9sw=S{iq-{bci7MP z@+<8@YW&#vp5D|2O0Xw}Uh%RTvHOxnvvoBrlupvjtVK zWmVbJJNd93Fm9)fsWM%&-uGGSxW)dAe-pUbuQ8GYxDk@QKM9^ zX|v{tXLyLEe3+OPgJ`mU;ReSB%@;JP#h`O++oA3(R*sf!YLv3*v+QhFpFQsp9l|g{ zcPqi(OLQ{Cw*W2rrt4~LZ7!TR>OBLYKcCJ9wx3Fp?9=CM=a{dYmOUUh)!Hu;?%O`Y zhG1+1!(oD|bMN}sjXzHtzl_#4Nk#Q|K~c}%=g`pWK8Ow#y#M2m&(*fb8~Rq1WV=-$ z))l56ih+<*YLhOz*jvT3#IE~apBMQP}QzyH~Q;v4EP8y47x z$ukqQy|OHd0loPB{2%MV3JUW62s6Z8%z9vU2!o(KtQTVeWDGb#!RqbrO z$loE_dAH`Yi}`Z1@AyqVone8uUCw%W0h@@e#}CGn^a69~SLtK~>#W;TC*Vqgscxzj zHQ&HAA%Ajue5lQBHis)a1g@7t#wO&PgbbY!)w^LI8fyv&enJ$le&7<^cbNwc)z>Rw+DS>{3yMEwY+D3^nD5#^4q2xvUd~%?W+<@;?Ve&RxE_&{yT>peWwX#;QZ- zo)Af0%*3TQ{sjdvsvqiu2Ftzf4|tz+$vR+I&%}J70+j_C5Z+}i1kR@Egm&0$65F1oo~LOvuR;PJok$MX5FdY6dTP|Zw3pZDhDbbRcB_je{hbki&Z(i z;P+cy9pP74#KazQAgbC*x&gfw+J#b@nQJ(TY8LEU$@@7r;O8Y(+72MXk;@kwQ`g*_ zpZfeATA`rzWo$Y&KVzuFJ`3Hwzi%O^791q>rd!6lkk75ia;;XivW9iUo{t2 z74;Gp8^y70M?Zu5xq$Vce@6;ewtH_6%S( z^{XAtgGzB-4}D^2Z@;tKI%wxclNk#ZZm=Ao%pFgsO|5*`|j!X0r<13 zN%HFGtO@SakK-nEsaQIEG^gC!53|wRQE@f;5lh;(eBiifT}LA;oI7g5xUUe%tKFo} zYC}Ue-Obg;1}ew|)o6i68Z~isN|r6B7aXZp;;#d^W>jFS54Gzh|HF|uK2*yb67GJ& zo6MOQ_puNW&sQr%Ljp5DZwxxr+;y)E?!hCpwqC|^eR9w`+E1|NK^mfmKYX^P9?)m$ z9y)DM@N%lA1H&cU^b!P}^V7V*xl5c!3Sl0QK)FU=n=?Yn;&H|Zsmqj9NwWp?*m z>tRBZ+KJY{+St{VE7pD5z~oszH_XdMo}YjEYRXm+R|i7S*7iJ6R1CoON!{fD4HDV>NP|<`mMyM59vu7?H1;v7B`CB3%}n z-()W$Kj2aA6cDA^lo3v$vS({Su2=Aq_J>n>Vmi5giKZo#Bd{Pze4Nwrs;Y?*W~A7j zItAg21Siu~0BE6UM=&2iq6%ST<08T|*ry@w1T__LV=(F_ mZYo}#69leU1>b9JGzXDyVQXzY+cap8RX\r\n" "#endif\r\n" "\r\n" - "#include \"wmc_auto.h\"\r\n" "\r\n" -"\r\n" "#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */\r\n" "\r\n" "#ifdef WMOPS\r\n" @@ -37,23 +35,26 @@ " * Complexity counting tool\r\n" " *--------------------------------------------------------------------*/\r\n" "\r\n" -"#define MAX_RECORDS 1024\r\n" -"#define MAX_CHAR 64\r\n" -"#define MAX_STACK 64\r\n" -"#define DOUBLE_MAX 0x80000000\r\n" +"#define MAX_FUNCTION_NAME_LENGTH 50 /* Maximum length of the function name */\r\n" +"#define MAX_PARAMS_LENGTH 50 /* Maximum length of the function parameter string */\r\n" +"#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> mightb be increased during runtime, if needed */\r\n" +"#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */\r\n" +"\r\n" +"#define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */\r\n" +"#define DOUBLE_MAX 0x80000000\r\n" "\r\n" -"struct wmops_record\r\n" +"typedef struct \r\n" "{\r\n" -" char label[MAX_CHAR];\r\n" +" char label[MAX_FUNCTION_NAME_LENGTH];\r\n" " long call_number;\r\n" " long update_cnt;\r\n" -" int call_tree[MAX_RECORDS];\r\n" +" int call_tree[MAX_CALL_TREE_DEPTH];\r\n" " double start_selfcnt;\r\n" " double current_selfcnt;\r\n" " double max_selfcnt;\r\n" " double min_selfcnt;\r\n" " double tot_selfcnt;\r\n" -" double start_cnt; /* The following take into account the decendants */\r\n" +" double start_cnt; \r\n" " double current_cnt;\r\n" " double max_cnt;\r\n" " double min_cnt;\r\n" @@ -64,16 +65,14 @@ " double wc_selfcnt;\r\n" " int32_t wc_call_number;\r\n" "#endif\r\n" -"};\r\n" +"} wmops_record;\r\n" "\r\n" "double ops_cnt;\r\n" "double prom_cnt;\r\n" "double inst_cnt[NUM_INST];\r\n" "\r\n" -"static struct wmops_record wmops[MAX_RECORDS];\r\n" -"static int stack[MAX_STACK];\r\n" -"static int sptr;\r\n" -"static int num_records;\r\n" +"static wmops_record *wmops = NULL;\r\n" +"static int num_wmops_records, max_num_wmops_records;\r\n" "static int current_record;\r\n" "static long update_cnt;\r\n" "static double start_cnt;\r\n" @@ -81,20 +80,41 @@ "static double min_cnt;\r\n" "static double inst_cnt_wc[NUM_INST];\r\n" "static long fnum_cnt_wc;\r\n" -"\r\n" +"static int *wmops_caller_stack = NULL, wmops_caller_stack_index, max_wmops_caller_stack_index = 0;\r\n" "static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0;\r\n" "\r\n" -"\r\n" "void reset_wmops( void )\r\n" "{\r\n" " int i, j;\r\n" "\r\n" -" for ( i = 0; i < MAX_RECORDS; i++ )\r\n" +" num_wmops_records = 0;\r\n" +" max_num_wmops_records = MAX_NUM_RECORDS;\r\n" +" current_record = -1;\r\n" +" update_cnt = 0;\r\n" +"\r\n" +" max_cnt = 0.0;\r\n" +" min_cnt = DOUBLE_MAX;\r\n" +" start_cnt = 0.0;\r\n" +" ops_cnt = 0.0;\r\n" +"\r\n" +" /* allocate the list of wmops records */\r\n" +" if ( wmops == NULL )\r\n" +" {\r\n" +" wmops = (wmops_record *)malloc( max_num_wmops_records * sizeof( wmops_record ) );\r\n" +" }\r\n" +"\r\n" +" if ( wmops == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Records!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" for ( i = 0; i < max_num_wmops_records; i++ )\r\n" " {\r\n" " strcpy( &wmops[i].label[0], \"\\0\" );\r\n" " wmops[i].call_number = 0;\r\n" " wmops[i].update_cnt = 0;\r\n" -" for ( j = 0; j < MAX_RECORDS; j++ )\r\n" +" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n" " {\r\n" " wmops[i].call_tree[j] = -1;\r\n" " }\r\n" @@ -112,22 +132,30 @@ " wmops[i].wc_cnt = 0.0;\r\n" " wmops[i].wc_selfcnt = 0.0;\r\n" " wmops[i].current_call_number = 0;\r\n" +" wmops[i].wc_call_number = -1;\r\n" "#endif\r\n" " }\r\n" "\r\n" -" for ( i = 0; i < MAX_STACK; i++ )\r\n" +" /* allocate the list of wmops callers to track the sequence of function calls */\r\n" +" wmops_caller_stack_index = 0;\r\n" +" max_wmops_caller_stack_index = MAX_NUM_RECORDS;\r\n" +" if ( wmops_caller_stack == NULL )\r\n" " {\r\n" -" stack[i] = -1;\r\n" +" wmops_caller_stack = malloc( max_wmops_caller_stack_index * sizeof( int ) );\r\n" " }\r\n" -" sptr = 0;\r\n" -" num_records = 0;\r\n" -" current_record = -1;\r\n" -" update_cnt = 0;\r\n" "\r\n" -" max_cnt = 0.0;\r\n" -" min_cnt = DOUBLE_MAX;\r\n" -" start_cnt = 0.0;\r\n" -" ops_cnt = 0.0;\r\n" +" if ( wmops_caller_stack == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Callers!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" for ( i = 0; i < max_wmops_caller_stack_index; i++ )\r\n" +" {\r\n" +" wmops_caller_stack[i] = -1;\r\n" +" }\r\n" +"\r\n" +" return;\r\n" "}\r\n" "\r\n" "\r\n" @@ -136,9 +164,9 @@ " int new_flag;\r\n" " int i, j;\r\n" "\r\n" -" /* Check if new function record label */\r\n" +" /* Check, if this is a new function label */\r\n" " new_flag = 1;\r\n" -" for ( i = 0; i < num_records; i++ )\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" " {\r\n" " if ( strcmp( wmops[i].label, label ) == 0 )\r\n" " {\r\n" @@ -147,33 +175,36 @@ " }\r\n" " }\r\n" "\r\n" -" /* Configure new record */\r\n" +" /* Create a new record in the list */\r\n" " if ( new_flag )\r\n" " {\r\n" -" if ( num_records >= MAX_RECORDS )\r\n" +" if ( num_wmops_records >= max_num_wmops_records )\r\n" " {\r\n" -" fprintf( stdout, \"push_wmops(): exceeded MAX_RECORDS count.\\n\\n\" );\r\n" -" exit( -1 );\r\n" +" /* There is no room for a new wmops record -> reallocate the list */\r\n" +" max_num_wmops_records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" wmops = realloc( wmops, max_num_wmops_records * sizeof( wmops_record ) );\r\n" " }\r\n" +"\r\n" " strcpy( wmops[i].label, label );\r\n" -" num_records++;\r\n" +" num_wmops_records++;\r\n" " }\r\n" "\r\n" -" /* Push current context onto stack */\r\n" +" /* Push the current context info to the new record */\r\n" " if ( current_record >= 0 )\r\n" " {\r\n" -" if ( sptr >= MAX_STACK )\r\n" +" if ( wmops_caller_stack_index >= max_wmops_caller_stack_index )\r\n" " {\r\n" -" fprintf( stdout, \"\\r push_wmops(): stack exceeded, try inreasing MAX_STACK\\n\" );\r\n" -" exit( -1 );\r\n" +" /* There is no room for a new record -> reallocate the list */\r\n" +" max_wmops_caller_stack_index += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" wmops_caller_stack = realloc( wmops_caller_stack, max_wmops_caller_stack_index * sizeof( int ) );\r\n" " }\r\n" -" stack[sptr++] = current_record;\r\n" +" wmops_caller_stack[wmops_caller_stack_index++] = current_record;\r\n" "\r\n" " /* accumulate op counts */\r\n" " wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n" "\r\n" " /* update call tree */\r\n" -" for ( j = 0; j < MAX_RECORDS; j++ )\r\n" +" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n" " {\r\n" " if ( wmops[i].call_tree[j] == current_record )\r\n" " {\r\n" @@ -187,7 +218,7 @@ " }\r\n" " }\r\n" "\r\n" -" /* init current record */\r\n" +" /* update the current context info */\r\n" " current_record = i;\r\n" " wmops[current_record].start_selfcnt = ops_cnt;\r\n" " wmops[current_record].start_cnt = ops_cnt;\r\n" @@ -215,9 +246,9 @@ " wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt;\r\n" "\r\n" " /* Get back previous context from stack */\r\n" -" if ( sptr > 0 )\r\n" +" if ( wmops_caller_stack_index > 0 )\r\n" " {\r\n" -" current_record = stack[--sptr];\r\n" +" current_record = wmops_caller_stack[--wmops_caller_stack_index];\r\n" " wmops[current_record].start_selfcnt = ops_cnt;\r\n" " }\r\n" " else\r\n" @@ -239,9 +270,9 @@ " float tmpF;\r\n" "#endif\r\n" "\r\n" -" if ( sptr != 0 )\r\n" +" if ( wmops_caller_stack_index != 0 )\r\n" " {\r\n" -" fprintf( stdout, \"update_wmops(): Stack must be empty!\\n\" );\r\n" +" fprintf( stdout, \"update_wmops(): WMOPS caller stack corrupted - check that all push_wmops() are matched with pop_wmops()!\\n\" );\r\n" " exit( -1 );\r\n" " }\r\n" "\r\n" @@ -266,7 +297,7 @@ "#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" " if ( ops_cnt - start_cnt > max_cnt )\r\n" " {\r\n" -" for ( i = 0; i < num_records; i++ )\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" " {\r\n" " wmops[i].wc_cnt = wmops[i].current_cnt;\r\n" " wmops[i].wc_selfcnt = wmops[i].current_selfcnt;\r\n" @@ -275,7 +306,7 @@ " }\r\n" "#endif\r\n" "\r\n" -" for ( i = 0; i < num_records; i++ )\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" " {\r\n" " wmops[i].tot_selfcnt += wmops[i].current_selfcnt;\r\n" " wmops[i].tot_cnt += wmops[i].current_cnt;\r\n" @@ -365,7 +396,7 @@ "\r\n" " /* calculate maximum label length for compact prinout */\r\n" " max_label_len = 0;\r\n" -" for ( i = 0; i < num_records; i++ )\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" " {\r\n" " label_len = strlen( wmops[i].label );\r\n" " if ( label_len > max_label_len )\r\n" @@ -381,7 +412,7 @@ " fprintf( stdout, sfmt, max_label_len, \" routine\", \" calls\", \" min \", \" max \", \" avg \", \" min \", \" max \", \" avg \" );\r\n" " fprintf( stdout, sfmt, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\" );\r\n" "\r\n" -" for ( i = 0; i < num_records; i++ )\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" " {\r\n" " fprintf( stdout, dfmt, max_label_len, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt,\r\n" " wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt,\r\n" @@ -397,37 +428,42 @@ " fprintf( stdout, \"\\n\" );\r\n" "\r\n" "#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" fprintf( stdout, \"\\nComplexity analysis for the worst-case frame %ld:\\n\", fnum_cnt_wc );\r\n" +" fprintf( stdout, \"\\nComplexity analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n" " fprintf( stdout, \"%*s %8s %10s %12s\\n\", max_label_len, \" routine\", \" calls\", \" SELF\", \" CUMULATIVE\" );\r\n" " fprintf( stdout, \"%*s %8s %10s %10s\\n\", max_label_len, \"---------------\", \"------\", \"------\", \"----------\" );\r\n" "\r\n" -" for ( i = 0; i < num_records; i++ )\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" " {\r\n" -" fprintf( stdout, \"%*s %8d %10.3f %12.3f\\n\", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt );\r\n" +" if ( wmops[i].wc_call_number > 0 )\r\n" +" {\r\n" +" fprintf( stdout, \"%*s %8d %10.3f %12.3f\\n\", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt );\r\n" +" }\r\n" " }\r\n" "\r\n" -" fprintf( stdout, \"\\nCall Tree:\\n\\n\" );\r\n" -" fprintf( stdout, sfmtt, \" function\", \"num\", \"called by: \" );\r\n" +" fprintf( stdout, \"\\nCall tree for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n" +" fprintf( stdout, sfmtt, \" function\", \"num\", \"called by \" );\r\n" " fprintf( stdout, sfmtt, \"---------------\", \"---\", \"--------------\" );\r\n" "\r\n" -" for ( i = 0; i < num_records; i++ )\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" " {\r\n" -" fprintf( stdout, dfmtt, wmops[i].label, i );\r\n" -" for ( j = 0; wmops[i].call_tree[j] != -1; j++ )\r\n" +" if ( wmops[i].wc_call_number > 0 )\r\n" " {\r\n" -" if ( j != 0 )\r\n" +" fprintf( stdout, dfmtt, wmops[i].label, i );\r\n" +" for ( j = 0; wmops[i].call_tree[j] != -1 && j < MAX_CALL_TREE_DEPTH; j++ )\r\n" " {\r\n" -" fprintf( stdout, \", \" );\r\n" +" if ( j != 0 )\r\n" +" {\r\n" +" fprintf( stdout, \", \" );\r\n" +" }\r\n" +" fprintf( stdout, \"%d\", wmops[i].call_tree[j] );\r\n" " }\r\n" -" fprintf( stdout, \"%d\", wmops[i].call_tree[j] );\r\n" +" fprintf( stdout, \"\\n\" );\r\n" " }\r\n" -" fprintf( stdout, \"\\n\" );\r\n" " }\r\n" "\r\n" -" fprintf( stdout, sfmtt, \"---------------\", \"---\", \"--------------\" );\r\n" " fprintf( stdout, \"\\n\\n\" );\r\n" "\r\n" -" fprintf( stdout, \"\\nInstruction type analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc ); /* added -- JPA */\r\n" +" fprintf( stdout, \"\\nInstruction type analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc ); \r\n" " for ( i = 0; i < NUM_INST; i++ )\r\n" " {\r\n" " switch ( (enum instructions) i )\r\n" @@ -524,12 +560,6 @@ " * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free().\r\n" " *--------------------------------------------------------------------*/\r\n" "\r\n" -"#define MAX_RECORDABLE_CALLS 100\r\n" -"#define MAX_FUNCTION_NAME_LENGTH 35 /* Maximum length that the function string will be truncated to */\r\n" -"#define MAX_PARAMS_LENGTH 50 /* Maximum length that the parameter string will be truncated to */\r\n" -"#define MAX_NUM_RECORDS 300 /* Initial maximum number of memory records -> mightb be increased during runtime, if needed */\r\n" -"#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of memory records, increase the number of records by this number */\r\n" -"\r\n" "/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using\r\n" " a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */\r\n" "#ifdef MEM_ALIGN_64BITS\r\n" @@ -539,15 +569,13 @@ "#endif\r\n" "\r\n" "#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) )\r\n" +"#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) )\r\n" "\r\n" "#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */\r\n" "#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */\r\n" "#define OOB_START 0x1 /* Flag indicating out-of-bounds access before memory block */\r\n" "#define OOB_END 0x2 /* Flag indicating out-of-bounds access after memory block */\r\n" "\r\n" -"#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) )\r\n" -"#define IS_CALLOC( str ) ( str[0] == 'c' )\r\n" -"\r\n" "#ifdef MEM_COUNT_DETAILS\r\n" "const char *csv_filename = \"mem_analysis.csv\";\r\n" "static FILE *fid_csv_filename = NULL;\r\n" @@ -559,8 +587,16 @@ " int16_t *stack_ptr;\r\n" "} caller_info;\r\n" "\r\n" -"caller_info stack_callers[2][MAX_RECORDABLE_CALLS];\r\n" +"static caller_info *stack_callers[2] = {NULL, NULL};\r\n" "\r\n" +"static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */\r\n" +"static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */\r\n" +"static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */\r\n" +"static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */\r\n" +"static int current_calls = 0, max_num_calls = MAX_NUM_RECORDS;\r\n" +"static char location_max_stack[256] = \"undefined\";\r\n" +"\r\n" +"/* Heap-related variables */\r\n" "typedef struct\r\n" "{\r\n" " char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */\r\n" @@ -580,18 +616,12 @@ "\r\n" "allocator_record *allocation_list = NULL;\r\n" "\r\n" -"static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */\r\n" -"static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */\r\n" -"static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */\r\n" -"static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */\r\n" -"static int32_t wc_ram_size, wc_ram_frame;\r\n" -"static int32_t current_heap_size;\r\n" -"static int current_calls = 0;\r\n" -"static char location_max_stack[256] = \"undefined\";\r\n" "static int Num_Records, Max_Num_Records;\r\n" "static size_t Stat_Cnt_Size = USE_BYTES;\r\n" "static const char *Count_Unit[] = { \"bytes\", \"words\", \"words\" };\r\n" "\r\n" +"static int32_t wc_ram_size, wc_ram_frame;\r\n" +"static int32_t current_heap_size;\r\n" "static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap;\r\n" "static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap;\r\n" "static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap;\r\n" @@ -612,11 +642,28 @@ " int16_t something;\r\n" " size_t tmp_size;\r\n" "\r\n" +" /* initialize list of stack records */\r\n" +" if ( stack_callers[0] == NULL )\r\n" +" {\r\n" +" stack_callers[0] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n" +" stack_callers[1] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n" +" }\r\n" +"\r\n" +" if ( stack_callers[0] == NULL || stack_callers[1] == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Error: Unable to Allocate List of Stack Records!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" current_calls = 0;\r\n" +" max_num_calls = MAX_NUM_RECORDS;\r\n" +"\r\n" " /* initialize stack pointers */\r\n" " ptr_base_stack = &something;\r\n" " ptr_max_stack = ptr_base_stack;\r\n" " ptr_current_stack = ptr_base_stack;\r\n" "\r\n" +" /* initialize the unit of memory block size */\r\n" " Stat_Cnt_Size = cnt_size;\r\n" "\r\n" " /* Check, if sizeof(int32_t) is 4 bytes */\r\n" @@ -742,11 +789,12 @@ "\r\n" " (void) *filename; /* to avoid compilation warning */\r\n" "\r\n" -" /* Is there room to save the caller's information? */\r\n" -" if ( current_calls >= MAX_RECORDABLE_CALLS )\r\n" -" { /* No */\r\n" -" fprintf( stderr, \"No more room to store call stack info. Please increase MAX_RECORDABLE_CALLS\" );\r\n" -" exit( -1 );\r\n" +" if ( current_calls >= max_num_calls )\r\n" +" {\r\n" +" /* There is no room for a new record -> reallocate the list */\r\n" +" max_num_calls += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" stack_callers[0] = realloc( stack_callers[0], max_num_calls * sizeof( caller_info ) );\r\n" +" stack_callers[1] = realloc( stack_callers[1], max_num_calls * sizeof( caller_info ) );\r\n" " }\r\n" "\r\n" " /* Valid Function Name? */\r\n" @@ -763,7 +811,7 @@ " /* Save the Stack Pointer */\r\n" " stack_callers[0][current_calls].stack_ptr = ptr_current_stack;\r\n" "\r\n" -" /* Increase Stack Calling Tree Level */\r\n" +" /* Increase the Number of Calls in the List */\r\n" " current_calls++;\r\n" "\r\n" " /* Is this the First Time or the Worst Case? */\r\n" @@ -772,15 +820,17 @@ " /* Save Info about it */\r\n" " ptr_max_stack = ptr_current_stack;\r\n" "\r\n" -" wc_stack_frame = update_cnt; /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */\r\n" +" /* save the worst-case frame number */\r\n" +" /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */\r\n" +" wc_stack_frame = update_cnt; \r\n" " strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 );\r\n" " location_max_stack[sizeof( location_max_stack ) - 1] = '\\0';\r\n" "\r\n" " /* Save Call Tree */\r\n" " memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls );\r\n" "\r\n" -" /* Terminate the List (Unless Full) */\r\n" -" if ( current_calls < MAX_RECORDABLE_CALLS )\r\n" +" /* Terminate the List with 0 (for printing purposes) */\r\n" +" if ( current_calls < max_num_calls )\r\n" " {\r\n" " stack_callers[1][current_calls].function_name[0] = 0;\r\n" " }\r\n" @@ -816,13 +866,13 @@ "\r\n" " (void) *filename; /* to avoid compilation warning */\r\n" "\r\n" -" /* Decrease Stack Calling */\r\n" +" /* Decrease the Number of Records */\r\n" " current_calls--;\r\n" "\r\n" " /* Get Pointer to Caller Information */\r\n" " caller_info_ptr = &stack_callers[0][current_calls];\r\n" "\r\n" -" /* Check, if Names Match */\r\n" +" /* Check, if the Function Names Match */\r\n" " if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 )\r\n" " {\r\n" " fprintf( stderr, \"Invalid usage of pop_stack()\" );\r\n" @@ -861,7 +911,7 @@ " fprintf( stdout, \"\\nList of functions when maximum stack size is reached:\\n\\n\" );\r\n" "\r\n" " caller_info_ptr = &stack_callers[1][0];\r\n" -" for ( call_level = 0; call_level < MAX_RECORDABLE_CALLS; call_level++ )\r\n" +" for ( call_level = 0; call_level < max_num_calls; call_level++ )\r\n" " {\r\n" " /* Done? */\r\n" " if ( caller_info_ptr->function_name[0] == 0 )\r\n" @@ -1060,7 +1110,7 @@ "\r\n" " /* Fill Memory Block with Magic Value or 0 */\r\n" " fill_value = MAGIC_VALUE_USED;\r\n" -" if ( IS_CALLOC( size_str ) )\r\n" +" if ( size_str[0] == 'c' )\r\n" " {\r\n" " fill_value = 0x00000000;\r\n" " }\r\n" @@ -1924,4 +1974,5 @@ "#ifndef WMOPS\r\n" "int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */\r\n" "#endif\r\n" +"\r\n" "\r\n" \ No newline at end of file diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index cfd4a71..938ba8f 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -30,11 +30,9 @@ "#endif\r\n" "\r\n" "/* Real-time relationships */\r\n" -"#define FRAMES_PER_SECOND 50.0\r\n" -"#define MILLION_CYCLES 1e6\r\n" +"#define FRAMES_PER_SECOND 50.0 \r\n" "#define WMOPS_BOOST_FAC ( 1.0f ) /* scaling factor for equalizing the difference between automatic and manual instrumentation */\r\n" -"#define FAC ( FRAMES_PER_SECOND / MILLION_CYCLES * WMOPS_BOOST_FAC )\r\n" -"#define NUM_INST 20 /* Total number of instruction types (in enum below) */\r\n" +"#define FAC ( FRAMES_PER_SECOND / 1e6 * WMOPS_BOOST_FAC )\r\n" "\r\n" "\r\n" "#ifdef WMOPS\r\n" @@ -59,7 +57,8 @@ " _TEST,\r\n" " _POWER,\r\n" " _LOG,\r\n" -" _MISC\r\n" +" _MISC,\r\n" +" NUM_INST\r\n" "};\r\n" "\r\n" "#define _ADD_C 1\r\n" From 209c41910e00609f4eb74de526cee0842f0d6a5f Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 27 Sep 2023 09:22:34 +0200 Subject: [PATCH 24/67] support for counting BASOP complexity --- src/wmc_tool/wmc_auto_c.txt | 171 ++++++++++++++- src/wmc_tool/wmc_auto_h.txt | 406 +++++++++++++++++++++++++++++++++++- 2 files changed, 574 insertions(+), 3 deletions(-) diff --git a/src/wmc_tool/wmc_auto_c.txt b/src/wmc_tool/wmc_auto_c.txt index 142e8cd..6265940 100644 --- a/src/wmc_tool/wmc_auto_c.txt +++ b/src/wmc_tool/wmc_auto_c.txt @@ -39,7 +39,6 @@ "#define MAX_PARAMS_LENGTH 50 /* Maximum length of the function parameter string */\r\n" "#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> mightb be increased during runtime, if needed */\r\n" "#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */\r\n" -"\r\n" "#define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */\r\n" "#define DOUBLE_MAX 0x80000000\r\n" "\r\n" @@ -49,6 +48,7 @@ " long call_number;\r\n" " long update_cnt;\r\n" " int call_tree[MAX_CALL_TREE_DEPTH];\r\n" +" long LastWOper;\r\n" " double start_selfcnt;\r\n" " double current_selfcnt;\r\n" " double max_selfcnt;\r\n" @@ -86,6 +86,7 @@ "void reset_wmops( void )\r\n" "{\r\n" " int i, j;\r\n" +" unsigned int *ptr;\r\n" "\r\n" " num_wmops_records = 0;\r\n" " max_num_wmops_records = MAX_NUM_RECORDS;\r\n" @@ -109,6 +110,20 @@ " exit( -1 );\r\n" " }\r\n" "\r\n" +" /* allocate the BASOP WMOPS counter */\r\n" +" if ( multiCounter == NULL )\r\n" +" {\r\n" +" multiCounter = (BASIC_OP *) malloc( max_num_wmops_records * sizeof( BASIC_OP ) );\r\n" +" }\r\n" +"\r\n" +" if ( multiCounter == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Error: Unable to Allocate the BASOP WMOPS counter!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" /* initilize the list of wmops records */\r\n" +" /* initilize the BASOP WMOPS counters */\r\n" " for ( i = 0; i < max_num_wmops_records; i++ )\r\n" " {\r\n" " strcpy( &wmops[i].label[0], \"\\0\" );\r\n" @@ -134,6 +149,14 @@ " wmops[i].current_call_number = 0;\r\n" " wmops[i].wc_call_number = -1;\r\n" "#endif\r\n" +"\r\n" +" /* clear all BASOP operation counters */\r\n" +" ptr = (unsigned int*) &multiCounter[i];\r\n" +" for ( j = 0; j < (int) ( sizeof(BASIC_OP ) / sizeof( unsigned int ) ); j++ )\r\n" +" {\r\n" +" *ptr++ = 0;\r\n" +" }\r\n" +" wmops[i].LastWOper = 0;\r\n" " }\r\n" "\r\n" " /* allocate the list of wmops callers to track the sequence of function calls */\r\n" @@ -155,6 +178,10 @@ " wmops_caller_stack[i] = -1;\r\n" " }\r\n" "\r\n" +" /* initialize auxiliary BASOP WMOPS variables */\r\n" +" call_occurred = 1;\r\n" +" funcId_where_last_call_to_else_occurred = INT_MAX;\r\n" +"\r\n" " return;\r\n" "}\r\n" "\r\n" @@ -183,9 +210,11 @@ " /* There is no room for a new wmops record -> reallocate the list */\r\n" " max_num_wmops_records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" " wmops = realloc( wmops, max_num_wmops_records * sizeof( wmops_record ) );\r\n" +" multiCounter = realloc( multiCounter, max_num_wmops_records * sizeof( BASIC_OP ) );\r\n" " }\r\n" "\r\n" " strcpy( wmops[i].label, label );\r\n" +"\r\n" " num_wmops_records++;\r\n" " }\r\n" "\r\n" @@ -227,12 +256,16 @@ " wmops[current_record].current_call_number++;\r\n" "#endif\r\n" "\r\n" +" /* set the ID of BASOP functions counters */\r\n" +" Set_BASOP_WMOPS_counter( current_record );\r\n" +"\r\n" " return;\r\n" "}\r\n" "\r\n" "\r\n" "void pop_wmops( void )\r\n" "{\r\n" +" long tot;\r\n" "\r\n" " /* Check for underflow */\r\n" " if ( current_record < 0 )\r\n" @@ -241,6 +274,10 @@ " exit( -1 );\r\n" " }\r\n" "\r\n" +" /* add the BASOP complexity to the counter */\r\n" +" tot = DeltaWeightedOperation();\r\n" +" ops_cnt += tot;\r\n" +"\r\n" " /* update count of current record */\r\n" " wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n" " wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt;\r\n" @@ -250,6 +287,9 @@ " {\r\n" " current_record = wmops_caller_stack[--wmops_caller_stack_index];\r\n" " wmops[current_record].start_selfcnt = ops_cnt;\r\n" +"\r\n" +" /* set the ID of the previous BASOP counter */\r\n" +" Set_BASOP_WMOPS_counter( current_record );\r\n" " }\r\n" " else\r\n" " {\r\n" @@ -345,6 +385,10 @@ "#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" " wmops[i].current_call_number = 0;\r\n" "#endif\r\n" +"\r\n" +" /* update the WC of all BASOP counters */\r\n" +" Set_BASOP_WMOPS_counter( i );\r\n" +" Reset_BASOP_WMOPS_counter();\r\n" " }\r\n" "\r\n" " current_cnt = ops_cnt - start_cnt;\r\n" @@ -534,6 +578,24 @@ " }\r\n" "#endif\r\n" "\r\n" +" /* De-allocate the list of wmops record */\r\n" +" if ( wmops != NULL )\r\n" +" {\r\n" +" free( wmops );\r\n" +" }\r\n" +"\r\n" +" /* De-allocate the list of wmops caller functions */\r\n" +" if ( wmops_caller_stack != NULL )\r\n" +" {\r\n" +" free( wmops_caller_stack );\r\n" +" }\r\n" +"\r\n" +" /* De-allocate the BASOP WMOPS counter */\r\n" +" if ( multiCounter != NULL )\r\n" +" {\r\n" +" free( multiCounter );\r\n" +" }\r\n" +"\r\n" " return;\r\n" "}\r\n" "\r\n" @@ -1937,6 +1999,17 @@ " free( allocation_list );\r\n" " }\r\n" "\r\n" +" /* De-allocate list of stack records */\r\n" +" if ( stack_callers[0] != NULL )\r\n" +" {\r\n" +" free( stack_callers[0] );\r\n" +" }\r\n" +"\r\n" +" if ( stack_callers[1] != NULL )\r\n" +" {\r\n" +" free( stack_callers[1] );\r\n" +" }\r\n" +"\r\n" " /* De-allocate heap allocation call tree */\r\n" " if ( heap_allocation_call_tree != NULL )\r\n" " {\r\n" @@ -1975,4 +2048,100 @@ "int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */\r\n" "#endif\r\n" "\r\n" +"#ifdef WMOPS\r\n" +"/* Global counter for the calculation of BASOP complexity */\r\n" +"BASIC_OP *multiCounter = NULL;\r\n" +"int currCounter = 0;\r\n" +"int funcId_where_last_call_to_else_occurred;\r\n" +"long funcid_total_wmops_at_last_call_to_else;\r\n" +"int call_occurred = 1;\r\n" +"\r\n" +"const BASIC_OP op_weight = {\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 2, 2, 1,\r\n" +" 1, 1, 1, 3, 1,\r\n" +"\r\n" +" 1, 1, 1, 3, 1,\r\n" +" 4, 1, 18, 1, 1,\r\n" +" 2, 1, 2, 2, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 3, 3, 3, 3, 1,\r\n" +"\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 1, 2,\r\n" +" 1, 2, 2, 4, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +"\r\n" +" 1, 1, 1, 1, 3,\r\n" +" 3, 3, 3, 3, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 1, 4, 4,\r\n" +" 4, 8, 3, 4, 4,\r\n" +"\r\n" +" 5, 32, 3\r\n" +"};\r\n" +"\r\n" +"/* Set the counter group to use, default is zero */\r\n" +"void Set_BASOP_WMOPS_counter( int counterId )\r\n" +"{\r\n" +" if ( ( counterId > num_wmops_records ) || ( counterId < 0 ) )\r\n" +" {\r\n" +" currCounter = 0;\r\n" +" return;\r\n" +" }\r\n" +" currCounter = counterId;\r\n" +" call_occurred = 1;\r\n" +"}\r\n" +"\r\n" +"long TotalWeightedOperation()\r\n" +"{\r\n" +" int i;\r\n" +" const long *ptr, *ptr2;\r\n" +" long tot; \r\n" +"\r\n" +" tot = 0;\r\n" +" ptr = (const long *) &multiCounter[currCounter];\r\n" +" ptr2 = (const long *) &op_weight;\r\n" +" for ( i = 0; i < ( int )( sizeof( multiCounter[currCounter] ) / sizeof( long ) ); i++ )\r\n" +" {\r\n" +" tot += ( ( *ptr++ ) * ( *ptr2++ ) );\r\n" +" }\r\n" +"\r\n" +" return ( (long) tot );\r\n" +"}\r\n" +"\r\n" +"long DeltaWeightedOperation()\r\n" +"{\r\n" +" long NewWOper, delta;\r\n" +"\r\n" +" NewWOper = TotalWeightedOperation();\r\n" +" delta = NewWOper - wmops[currCounter].LastWOper;\r\n" +" wmops[currCounter].LastWOper = NewWOper;\r\n" +"\r\n" +" return ( delta );\r\n" +"}\r\n" +"\r\n" +"/* Resets the current BASOP WMOPS counter */\r\n" +"void Reset_BASOP_WMOPS_counter( void )\r\n" +"{\r\n" +" int i;\r\n" +" long *ptr;\r\n" +"\r\n" +" /* clear the current BASOP operation counter before new frame begins */\r\n" +" ptr = (long *) &multiCounter[currCounter];\r\n" +" for ( i = 0; i < (int) ( sizeof( multiCounter[currCounter] ) / sizeof( long ) ); i++ )\r\n" +" {\r\n" +" *ptr++ = 0;\r\n" +" }\r\n" +"\r\n" +" wmops[currCounter].LastWOper = 0;\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"#endif\r\n" +"\r\n" "\r\n" \ No newline at end of file diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index 938ba8f..ccbaca4 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -29,12 +29,15 @@ "#pragma GCC system_header\r\n" "#endif\r\n" "\r\n" +"#ifndef INT_MAX\r\n" +"#define INT_MAX 32767\r\n" +"#endif\r\n" +"\r\n" "/* Real-time relationships */\r\n" "#define FRAMES_PER_SECOND 50.0 \r\n" "#define WMOPS_BOOST_FAC ( 1.0f ) /* scaling factor for equalizing the difference between automatic and manual instrumentation */\r\n" "#define FAC ( FRAMES_PER_SECOND / 1e6 * WMOPS_BOOST_FAC )\r\n" "\r\n" -"\r\n" "#ifdef WMOPS\r\n" "enum instructions\r\n" "{\r\n" @@ -560,7 +563,6 @@ "extern double ops_cnt;\r\n" "extern double prom_cnt;\r\n" "extern double inst_cnt[NUM_INST];\r\n" -"extern int ops_cnt_activ;\r\n" "\r\n" "void reset_wmops( void );\r\n" "void push_wmops( const char *label );\r\n" @@ -1035,5 +1037,405 @@ "\r\n" "#endif\r\n" "\r\n" +"\r\n" +"/* Global counter variable for calculation of complexity weight */\r\n" +"typedef struct\r\n" +"{\r\n" +" unsigned int add; /* Complexity Weight of 1 */\r\n" +" unsigned int sub; /* Complexity Weight of 1 */\r\n" +" unsigned int abs_s; /* Complexity Weight of 1 */\r\n" +" unsigned int shl; /* Complexity Weight of 1 */\r\n" +" unsigned int shr; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int extract_h; /* Complexity Weight of 1 */\r\n" +" unsigned int extract_l; /* Complexity Weight of 1 */\r\n" +" unsigned int mult; /* Complexity Weight of 1 */\r\n" +" unsigned int L_mult; /* Complexity Weight of 1 */\r\n" +" unsigned int negate; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int round; /* Complexity Weight of 1 */\r\n" +" unsigned int L_mac; /* Complexity Weight of 1 */\r\n" +" unsigned int L_msu; /* Complexity Weight of 1 */\r\n" +" unsigned int L_macNs; /* Complexity Weight of 1 */\r\n" +" unsigned int L_msuNs; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L_add; /* Complexity Weight of 1 */\r\n" +" unsigned int L_sub; /* Complexity Weight of 1 */\r\n" +" unsigned int L_add_c; /* Complexity Weight of 2 */\r\n" +" unsigned int L_sub_c; /* Complexity Weight of 2 */\r\n" +" unsigned int L_negate; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L_shl; /* Complexity Weight of 1 */\r\n" +" unsigned int L_shr; /* Complexity Weight of 1 */\r\n" +" unsigned int mult_r; /* Complexity Weight of 1 */\r\n" +" unsigned int shr_r; /* Complexity Weight of 3 */\r\n" +" unsigned int mac_r; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int msu_r; /* Complexity Weight of 1 */\r\n" +" unsigned int L_deposit_h; /* Complexity Weight of 1 */\r\n" +" unsigned int L_deposit_l; /* Complexity Weight of 1 */\r\n" +" unsigned int L_shr_r; /* Complexity Weight of 3 */\r\n" +" unsigned int L_abs; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L_sat; /* Complexity Weight of 4 */\r\n" +" unsigned int norm_s; /* Complexity Weight of 1 */\r\n" +" unsigned int div_s; /* Complexity Weight of 18 */\r\n" +" unsigned int norm_l; /* Complexity Weight of 1 */\r\n" +" unsigned int move16; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int move32; /* Complexity Weight of 2 */\r\n" +" unsigned int Logic16; /* Complexity Weight of 1 */\r\n" +" unsigned int Logic32; /* Complexity Weight of 2 */\r\n" +" unsigned int Test; /* Complexity Weight of 2 */\r\n" +" unsigned int s_max; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int s_min; /* Complexity Weight of 1 */\r\n" +" unsigned int L_max; /* Complexity Weight of 1 */\r\n" +" unsigned int L_min; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_max; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_min; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int shl_r; /* Complexity Weight of 3 */\r\n" +" unsigned int L_shl_r; /* Complexity Weight of 3 */\r\n" +" unsigned int L40_shr_r; /* Complexity Weight of 3 */\r\n" +" unsigned int L40_shl_r; /* Complexity Weight of 3 */\r\n" +" unsigned int norm_L40; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L40_shl; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_shr; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_negate; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_add; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_sub; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L40_abs; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_mult; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_mac; /* Complexity Weight of 1 */\r\n" +" unsigned int mac_r40; /* Complexity Weight of 2 */\r\n" +"\r\n" +" unsigned int L40_msu; /* Complexity Weight of 1 */\r\n" +" unsigned int msu_r40; /* Complexity Weight of 2 */\r\n" +" unsigned int Mpy_32_16_ss; /* Complexity Weight of 2 */\r\n" +" unsigned int Mpy_32_32_ss; /* Complexity Weight of 4 */\r\n" +" unsigned int L_mult0; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L_mac0; /* Complexity Weight of 1 */\r\n" +" unsigned int L_msu0; /* Complexity Weight of 1 */\r\n" +" unsigned int lshl; /* Complexity Weight of 1 */\r\n" +" unsigned int lshr; /* Complexity Weight of 1 */\r\n" +" unsigned int L_lshl; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L_lshr; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_lshl; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_lshr; /* Complexity Weight of 1 */\r\n" +" unsigned int s_and; /* Complexity Weight of 1 */\r\n" +" unsigned int s_or; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int s_xor; /* Complexity Weight of 1 */\r\n" +" unsigned int L_and; /* Complexity Weight of 1 */\r\n" +" unsigned int L_or; /* Complexity Weight of 1 */\r\n" +" unsigned int L_xor; /* Complexity Weight of 1 */\r\n" +" unsigned int rotl; /* Complexity Weight of 3 */\r\n" +"\r\n" +" unsigned int rotr; /* Complexity Weight of 3 */\r\n" +" unsigned int L_rotl; /* Complexity Weight of 3 */\r\n" +" unsigned int L_rotr; /* Complexity Weight of 3 */\r\n" +" unsigned int L40_set; /* Complexity Weight of 3 */\r\n" +" unsigned int L40_deposit_h; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L40_deposit_l; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_deposit32; /* Complexity Weight of 1 */\r\n" +" unsigned int Extract40_H; /* Complexity Weight of 1 */\r\n" +" unsigned int Extract40_L; /* Complexity Weight of 1 */\r\n" +" unsigned int L_Extract40; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L40_round; /* Complexity Weight of 1 */\r\n" +" unsigned int L_saturate40; /* Complexity Weight of 1 */\r\n" +" unsigned int round40; /* Complexity Weight of 1 */\r\n" +" unsigned int If; /* Complexity Weight of 4 */\r\n" +" unsigned int Goto; /* Complexity Weight of 4 */\r\n" +"\r\n" +" unsigned int Break; /* Complexity Weight of 4 */\r\n" +" unsigned int Switch; /* Complexity Weight of 8 */\r\n" +" unsigned int For; /* Complexity Weight of 3 */\r\n" +" unsigned int While; /* Complexity Weight of 4 */\r\n" +" unsigned int Continue; /* Complexity Weight of 4 */\r\n" +"\r\n" +" unsigned int L_mls; /* Complexity Weight of 6 */\r\n" +" unsigned int div_l; /* Complexity Weight of 32 */\r\n" +" unsigned int i_mult; /* Complexity Weight of 3 */\r\n" +"} BASIC_OP;\r\n" +"\r\n" +"#ifdef WMOPS\r\n" +"extern BASIC_OP *multiCounter;\r\n" +"extern int currCounter;\r\n" +"\r\n" +"/* Technical note :\r\n" +" * The following 3 variables are only used for correct complexity\r\n" +" * evaluation of the following structure :\r\n" +" * IF{\r\n" +" * ...\r\n" +" * } ELSE IF {\r\n" +" * ...\r\n" +" * } ELSE IF {\r\n" +" * ...\r\n" +" * }\r\n" +" * ...\r\n" +" * } ELSE {\r\n" +" * ...\r\n" +" * }\r\n" +" */\r\n" +"extern int funcId_where_last_call_to_else_occurred;\r\n" +"extern long funcid_total_wmops_at_last_call_to_else;\r\n" +"extern int call_occurred;\r\n" +"\r\n" +"extern long TotalWeightedOperation( void );\r\n" +"long DeltaWeightedOperation();\r\n" +"\r\n" +"void Set_BASOP_WMOPS_counter( int counterId );\r\n" +"void Reset_BASOP_WMOPS_counter( void );\r\n" +"\r\n" +"#endif\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : FOR\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro FOR should be used instead of the 'for' C statement.\r\n" +" * The complexity is independent of the number of loop iterations that are\r\n" +" * performed.\r\n" +" *\r\n" +" * Complexity weight : 3 (regardless of number of iterations).\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define FOR( a) for( a)\r\n" +"\r\n" +"#else \r\n" +"#define FOR( a) if( incrFor(), 0); else for( a)\r\n" +"\r\n" +"static __inline void incrFor( void) {\r\n" +" multiCounter[currCounter].For++;\r\n" +"}\r\n" +"#endif \r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : WHILE\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro WHILE should be used instead of the 'while' C statement.\r\n" +" * The complexity is proportional to the number of loop iterations that\r\n" +" * are performed.\r\n" +" *\r\n" +" * Complexity weight : 4 x 'number of loop iterations'.\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define WHILE( a) while( a)\r\n" +"\r\n" +"#else \r\n" +"#define WHILE( a) while( incrWhile(), a)\r\n" +"\r\n" +"static __inline void incrWhile( void) {\r\n" +" multiCounter[currCounter].While++;\r\n" +"}\r\n" +"#endif \r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : DO\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro DO should be used instead of the 'do' C statement.\r\n" +" *\r\n" +" * Complexity weight : 0 (complexity counted by WHILE macro).\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define DO do\r\n" +"\r\n" +"#else \r\n" +"#define DO do\r\n" +"\r\n" +"#endif \r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : IF\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro IF should :\r\n" +" *\r\n" +" * - not be used when :\r\n" +" * - the 'if' structure does not have any 'else if' nor 'else' statement\r\n" +" * - and it conditions only one DSP basic operations.\r\n" +" *\r\n" +" * - be used instead of the 'if' C statement in every other case :\r\n" +" * - when there is an 'else' or 'else if' statement,\r\n" +" * - or when the 'if' conditions several DSP basic operations,\r\n" +" * - or when the 'if' conditions a function call.\r\n" +" *\r\n" +" * Complexity weight : 4\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define IF( a) if( a)\r\n" +"\r\n" +"#else \r\n" +"#define IF( a) if( incrIf(), a)\r\n" +"\r\n" +"static __inline void incrIf( void) {\r\n" +" /* Technical note :\r\n" +" * If the \"IF\" operator comes just after an \"ELSE\", its counter\r\n" +" * must not be incremented.\r\n" +" */\r\n" +" if ( ( currCounter != funcId_where_last_call_to_else_occurred ) || ( TotalWeightedOperation() != funcid_total_wmops_at_last_call_to_else ) || ( call_occurred == 1 ) )\r\n" +" {\r\n" +" multiCounter[currCounter].If++;\r\n" +" }\r\n" +"\r\n" +" call_occurred = 0;\r\n" +" funcId_where_last_call_to_else_occurred = INT_MAX;\r\n" +"}\r\n" +"#endif \r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : ELSE\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro ELSE should be used instead of the 'else' C statement.\r\n" +" *\r\n" +" * Complexity weight : 4\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define ELSE else\r\n" +"\r\n" +"#else \r\n" +"#define ELSE else if( incrElse(), 0) ; else\r\n" +"\r\n" +"static __inline void incrElse( void) {\r\n" +" multiCounter[currCounter].If++;\r\n" +"\r\n" +" /* We keep track of the funcId of the last function\r\n" +" * which used ELSE {...} structure.\r\n" +" */\r\n" +" funcId_where_last_call_to_else_occurred = currCounter;\r\n" +"\r\n" +" /* We keep track of the number of WMOPS of this funcId\r\n" +" * when the ELSE macro was called.\r\n" +" */\r\n" +" funcid_total_wmops_at_last_call_to_else = TotalWeightedOperation();\r\n" +"\r\n" +" /* call_occurred is set to 0, in order to count the next IF (if necessary)\r\n" +" */\r\n" +" call_occurred = 0;\r\n" +"}\r\n" +"#endif \r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : SWITCH\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro SWITCH should be used instead of the 'switch' C statement.\r\n" +" *\r\n" +" * Complexity weight : 8\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define SWITCH( a) switch( a)\r\n" +"\r\n" +"#else \r\n" +"#define SWITCH( a) switch( incrSwitch(), a)\r\n" +"\r\n" +"static __inline void incrSwitch( void) {\r\n" +" multiCounter[currCounter].Switch++;\r\n" +"}\r\n" +"#endif \r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : CONTINUE\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro CONTINUE should be used instead of the 'continue' C statement.\r\n" +" *\r\n" +" * Complexity weight : 4\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define CONTINUE continue\r\n" +"\r\n" +"#else \r\n" +"#define CONTINUE if( incrContinue(), 0); else continue\r\n" +"\r\n" +"static __inline void incrContinue( void) {\r\n" +" multiCounter[currCounter].Continue++;\r\n" +"}\r\n" +"#endif \r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : BREAK\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro BREAK should be used instead of the 'break' C statement.\r\n" +" *\r\n" +" * Complexity weight : 4\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define BREAK break\r\n" +"\r\n" +"#else \r\n" +"#define BREAK if( incrBreak(), 0) break; else break\r\n" +"\r\n" +"static __inline void incrBreak( void) {\r\n" +" multiCounter[currCounter].Break++;\r\n" +"}\r\n" +"#endif \r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : GOTO\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro GOTO should be used instead of the 'goto' C statement.\r\n" +" *\r\n" +" * Complexity weight : 4\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define GOTO goto\r\n" +"\r\n" +"#else \r\n" +"#define GOTO if( incrGoto(), 0); else goto\r\n" +"\r\n" +"static __inline void incrGoto( void) {\r\n" +" multiCounter[currCounter].Goto++;\r\n" +"}\r\n" +"#endif \r\n" +"\r\n" "#endif /* WMOPS_H */\r\n" +"\r\n" "\r\n" \ No newline at end of file From a93d1b3d5777b3c2d1dc230ecfe57a289873ace4 Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 27 Sep 2023 09:34:13 +0200 Subject: [PATCH 25/67] new reference files wmc_auto.[c|h] for ctest --- src/wmc_tool/test_data/ref/wmc_auto.c | 171 ++++++++++- src/wmc_tool/test_data/ref/wmc_auto.h | 406 +++++++++++++++++++++++++- 2 files changed, 574 insertions(+), 3 deletions(-) diff --git a/src/wmc_tool/test_data/ref/wmc_auto.c b/src/wmc_tool/test_data/ref/wmc_auto.c index 8e70ebe..00c2896 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.c +++ b/src/wmc_tool/test_data/ref/wmc_auto.c @@ -39,7 +39,6 @@ #define MAX_PARAMS_LENGTH 50 /* Maximum length of the function parameter string */ #define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> mightb be increased during runtime, if needed */ #define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */ - #define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */ #define DOUBLE_MAX 0x80000000 @@ -49,6 +48,7 @@ typedef struct long call_number; long update_cnt; int call_tree[MAX_CALL_TREE_DEPTH]; + long LastWOper; double start_selfcnt; double current_selfcnt; double max_selfcnt; @@ -86,6 +86,7 @@ static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0 void reset_wmops( void ) { int i, j; + unsigned int *ptr; num_wmops_records = 0; max_num_wmops_records = MAX_NUM_RECORDS; @@ -109,6 +110,20 @@ void reset_wmops( void ) exit( -1 ); } + /* allocate the BASOP WMOPS counter */ + if ( multiCounter == NULL ) + { + multiCounter = (BASIC_OP *) malloc( max_num_wmops_records * sizeof( BASIC_OP ) ); + } + + if ( multiCounter == NULL ) + { + fprintf( stderr, "Error: Unable to Allocate the BASOP WMOPS counter!" ); + exit( -1 ); + } + + /* initilize the list of wmops records */ + /* initilize the BASOP WMOPS counters */ for ( i = 0; i < max_num_wmops_records; i++ ) { strcpy( &wmops[i].label[0], "\0" ); @@ -134,6 +149,14 @@ void reset_wmops( void ) wmops[i].current_call_number = 0; wmops[i].wc_call_number = -1; #endif + + /* clear all BASOP operation counters */ + ptr = (unsigned int*) &multiCounter[i]; + for ( j = 0; j < (int) ( sizeof(BASIC_OP ) / sizeof( unsigned int ) ); j++ ) + { + *ptr++ = 0; + } + wmops[i].LastWOper = 0; } /* allocate the list of wmops callers to track the sequence of function calls */ @@ -155,6 +178,10 @@ void reset_wmops( void ) wmops_caller_stack[i] = -1; } + /* initialize auxiliary BASOP WMOPS variables */ + call_occurred = 1; + funcId_where_last_call_to_else_occurred = INT_MAX; + return; } @@ -183,9 +210,11 @@ void push_wmops( const char *label ) /* There is no room for a new wmops record -> reallocate the list */ max_num_wmops_records += MAX_NUM_RECORDS_REALLOC_STEP; wmops = realloc( wmops, max_num_wmops_records * sizeof( wmops_record ) ); + multiCounter = realloc( multiCounter, max_num_wmops_records * sizeof( BASIC_OP ) ); } strcpy( wmops[i].label, label ); + num_wmops_records++; } @@ -227,12 +256,16 @@ void push_wmops( const char *label ) wmops[current_record].current_call_number++; #endif + /* set the ID of BASOP functions counters */ + Set_BASOP_WMOPS_counter( current_record ); + return; } void pop_wmops( void ) { + long tot; /* Check for underflow */ if ( current_record < 0 ) @@ -241,6 +274,10 @@ void pop_wmops( void ) exit( -1 ); } + /* add the BASOP complexity to the counter */ + tot = DeltaWeightedOperation(); + ops_cnt += tot; + /* update count of current record */ wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt; @@ -250,6 +287,9 @@ void pop_wmops( void ) { current_record = wmops_caller_stack[--wmops_caller_stack_index]; wmops[current_record].start_selfcnt = ops_cnt; + + /* set the ID of the previous BASOP counter */ + Set_BASOP_WMOPS_counter( current_record ); } else { @@ -345,6 +385,10 @@ void update_wmops( void ) #ifdef WMOPS_WC_FRAME_ANALYSIS wmops[i].current_call_number = 0; #endif + + /* update the WC of all BASOP counters */ + Set_BASOP_WMOPS_counter( i ); + Reset_BASOP_WMOPS_counter(); } current_cnt = ops_cnt - start_cnt; @@ -534,6 +578,24 @@ void print_wmops( void ) } #endif + /* De-allocate the list of wmops record */ + if ( wmops != NULL ) + { + free( wmops ); + } + + /* De-allocate the list of wmops caller functions */ + if ( wmops_caller_stack != NULL ) + { + free( wmops_caller_stack ); + } + + /* De-allocate the BASOP WMOPS counter */ + if ( multiCounter != NULL ) + { + free( multiCounter ); + } + return; } @@ -1937,6 +1999,17 @@ void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) free( allocation_list ); } + /* De-allocate list of stack records */ + if ( stack_callers[0] != NULL ) + { + free( stack_callers[0] ); + } + + if ( stack_callers[1] != NULL ) + { + free( stack_callers[1] ); + } + /* De-allocate heap allocation call tree */ if ( heap_allocation_call_tree != NULL ) { @@ -1975,4 +2048,100 @@ void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */ #endif +#ifdef WMOPS +/* Global counter for the calculation of BASOP complexity */ +BASIC_OP *multiCounter = NULL; +int currCounter = 0; +int funcId_where_last_call_to_else_occurred; +long funcid_total_wmops_at_last_call_to_else; +int call_occurred = 1; + +const BASIC_OP op_weight = { + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 2, 2, 1, + 1, 1, 1, 3, 1, + + 1, 1, 1, 3, 1, + 4, 1, 18, 1, 1, + 2, 1, 2, 2, 1, + 1, 1, 1, 1, 1, + 3, 3, 3, 3, 1, + + 1, 1, 1, 1, 1, + 1, 1, 1, 2, + 1, 2, 2, 4, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 3, + 3, 3, 3, 3, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 4, 4, + 4, 8, 3, 4, 4, + + 5, 32, 3 +}; + +/* Set the counter group to use, default is zero */ +void Set_BASOP_WMOPS_counter( int counterId ) +{ + if ( ( counterId > num_wmops_records ) || ( counterId < 0 ) ) + { + currCounter = 0; + return; + } + currCounter = counterId; + call_occurred = 1; +} + +long TotalWeightedOperation() +{ + int i; + const long *ptr, *ptr2; + long tot; + + tot = 0; + ptr = (const long *) &multiCounter[currCounter]; + ptr2 = (const long *) &op_weight; + for ( i = 0; i < ( int )( sizeof( multiCounter[currCounter] ) / sizeof( long ) ); i++ ) + { + tot += ( ( *ptr++ ) * ( *ptr2++ ) ); + } + + return ( (long) tot ); +} + +long DeltaWeightedOperation() +{ + long NewWOper, delta; + + NewWOper = TotalWeightedOperation(); + delta = NewWOper - wmops[currCounter].LastWOper; + wmops[currCounter].LastWOper = NewWOper; + + return ( delta ); +} + +/* Resets the current BASOP WMOPS counter */ +void Reset_BASOP_WMOPS_counter( void ) +{ + int i; + long *ptr; + + /* clear the current BASOP operation counter before new frame begins */ + ptr = (long *) &multiCounter[currCounter]; + for ( i = 0; i < (int) ( sizeof( multiCounter[currCounter] ) / sizeof( long ) ); i++ ) + { + *ptr++ = 0; + } + + wmops[currCounter].LastWOper = 0; + + return; +} + +#endif + diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index 767a02d..be056e9 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.h +++ b/src/wmc_tool/test_data/ref/wmc_auto.h @@ -29,12 +29,15 @@ #pragma GCC system_header #endif +#ifndef INT_MAX +#define INT_MAX 32767 +#endif + /* Real-time relationships */ #define FRAMES_PER_SECOND 50.0 #define WMOPS_BOOST_FAC ( 1.0f ) /* scaling factor for equalizing the difference between automatic and manual instrumentation */ #define FAC ( FRAMES_PER_SECOND / 1e6 * WMOPS_BOOST_FAC ) - #ifdef WMOPS enum instructions { @@ -560,7 +563,6 @@ enum instructions extern double ops_cnt; extern double prom_cnt; extern double inst_cnt[NUM_INST]; -extern int ops_cnt_activ; void reset_wmops( void ); void push_wmops( const char *label ); @@ -1035,5 +1037,405 @@ void reset_stack( void ); #endif + +/* Global counter variable for calculation of complexity weight */ +typedef struct +{ + unsigned int add; /* Complexity Weight of 1 */ + unsigned int sub; /* Complexity Weight of 1 */ + unsigned int abs_s; /* Complexity Weight of 1 */ + unsigned int shl; /* Complexity Weight of 1 */ + unsigned int shr; /* Complexity Weight of 1 */ + + unsigned int extract_h; /* Complexity Weight of 1 */ + unsigned int extract_l; /* Complexity Weight of 1 */ + unsigned int mult; /* Complexity Weight of 1 */ + unsigned int L_mult; /* Complexity Weight of 1 */ + unsigned int negate; /* Complexity Weight of 1 */ + + unsigned int round; /* Complexity Weight of 1 */ + unsigned int L_mac; /* Complexity Weight of 1 */ + unsigned int L_msu; /* Complexity Weight of 1 */ + unsigned int L_macNs; /* Complexity Weight of 1 */ + unsigned int L_msuNs; /* Complexity Weight of 1 */ + + unsigned int L_add; /* Complexity Weight of 1 */ + unsigned int L_sub; /* Complexity Weight of 1 */ + unsigned int L_add_c; /* Complexity Weight of 2 */ + unsigned int L_sub_c; /* Complexity Weight of 2 */ + unsigned int L_negate; /* Complexity Weight of 1 */ + + unsigned int L_shl; /* Complexity Weight of 1 */ + unsigned int L_shr; /* Complexity Weight of 1 */ + unsigned int mult_r; /* Complexity Weight of 1 */ + unsigned int shr_r; /* Complexity Weight of 3 */ + unsigned int mac_r; /* Complexity Weight of 1 */ + + unsigned int msu_r; /* Complexity Weight of 1 */ + unsigned int L_deposit_h; /* Complexity Weight of 1 */ + unsigned int L_deposit_l; /* Complexity Weight of 1 */ + unsigned int L_shr_r; /* Complexity Weight of 3 */ + unsigned int L_abs; /* Complexity Weight of 1 */ + + unsigned int L_sat; /* Complexity Weight of 4 */ + unsigned int norm_s; /* Complexity Weight of 1 */ + unsigned int div_s; /* Complexity Weight of 18 */ + unsigned int norm_l; /* Complexity Weight of 1 */ + unsigned int move16; /* Complexity Weight of 1 */ + + unsigned int move32; /* Complexity Weight of 2 */ + unsigned int Logic16; /* Complexity Weight of 1 */ + unsigned int Logic32; /* Complexity Weight of 2 */ + unsigned int Test; /* Complexity Weight of 2 */ + unsigned int s_max; /* Complexity Weight of 1 */ + + unsigned int s_min; /* Complexity Weight of 1 */ + unsigned int L_max; /* Complexity Weight of 1 */ + unsigned int L_min; /* Complexity Weight of 1 */ + unsigned int L40_max; /* Complexity Weight of 1 */ + unsigned int L40_min; /* Complexity Weight of 1 */ + + unsigned int shl_r; /* Complexity Weight of 3 */ + unsigned int L_shl_r; /* Complexity Weight of 3 */ + unsigned int L40_shr_r; /* Complexity Weight of 3 */ + unsigned int L40_shl_r; /* Complexity Weight of 3 */ + unsigned int norm_L40; /* Complexity Weight of 1 */ + + unsigned int L40_shl; /* Complexity Weight of 1 */ + unsigned int L40_shr; /* Complexity Weight of 1 */ + unsigned int L40_negate; /* Complexity Weight of 1 */ + unsigned int L40_add; /* Complexity Weight of 1 */ + unsigned int L40_sub; /* Complexity Weight of 1 */ + + unsigned int L40_abs; /* Complexity Weight of 1 */ + unsigned int L40_mult; /* Complexity Weight of 1 */ + unsigned int L40_mac; /* Complexity Weight of 1 */ + unsigned int mac_r40; /* Complexity Weight of 2 */ + + unsigned int L40_msu; /* Complexity Weight of 1 */ + unsigned int msu_r40; /* Complexity Weight of 2 */ + unsigned int Mpy_32_16_ss; /* Complexity Weight of 2 */ + unsigned int Mpy_32_32_ss; /* Complexity Weight of 4 */ + unsigned int L_mult0; /* Complexity Weight of 1 */ + + unsigned int L_mac0; /* Complexity Weight of 1 */ + unsigned int L_msu0; /* Complexity Weight of 1 */ + unsigned int lshl; /* Complexity Weight of 1 */ + unsigned int lshr; /* Complexity Weight of 1 */ + unsigned int L_lshl; /* Complexity Weight of 1 */ + + unsigned int L_lshr; /* Complexity Weight of 1 */ + unsigned int L40_lshl; /* Complexity Weight of 1 */ + unsigned int L40_lshr; /* Complexity Weight of 1 */ + unsigned int s_and; /* Complexity Weight of 1 */ + unsigned int s_or; /* Complexity Weight of 1 */ + + unsigned int s_xor; /* Complexity Weight of 1 */ + unsigned int L_and; /* Complexity Weight of 1 */ + unsigned int L_or; /* Complexity Weight of 1 */ + unsigned int L_xor; /* Complexity Weight of 1 */ + unsigned int rotl; /* Complexity Weight of 3 */ + + unsigned int rotr; /* Complexity Weight of 3 */ + unsigned int L_rotl; /* Complexity Weight of 3 */ + unsigned int L_rotr; /* Complexity Weight of 3 */ + unsigned int L40_set; /* Complexity Weight of 3 */ + unsigned int L40_deposit_h; /* Complexity Weight of 1 */ + + unsigned int L40_deposit_l; /* Complexity Weight of 1 */ + unsigned int L40_deposit32; /* Complexity Weight of 1 */ + unsigned int Extract40_H; /* Complexity Weight of 1 */ + unsigned int Extract40_L; /* Complexity Weight of 1 */ + unsigned int L_Extract40; /* Complexity Weight of 1 */ + + unsigned int L40_round; /* Complexity Weight of 1 */ + unsigned int L_saturate40; /* Complexity Weight of 1 */ + unsigned int round40; /* Complexity Weight of 1 */ + unsigned int If; /* Complexity Weight of 4 */ + unsigned int Goto; /* Complexity Weight of 4 */ + + unsigned int Break; /* Complexity Weight of 4 */ + unsigned int Switch; /* Complexity Weight of 8 */ + unsigned int For; /* Complexity Weight of 3 */ + unsigned int While; /* Complexity Weight of 4 */ + unsigned int Continue; /* Complexity Weight of 4 */ + + unsigned int L_mls; /* Complexity Weight of 6 */ + unsigned int div_l; /* Complexity Weight of 32 */ + unsigned int i_mult; /* Complexity Weight of 3 */ +} BASIC_OP; + +#ifdef WMOPS +extern BASIC_OP *multiCounter; +extern int currCounter; + +/* Technical note : + * The following 3 variables are only used for correct complexity + * evaluation of the following structure : + * IF{ + * ... + * } ELSE IF { + * ... + * } ELSE IF { + * ... + * } + * ... + * } ELSE { + * ... + * } + */ +extern int funcId_where_last_call_to_else_occurred; +extern long funcid_total_wmops_at_last_call_to_else; +extern int call_occurred; + +extern long TotalWeightedOperation( void ); +long DeltaWeightedOperation(); + +void Set_BASOP_WMOPS_counter( int counterId ); +void Reset_BASOP_WMOPS_counter( void ); + +#endif + +/***************************************************************************** + * + * Function Name : FOR + * + * Purpose : + * + * The macro FOR should be used instead of the 'for' C statement. + * The complexity is independent of the number of loop iterations that are + * performed. + * + * Complexity weight : 3 (regardless of number of iterations). + * + *****************************************************************************/ +#ifndef WMOPS +#define FOR( a) for( a) + +#else +#define FOR( a) if( incrFor(), 0); else for( a) + +static __inline void incrFor( void) { + multiCounter[currCounter].For++; +} +#endif + + +/***************************************************************************** + * + * Function Name : WHILE + * + * Purpose : + * + * The macro WHILE should be used instead of the 'while' C statement. + * The complexity is proportional to the number of loop iterations that + * are performed. + * + * Complexity weight : 4 x 'number of loop iterations'. + * + *****************************************************************************/ +#ifndef WMOPS +#define WHILE( a) while( a) + +#else +#define WHILE( a) while( incrWhile(), a) + +static __inline void incrWhile( void) { + multiCounter[currCounter].While++; +} +#endif + + +/***************************************************************************** + * + * Function Name : DO + * + * Purpose : + * + * The macro DO should be used instead of the 'do' C statement. + * + * Complexity weight : 0 (complexity counted by WHILE macro). + * + *****************************************************************************/ +#ifndef WMOPS +#define DO do + +#else +#define DO do + +#endif + + +/***************************************************************************** + * + * Function Name : IF + * + * Purpose : + * + * The macro IF should : + * + * - not be used when : + * - the 'if' structure does not have any 'else if' nor 'else' statement + * - and it conditions only one DSP basic operations. + * + * - be used instead of the 'if' C statement in every other case : + * - when there is an 'else' or 'else if' statement, + * - or when the 'if' conditions several DSP basic operations, + * - or when the 'if' conditions a function call. + * + * Complexity weight : 4 + * + *****************************************************************************/ +#ifndef WMOPS +#define IF( a) if( a) + +#else +#define IF( a) if( incrIf(), a) + +static __inline void incrIf( void) { + /* Technical note : + * If the "IF" operator comes just after an "ELSE", its counter + * must not be incremented. + */ + if ( ( currCounter != funcId_where_last_call_to_else_occurred ) || ( TotalWeightedOperation() != funcid_total_wmops_at_last_call_to_else ) || ( call_occurred == 1 ) ) + { + multiCounter[currCounter].If++; + } + + call_occurred = 0; + funcId_where_last_call_to_else_occurred = INT_MAX; +} +#endif + + +/***************************************************************************** + * + * Function Name : ELSE + * + * Purpose : + * + * The macro ELSE should be used instead of the 'else' C statement. + * + * Complexity weight : 4 + * + *****************************************************************************/ +#ifndef WMOPS +#define ELSE else + +#else +#define ELSE else if( incrElse(), 0) ; else + +static __inline void incrElse( void) { + multiCounter[currCounter].If++; + + /* We keep track of the funcId of the last function + * which used ELSE {...} structure. + */ + funcId_where_last_call_to_else_occurred = currCounter; + + /* We keep track of the number of WMOPS of this funcId + * when the ELSE macro was called. + */ + funcid_total_wmops_at_last_call_to_else = TotalWeightedOperation(); + + /* call_occurred is set to 0, in order to count the next IF (if necessary) + */ + call_occurred = 0; +} +#endif + + +/***************************************************************************** + * + * Function Name : SWITCH + * + * Purpose : + * + * The macro SWITCH should be used instead of the 'switch' C statement. + * + * Complexity weight : 8 + * + *****************************************************************************/ +#ifndef WMOPS +#define SWITCH( a) switch( a) + +#else +#define SWITCH( a) switch( incrSwitch(), a) + +static __inline void incrSwitch( void) { + multiCounter[currCounter].Switch++; +} +#endif + + +/***************************************************************************** + * + * Function Name : CONTINUE + * + * Purpose : + * + * The macro CONTINUE should be used instead of the 'continue' C statement. + * + * Complexity weight : 4 + * + *****************************************************************************/ +#ifndef WMOPS +#define CONTINUE continue + +#else +#define CONTINUE if( incrContinue(), 0); else continue + +static __inline void incrContinue( void) { + multiCounter[currCounter].Continue++; +} +#endif + + +/***************************************************************************** + * + * Function Name : BREAK + * + * Purpose : + * + * The macro BREAK should be used instead of the 'break' C statement. + * + * Complexity weight : 4 + * + *****************************************************************************/ +#ifndef WMOPS +#define BREAK break + +#else +#define BREAK if( incrBreak(), 0) break; else break + +static __inline void incrBreak( void) { + multiCounter[currCounter].Break++; +} +#endif + + +/***************************************************************************** + * + * Function Name : GOTO + * + * Purpose : + * + * The macro GOTO should be used instead of the 'goto' C statement. + * + * Complexity weight : 4 + * + *****************************************************************************/ +#ifndef WMOPS +#define GOTO goto + +#else +#define GOTO if( incrGoto(), 0); else goto + +static __inline void incrGoto( void) { + multiCounter[currCounter].Goto++; +} +#endif + #endif /* WMOPS_H */ + From 27df890fcbe6a0f9a71a0e5d67200abe70c717d9 Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 27 Sep 2023 09:34:52 +0200 Subject: [PATCH 26/67] unifiy macros and functions under WMOPS_FUNCTS_STRING --- src/wmc_tool/c_parser.cpp | 42 ++++++++++----------------------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index a37863e..c1975c7 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -110,29 +110,13 @@ MANUAL_COUNTING_MACROS_STRING \ AUTO_COUNTING_MACROS_STRING -#define WMOPS_COUNTLIB_FUNCTS_STRING \ - "reset_wmops push_wmops pop_wmops update_wmops print_wmops " -#define OTHER_COUNTLIB_FUNCTS_STRING \ - "Dyn_Mem_Init Dyn_Mem_Exit Dyn_Mem_Exit_noprint " \ - "Dyn_Mem_In Dyn_Mem_Add Dyn_Mem_Out " \ - "Sta_Mem_Init Sta_Mem_Exit Sta_Mem_Exit_noprint Sta_Mem_Add " \ - "P_Dyn_Mem_Init P_Dyn_Mem_Exit P_Dyn_Mem_Exit_noprint " \ - "P_Dyn_Mem_In P_Dyn_Mem_Add P_Dyn_Mem_Out " \ - "P_Sta_Mem_Init P_Sta_Mem_Exit P_Sta_Mem_Exit_noprint P_Sta_Mem_Add " \ - "DYN_MEM_IN DYN_MEM_ADD DYN_MEM_OUT " -#define COUNTLIB_FUNCTS_STRING \ - WMOPS_COUNTLIB_FUNCTS_STRING \ - OTHER_COUNTLIB_FUNCTS_STRING +#define WMOPS_FUNCTS_STRING \ + "reset_wmops push_wmops pop_wmops update_wmops print_wmops print_mem " \ + "rsize Get_Const_Data_Size Print_Const_Data_Size " #define COUNTING_CODE_STRING \ COUNTING_MACROS_STRING \ - COUNTLIB_FUNCTS_STRING - -#define TOOL_FUNCTS_STRING \ - "rsize " \ - "Get_Const_Data_Size " \ - "Print_Const_Data_Size " \ - "print_mem " + WMOPS_FUNCTS_STRING #define SYSTEM_ALLOC_FUNCTS_STRING \ "malloc calloc free " @@ -4204,12 +4188,12 @@ static Item_Type Get_Call_Type( return ITEM_FUNC_COUNTERS_AUTO_R | ITEM_INSTRUMENTATION | ITEM_SKIPPED; } /* Any of the Counting Library Functions? */ - if ( memwordcmp( name_start, COUNTLIB_FUNCTS_STRING ) != NULL ) - { /* Yes */ - return ITEM_FUNC_COUNT_LIB | ITEM_SKIPPED; - } - /* Any of the ROM Counting Macros? */ - if ( memwordcmp( name_start, TOOL_FUNCTS_STRING ) != NULL ) + //if ( memwordcmp( name_start, COUNTLIB_FUNCTS_STRING ) != NULL ) + //{ /* Yes */ + // return ITEM_FUNC_COUNT_LIB | ITEM_SKIPPED; + //} + /* Any of the WMOPS Library Functions or Macros? */ + if ( memwordcmp( name_start, WMOPS_FUNCTS_STRING) != NULL ) { /* Yes */ return ITEM_FUNC_COUNT_LIB | ITEM_SKIPPED; } @@ -8714,11 +8698,7 @@ void Print_Information( void ) fprintf(stdout, "\n Manual Macros Removed during Desintrumentation:\n" ); Print_Words( MANUAL_COUNTING_MACROS_STRING ); fprintf(stdout, "\n WMOPS Library Functions that are not Instrumented:\n" ); - Print_Words( WMOPS_COUNTLIB_FUNCTS_STRING, true ); - fprintf(stdout, "\n Other Counting Functions that are not Instrumented:\n" ); - Print_Words( OTHER_COUNTLIB_FUNCTS_STRING ); - fprintf(stdout, "\n WMC_Tool Functions that are not Instrumented:\n" ); - Print_Words( TOOL_FUNCTS_STRING, true ); + Print_Words( WMOPS_FUNCTS_STRING, true ); fprintf(stdout, "\n System Functions that are not Instrumented:\n" ); Print_Words( SYSTEM_FUNCTS_STRING ); fprintf(stdout, "\n System Functions that are Instrumented:\n" ); From 88ab429cc76a7720759dbeed87452b42216d9782 Mon Sep 17 00:00:00 2001 From: malenov Date: Mon, 2 Oct 2023 14:54:08 +0200 Subject: [PATCH 27/67] count PROM size of BASOP functions and operators --- src/wmc_tool/c_parser.cpp | 135 +++++++++++++++++++++++++----------- src/wmc_tool/constants.h | 3 +- src/wmc_tool/parsing_defs.h | 1 + 3 files changed, 96 insertions(+), 43 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index c1975c7..bfbf24c 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -148,6 +148,18 @@ "set_min set_max " \ "mac msu " +#define BASOP_FUNCTS_STRING \ + "add sub abs_s shl shr extract_h extract_l mult L_mult negate round " \ + "L_mac L_msu L_macNs L_msuNs L_add L_sub L_add_c L_sub_c L_negate L_shl L_shr " \ + "mult_r shr_r mac_r msu_r L_deposit_h L_deposit_l L_shr_r L_abs L_sat norm_s div_s " \ + "norm_l move16 move32 Logic16 Logic32 Test s_max s_min L_max L_min L40_max " \ + "L40_min shl_r L_shl_r L40_shr_r L40_shl_r norm_L40 L40_shl L40_shr L40_negate " \ + "L40_add L40_sub L40_abs L40_mult L40_mac mac_r40 L40_msu msu_r40 Mpy_32_16_ss " \ + "Mpy_32_32_ss L_mult0 L_mac0 L_msu0 lshl lshr L_lshl L_lshr L40_lshl L40_lshr " \ + "s_and s_or s_xor L_and L_or L_xor rotl rotr L_rotl L_rotr L40_set L40_deposit_h " \ + "L40_deposit_l L40_deposit32 Extract40_H Extract40_L L_Extract40 L40_round " \ + "L_saturate40 round40 If Goto Break Switch For While Continue L_mls div_l i_mult " + #define WMOPS_LIB_INCLUDE_STRING \ "wmc_auto.h" @@ -180,15 +192,6 @@ #define RETURN_KW_STRING "return" -/***************************************** - * Fixed Point Macros Lacking a ';' - *****************************************/ - -#define NON_STANDARD_FXP_MACROS_STRING \ - "BASOP_SATURATE_WARNING_ON " \ - "BASOP_SATURATE_WARNING_OFF " \ - "BASOP_SATURATE_ERROR_ON " \ - "BASOP_SATURATE_ERROR_OFF " /*-------------------------------------------------------------------* * Local Typedefs @@ -2501,6 +2504,9 @@ static TOOL_ERROR Find_Keywords( { /* Yes */ /* Try Uppercase Version */ for (ns = kw_name; *ns != NUL_CHAR; *ns = toupper(*ns), ns++); + + /* Uppercase version is recognized as BASOP operation -> do not instrument */ + item_type = ITEM_INSTRUMENTATION_OFF; } else if (run == 2) { @@ -2572,6 +2578,7 @@ static TOOL_ERROR Find_Keywords( { /* Set Name End */ ne = ns + kw_name_len; + /* Add Keyword Region */ if ( ( ErrCode = Add_Region( ParseTbl_ptr, item_type + /* Keywords that Compute to Constants are stripped of KW Attribute. */ @@ -2661,8 +2668,7 @@ static TOOL_ERROR Find_Keywords( dp = pe; } /* Skip Blanks to the Left (this cannot fail) */ - pe = Skip_Chars( pe - 1, BLANK_CHARS, ParseTbl_ptr, - ITEM_ANY, ITEM_MOVED_OVER, BACKWARDS ); + pe = Skip_Chars( pe - 1, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_MOVED_OVER, BACKWARDS ); } /* Keyword Name has a Delimiter? */ if ( keywords[i].kw_delim != NUL_CHAR ) @@ -2728,15 +2734,17 @@ static TOOL_ERROR Find_Keywords( } /* Add Keyword Expression Region */ - if ( ( ErrCode = Add_Region( ParseTbl_ptr, + /* !!! VM: added ITEM_INSTRUMENTATION_OFF to mark a non-instrumented BASOP keyword expression region !!! */ + if ( ( ErrCode = Add_Region( ParseTbl_ptr, (item_type == ITEM_INSTRUMENTATION_OFF ? ITEM_INSTRUMENTATION_OFF : 0) + /* Keywords Expressions that Compute to Constants are stripped of KW_EXPR Attribute */ /* Added because when 'sizeof' is marked as a KW Expresion, instrumentation of something */ /* like 'sizeof(float) * 2' would be instrumented between the ')' and the '2'.*/ - ( ( keywords[i].kw_type & ITEM_CONSTANT ) ? 0 : ITEM_KW_EXPR ) | keywords[i].expr_type, ps, pe + 1 ) ) != NO_ERR ) + (( ( keywords[i].kw_type & ITEM_CONSTANT ) ? 0 : ITEM_KW_EXPR ) | keywords[i].expr_type), ps, pe + 1 ) ) != NO_ERR ) { goto ret; } } + /* Continue after Arguments or Value End */ ne = pe + 1; } @@ -3130,12 +3138,6 @@ static TOOL_ERROR Find_Data_Declarations( /* Skip Blanks to the Right */ ptr = Skip_Chars( start, BLANK_CHARS, ParseTbl_ptr ); } - /* Fixed Point Macros Lacking ';'? */ - if ( ( start = memwordcmp( ptr, NON_STANDARD_FXP_MACROS_STRING ) ) != NULL ) - { /* Yes */ - /* Done */ - break; - } /* Any of the Known Data Types, Type Definition Type Modifier or Storage Class? */ if ( ( start = memwordcmp( ptr, DATA_DEF_STRING ) ) != NULL ) @@ -3342,6 +3344,7 @@ static TOOL_ERROR Find_Data_Declarations( /* Done */ break; } + /* Go to End of Statement */ /* !!!!! Incorrect when have 'int a' then 'BRANCH(1)', 'a += 2', ... on Next Line (Known Limitation)*/ if ( ( start = Goto_EOS( start, ParseTbl_ptr ) ) == NULL ) @@ -3351,11 +3354,14 @@ static TOOL_ERROR Find_Data_Declarations( ErrCode = Expected_EOS( ptr ); goto ret; } + /* Skip Blanks to the Right */ ptr = Skip_Chars( start + 1, BLANK_CHARS, ParseTbl_ptr ); } + /* Set Region End */ ParseRecord.item_end = ptr; + /* Is Region Empty? */ if ( !Is_Empty_Region( ParseRecord.item_start, ptr, ParseTbl_ptr ) ) { @@ -3365,8 +3371,10 @@ static TOOL_ERROR Find_Data_Declarations( goto ret; } } + /* Change Data Declaration Region Type */ ParseRecord.item_type = ITEM_DATA_DECL_SUB | ITEM_WARNING; + /* Go to Next Code Block */ start = Find_String( ptr, "{", ParseTbl_ptr, ITEM_ANY ); } while ( start != NULL && start < end ); @@ -4146,16 +4154,19 @@ static Item_Type Get_Call_Type( /* Not a Function Call */ return ITEM_NONE; } + /* Any of the System Functions? */ if ( memwordcmp( name_start, SYSTEM_FUNCTS_STRING ) != NULL ) { /* Yes */ return ITEM_FUNC_SYSTEM | ITEM_SKIPPED; } + /* Any of the System Allocation Functions? */ if ( memwordcmp( name_start, SYSTEM_ALLOC_FUNCTS_STRING ) != NULL ) { /* Yes */ return ITEM_FUNC_SYSTEM; } + /* Any of the Instrumented System Allocation Functions? */ if ( memwordcmp( name_start, ins_sys_alloc_funcs_string ) != NULL ) { /* Yes */ @@ -4167,36 +4178,43 @@ static Item_Type Get_Call_Type( { /* Yes */ return ITEM_FUNC_MATH; } + /* Any of the Instrumented Math Functions? */ if ( memwordcmp( name_start, ins_math_funcs_string ) != NULL ) { /* Yes */ return ITEM_FUNC_MATH | ITEM_INSTRUMENTED; } + /* Any of the Manual Counting Macros? */ if ( memwordcmp( name_start, MANUAL_COUNTING_MACROS_STRING ) != NULL ) { /* Yes */ return ITEM_FUNC_COUNTERS_MAN | ITEM_INSTRUMENTATION | ITEM_SKIPPED; } + /* Any of the Left Automatic Counting Macros? */ if ( memwordcmp( name_start, AUTO_LEFT_COUNTING_MACRO_STRING ) != NULL ) { /* Yes */ return ITEM_FUNC_COUNTERS_AUTO_L | ITEM_INSTRUMENTATION | ITEM_SKIPPED; } + /* Any of the Right Automatic Counting Macros? */ if ( memwordcmp( name_start, AUTO_RIGHT_COUNTING_MACRO_STRING ) != NULL ) { /* Yes */ return ITEM_FUNC_COUNTERS_AUTO_R | ITEM_INSTRUMENTATION | ITEM_SKIPPED; } - /* Any of the Counting Library Functions? */ - //if ( memwordcmp( name_start, COUNTLIB_FUNCTS_STRING ) != NULL ) - //{ /* Yes */ - // return ITEM_FUNC_COUNT_LIB | ITEM_SKIPPED; - //} + /* Any of the WMOPS Library Functions or Macros? */ if ( memwordcmp( name_start, WMOPS_FUNCTS_STRING) != NULL ) { /* Yes */ return ITEM_FUNC_COUNT_LIB | ITEM_SKIPPED; } + + /* Any of the BASOP Functions or Macros? */ + if (memwordcmp(name_start, BASOP_FUNCTS_STRING) != NULL) + { /* Yes */ + return ITEM_FUNC_BASOP | ITEM_INSTRUMENTATION_OFF; + } + return ITEM_FUNC_PROJECT; } @@ -4328,8 +4346,8 @@ static TOOL_ERROR Find_Calls( { goto ret; } - /* Counting Macro or Function? */ - if ( item_type & ( ITEM_FUNC_COUNTERS | ITEM_FUNC_COUNT_LIB ) ) + /* Counting Macro, Couting Function or BASOP Function? */ + if ( item_type & ( ITEM_FUNC_COUNTERS | ITEM_FUNC_COUNT_LIB | ITEM_FUNC_BASOP ) ) { /* Yes */ /* Get Optional End of Statement @@ -4670,6 +4688,7 @@ static TOOL_ERROR Instrument_Keywords( /* Get Parse Table Address (for clarity) */ ParseTbl_ptr = &ParseCtx_ptr->ParseTbl; + /* Get PROM Ops Weights (for clarity) */ prom_ops_weights_ptr = &PROM_Ops_Weights[ParseCtx_ptr->PROMOpsWeightsSet]; @@ -4695,8 +4714,8 @@ static TOOL_ERROR Instrument_Keywords( { /* No */ /* Instrument After (by default) */ ptr = ParseRec_ptr->item_end; - /* Is it a 'while' that is part of a 'do' Block? */ + /* Is it a 'while' that is part of a 'do' Block? */ /* Insert Instrumentation Character */ if ( ( ErrCode = Add_Insertion( &ParseCtx_ptr->InsertTbl, ptr, WORD_INSTRUMENT_STRING ) ) != NO_ERR ) { @@ -4725,12 +4744,14 @@ static TOOL_ERROR Instrument_Keywords( { goto ret; } + if ( ( ErrCode = Add_Insertion( &ParseCtx_ptr->InsertTbl, ParseRec_ptr->item_end, ")" ) ) != NO_ERR ) { goto ret; } + /* Add Warning */ ParseRec_ptr->item_type |= ITEM_WARNING; } @@ -4746,14 +4767,22 @@ static TOOL_ERROR Instrument_Keywords( } } - /* Count Program Memory */ - if ( item_type == ITEM_KEYWORD_FOR ) - loops++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->loop; - else if ( item_type == ITEM_KEYWORD_WHILE ) - whiles++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->branch * 2; - else if ( item_type & ( ITEM_KEYWORD_CONTROL | ITEM_KEYWORD_IS_JUMP ) ) - jumps++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->branch; + ///* Count Program Memory */ + //if ( item_type == ITEM_KEYWORD_FOR ) + // loops++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->loop; + //else if ( item_type == ITEM_KEYWORD_WHILE ) + // whiles++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->branch * 2; + //else if ( item_type & ( ITEM_KEYWORD_CONTROL | ITEM_KEYWORD_IS_JUMP ) ) + // jumps++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->branch; } + + /* Count Program Memory */ /* !!! VM: Moved to this place to count PROM size even for non-instrumented keywords */ + if ( item_type == ITEM_KEYWORD_FOR ) + loops++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->loop; + else if ( item_type == ITEM_KEYWORD_WHILE ) + whiles++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->branch * 2; + else if ( item_type & ( ITEM_KEYWORD_CONTROL | ITEM_KEYWORD_IS_JUMP ) ) + jumps++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->branch; } } @@ -5411,11 +5440,13 @@ static TOOL_ERROR Instrument_Operators( /* Erase Operator Insert Table */ OperInsTbl.Size = 0; + /* Initialize (No Memory Allocated by Default) */ OperInsTbl.MaxSize = 0; /* Get Parse Table Address (for clarity) */ ParseTbl_ptr = &ParseCtx_ptr->ParseTbl; + /* Get PROM Ops Weights (for clarity) */ prom_ops_weights_ptr = &PROM_Ops_Weights[ParseCtx_ptr->PROMOpsWeightsSet]; @@ -6408,17 +6439,19 @@ TOOL_ERROR Setup_Regions( goto ret; } - /* Find Skipped Regions */ + /* Find Non-Instrumented Regions marked with #ifdef WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP */ /* Start at Beginning */ ptr = ParseCtx_ptr->File.Data; - /* Find the Beginning of Skipped Regions */ + /* Find the Beginning of Non-Instrumented Regions */ while ( ( ptr = Find_Identifier( ptr, WMC_TOOL_SKIP_STRING, ParseTbl_ptr, ITEM_CSTE_NAME, ITEM_ENCLOSED, &idx ) ) != NULL ) { /* Get Record */ ParseRec_ptr = &ParseTbl_ptr->Data[idx]; + /* Go to Start of Next Line */ ptr = strlend( ParseRec_ptr->item_end ) + 1; - /* Find the End of Skipped Regions */ + + /* Find the End of Non-Instrumented Regions */ /* Found it? */ if ( ( end = Find_Identifier( ptr, WMC_TOOL_SKIP_STRING, ParseTbl_ptr, ITEM_PREPROC_ARGS | ITEM_PREPROC_UNDEF, ITEM_ENCLOSED, &idx ) ) == NULL ) @@ -6429,16 +6462,18 @@ TOOL_ERROR Setup_Regions( Error("Unable to find matching #undef %s!", ErrCode, WMC_TOOL_SKIP_STRING); goto ret; - /* Skipped Regon will End at EOF */ + /* Skipped Region will End at EOF */ //end = file_ptr->Data + file_ptr->Size; } else { /* Yes */ /* Go to Preprocessor Command */ idx--; + /* Get Record */ ParseRec_ptr = &ParseTbl_ptr->Data[idx]; - /* Skipped Region will End before #undef */ + + /* Non-Instrumented Region will End before #undef */ end = ParseRec_ptr->item_start; } @@ -6475,8 +6510,10 @@ TOOL_ERROR Setup_Regions( { /* Get Record */ ParseRec_ptr = &ParseTbl_ptr->Data[idx]; + /* Mark Comment as Instrumentation */ ParseRec_ptr->item_type |= ITEM_INSTRUMENTATION; + /* continue After Comment */ ptr = ParseRec_ptr->item_end; } @@ -8141,7 +8178,7 @@ TOOL_ERROR Instrument( is_function_present = 1; } - /* Check, if there are const xx[] arrays */ + /* Check, if there are any const xx[] arrays */ is_cnst_data_present = 0; if ((Find_Identifier(ParseCtx_ptr->File.Data, CONST_STRING, ParseTbl_ptr, ITEM_ANY, ITEM_FUNC_DEF | ITEM_NOT_SEARCHED | ITEM_INSTRUMENTATION_OFF)) != NULL) { @@ -8168,10 +8205,13 @@ TOOL_ERROR Instrument( /* Reset Max Function Name Length */ max_name_length = 0; + /* Reset # of Occurances */ max_name_occ = 0; + /* Start at Beginning */ FctCallRec_ptr = FctCallTbl_ptr->Data; + /* Process all Project Function Calls */ for (idx = 0; idx < FctCallTbl_ptr->Size; idx++) { @@ -8179,10 +8219,12 @@ TOOL_ERROR Instrument( name_length = FctCallRec_ptr->NameLength; if (max_name_length < name_length) max_name_length = name_length; + /* Get Max Name Occurances */ name_occ = FctCallRec_ptr->NameOcc; if (max_name_occ < name_occ) max_name_occ = name_occ; + /* Advance */ FctCallRec_ptr++; } @@ -8342,6 +8384,13 @@ TOOL_ERROR Instrument( miscs += name_occ, ParseCtx_ptr->PROMSize += name_occ * prom_ops_weights_ptr->misc; } + /* Find BASOP Functions and Count their PROM size */ + for (idx = 0; (idx = Find_Region(NULL, ParseTbl_ptr, ITEM_CALL | ITEM_FUNC_BASOP, idx)) >= 0; idx++) + { + /* By default it is assumed that all BASOP functions take one PROM word */ + ParseCtx_ptr->PROMSize++; + } + /* Insert PROM_Size_Func() function */ if (is_function_present) { @@ -8697,8 +8746,10 @@ void Print_Information( void ) fprintf(stdout, "\n Manual Macros Removed during Desintrumentation:\n" ); Print_Words( MANUAL_COUNTING_MACROS_STRING ); - fprintf(stdout, "\n WMOPS Library Functions that are not Instrumented:\n" ); - Print_Words( WMOPS_FUNCTS_STRING, true ); + fprintf(stdout, "\n BASOP Functions that are not Instrumented:\n" ); + Print_Words( BASOP_FUNCTS_STRING, true ); + fprintf(stdout, "\n WMOPS Library Functions that are not Instrumented:\n"); + Print_Words(WMOPS_FUNCTS_STRING, true); fprintf(stdout, "\n System Functions that are not Instrumented:\n" ); Print_Words( SYSTEM_FUNCTS_STRING ); fprintf(stdout, "\n System Functions that are Instrumented:\n" ); diff --git a/src/wmc_tool/constants.h b/src/wmc_tool/constants.h index 1dbd913..76812a2 100644 --- a/src/wmc_tool/constants.h +++ b/src/wmc_tool/constants.h @@ -98,7 +98,8 @@ "Encoder_State " #define CONST_STRING "const" #define STORAGE_STRING "extern " \ - "static " CONST_STRING " " + "static " \ + "const " #define DATA_DEF_STRING TYPES_STRING TYPE_MOD_STRING TYPEDEF_STRING STORAGE_STRING diff --git a/src/wmc_tool/parsing_defs.h b/src/wmc_tool/parsing_defs.h index ec2532d..9994914 100644 --- a/src/wmc_tool/parsing_defs.h +++ b/src/wmc_tool/parsing_defs.h @@ -188,6 +188,7 @@ #define ITEM_FUNC_COUNTERS_MAN 0x01 #define ITEM_FUNC_COUNTERS ( ITEM_FUNC_COUNTERS_MAN | ITEM_FUNC_COUNTERS_AUTO ) #define ITEM_FUNC_COUNT_LIB 0x20 +#define ITEM_FUNC_BASOP 0x10 #define ITEM_FUNC_SYSTEM 0x40 /* Attributes for ITEM_SKIPPED */ From 8ec35826137fb01f1573f268dc9267826c1409f2 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 3 Oct 2023 08:00:53 +0200 Subject: [PATCH 28/67] small correction in the help printout --- src/wmc_tool/wmc_tool.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wmc_tool/wmc_tool.cpp b/src/wmc_tool/wmc_tool.cpp index 0fbc89b..ee3285c 100644 --- a/src/wmc_tool/wmc_tool.cpp +++ b/src/wmc_tool/wmc_tool.cpp @@ -69,10 +69,10 @@ static void usage() { - Print("Usage: wmc_tool [options] filename1 filename2 ...\n\n" - "WMC tool v%s - %s\n\n" + Print("WMC tool v%s - %s\n\n" + "Usage: wmc_tool [options] filename1 filename2 ...\n\n" "Mandatory arguments:\n" - " space-separated list of filenames or directories with file mask, e.g. ./lib_enc/array*.c\n" + " space-separated list of filenames or directories with file mask, e.g. ./lib_enc/array*.c my_dir/sub_dir/*.c\n" " note: if file mask is not specified *.c is assumed by default\n\n" "Options:\n" " -h [--help]: print help\n" @@ -82,7 +82,7 @@ static void usage() " -m filename [--rom filename]: add statistics about ROM and RAM consumption\n" " note: filename shall point to a .c file containing the print_mem() function\n" " -b [--no-backup]: no backup of original files\n" - " -c dirname [--generate-wmc-files dirname]: copy wmc_auto.h and wmc_auto.c to a user-specified directory\n", + " -c dirname [--generate-wmc-files dirname]: copy wmc_auto.h and wmc_auto.c to a user-specified directory\n" " -f value [--frames-per-second value]: set the number of frames per second (default 50.0)\n\n", WMC_TOOL_VERSION_NO, VERSION_STL); From 8c650422af9c373718fb4deea60c14d5be940dac Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 3 Oct 2023 08:43:29 +0200 Subject: [PATCH 29/67] fix warning about incorrect function declaration (missing void keyword) --- src/wmc_tool/wmc_auto_c.txt | 2 +- src/wmc_tool/wmc_auto_h.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wmc_tool/wmc_auto_c.txt b/src/wmc_tool/wmc_auto_c.txt index 6265940..4862418 100644 --- a/src/wmc_tool/wmc_auto_c.txt +++ b/src/wmc_tool/wmc_auto_c.txt @@ -2113,7 +2113,7 @@ " return ( (long) tot );\r\n" "}\r\n" "\r\n" -"long DeltaWeightedOperation()\r\n" +"long DeltaWeightedOperation( void )\r\n" "{\r\n" " long NewWOper, delta;\r\n" "\r\n" diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index ccbaca4..3957924 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -1189,7 +1189,7 @@ "extern int call_occurred;\r\n" "\r\n" "extern long TotalWeightedOperation( void );\r\n" -"long DeltaWeightedOperation();\r\n" +"long DeltaWeightedOperation( void );\r\n" "\r\n" "void Set_BASOP_WMOPS_counter( int counterId );\r\n" "void Reset_BASOP_WMOPS_counter( void );\r\n" From a9678869ba410672787f58e2e5a62a1b772d9232 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 3 Oct 2023 10:11:25 +0200 Subject: [PATCH 30/67] fix incorrect reading of PROM size from .c files containing digits in their names --- src/wmc_tool/text_utils.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/wmc_tool/text_utils.cpp b/src/wmc_tool/text_utils.cpp index b7d5596..076669d 100644 --- a/src/wmc_tool/text_utils.cpp +++ b/src/wmc_tool/text_utils.cpp @@ -556,9 +556,18 @@ int Extract_Value_From_File( { if ((ptr = strstr(line, line_keyword)) != NULL) { - while (!isdigit(*ptr++)); + /* skip the keyword */ + ptr += strlen(line_keyword); + + /* search for space followed by a number */ + while (!(isspace(ptr[0]) && isdigit(ptr[1]))) + { + ptr++; + } + fclose(fp); - return strtol(--ptr, &ptr2, 10); + + return strtol(ptr, &ptr2, 10); } } From d2353a346b5ee401f053942e66106cb9f1423326 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 3 Oct 2023 11:39:56 +0200 Subject: [PATCH 31/67] do not count PROM in skipped regions --- src/wmc_tool/c_parser.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index bfbf24c..bc11af0 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -4767,7 +4767,7 @@ static TOOL_ERROR Instrument_Keywords( } } - ///* Count Program Memory */ + /* Count Program Memory */ //if ( item_type == ITEM_KEYWORD_FOR ) // loops++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->loop; //else if ( item_type == ITEM_KEYWORD_WHILE ) @@ -4777,12 +4777,15 @@ static TOOL_ERROR Instrument_Keywords( } /* Count Program Memory */ /* !!! VM: Moved to this place to count PROM size even for non-instrumented keywords */ - if ( item_type == ITEM_KEYWORD_FOR ) - loops++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->loop; - else if ( item_type == ITEM_KEYWORD_WHILE ) - whiles++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->branch * 2; - else if ( item_type & ( ITEM_KEYWORD_CONTROL | ITEM_KEYWORD_IS_JUMP ) ) - jumps++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->branch; + if ( Find_Region(ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED) < 0 ) + { + if (item_type == ITEM_KEYWORD_FOR) + loops++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->loop; + else if (item_type == ITEM_KEYWORD_WHILE) + whiles++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->branch * 2; + else if (item_type & (ITEM_KEYWORD_CONTROL | ITEM_KEYWORD_IS_JUMP)) + jumps++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->branch; + } } } From 6205420c10acdc2f1684967ce40ea2bf2f35302a Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 3 Oct 2023 12:23:00 +0200 Subject: [PATCH 32/67] update ctest files --- src/wmc_tool/test_data/ref/main2.c | 2 +- src/wmc_tool/test_data/ref/wmc_auto.c | 2 +- src/wmc_tool/test_data/ref/wmc_auto.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wmc_tool/test_data/ref/main2.c b/src/wmc_tool/test_data/ref/main2.c index 2412264..d39d52c 100644 --- a/src/wmc_tool/test_data/ref/main2.c +++ b/src/wmc_tool/test_data/ref/main2.c @@ -20,7 +20,7 @@ /*AddedByWMC_Tool*/} /*AddedByWMC_Tool*/ROM_Size_Lookup_Table Const_Data_PROM_Table[] = /*AddedByWMC_Tool*/{ -/*AddedByWMC_Tool*/ { "out/test*.c", 734, Get_Const_Data_Size_out_test_c }, +/*AddedByWMC_Tool*/ { "out/test*.c", 119, Get_Const_Data_Size_out_test_c }, /*AddedByWMC_Tool*/ { "", -1, NULL } /*AddedByWMC_Tool*/}; /*AddedByWMC_Tool*/#endif diff --git a/src/wmc_tool/test_data/ref/wmc_auto.c b/src/wmc_tool/test_data/ref/wmc_auto.c index 00c2896..fcbcb09 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.c +++ b/src/wmc_tool/test_data/ref/wmc_auto.c @@ -2113,7 +2113,7 @@ long TotalWeightedOperation() return ( (long) tot ); } -long DeltaWeightedOperation() +long DeltaWeightedOperation( void ) { long NewWOper, delta; diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index be056e9..0a13cb7 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.h +++ b/src/wmc_tool/test_data/ref/wmc_auto.h @@ -1189,7 +1189,7 @@ extern long funcid_total_wmops_at_last_call_to_else; extern int call_occurred; extern long TotalWeightedOperation( void ); -long DeltaWeightedOperation(); +long DeltaWeightedOperation( void ); void Set_BASOP_WMOPS_counter( int counterId ); void Reset_BASOP_WMOPS_counter( void ); From 4ca1b5b6e049c05da8764c3defb30bf8df254489 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 3 Oct 2023 12:49:22 +0200 Subject: [PATCH 33/67] print error message if #undef WMC_TOOL_SKIP is not found --- src/wmc_tool/wmc_tool.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wmc_tool/wmc_tool.cpp b/src/wmc_tool/wmc_tool.cpp index ee3285c..d0d7df2 100644 --- a/src/wmc_tool/wmc_tool.cpp +++ b/src/wmc_tool/wmc_tool.cpp @@ -1539,6 +1539,10 @@ int main( int argc, char *argv[] ) { fprintf(stdout, "100%% Completed Successfully!\n" ); } + else + { + Print_Error(); + } return ErrCode; } From dd06209a1dc5be227dba0ecf340033f4c2d456ed Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 3 Oct 2023 15:32:03 +0200 Subject: [PATCH 34/67] make sure that PROM size is calculated and inserted in .c files where all functions are skipped with #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP --- src/wmc_tool/c_parser.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index bc11af0..61a1c15 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -8395,7 +8395,8 @@ TOOL_ERROR Instrument( } /* Insert PROM_Size_Func() function */ - if (is_function_present) + //if (is_function_present) + if (ParseCtx_ptr->PROMSize > 0) { if ((ErrCode = Instrument_PROM(ParseCtx_ptr)) != NO_ERR) { From c6c184d081f3fcebed38ecb5195a1263bb739da7 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 3 Oct 2023 15:39:02 +0200 Subject: [PATCH 35/67] update PROM size in ctest vectors --- src/wmc_tool/test_data/ref/main2.c | 2 +- src/wmc_tool/test_data/ref/test_basop.c | 1 + src/wmc_tool/test_data/ref/test_basop32.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/wmc_tool/test_data/ref/main2.c b/src/wmc_tool/test_data/ref/main2.c index d39d52c..e77f327 100644 --- a/src/wmc_tool/test_data/ref/main2.c +++ b/src/wmc_tool/test_data/ref/main2.c @@ -20,7 +20,7 @@ /*AddedByWMC_Tool*/} /*AddedByWMC_Tool*/ROM_Size_Lookup_Table Const_Data_PROM_Table[] = /*AddedByWMC_Tool*/{ -/*AddedByWMC_Tool*/ { "out/test*.c", 119, Get_Const_Data_Size_out_test_c }, +/*AddedByWMC_Tool*/ { "out/test*.c", 291, Get_Const_Data_Size_out_test_c }, /*AddedByWMC_Tool*/ { "", -1, NULL } /*AddedByWMC_Tool*/}; /*AddedByWMC_Tool*/#endif diff --git a/src/wmc_tool/test_data/ref/test_basop.c b/src/wmc_tool/test_data/ref/test_basop.c index b090bf1..dd20ac3 100644 --- a/src/wmc_tool/test_data/ref/test_basop.c +++ b/src/wmc_tool/test_data/ref/test_basop.c @@ -55,3 +55,4 @@ void weight_coef_a( const Word16 *a, Word16 *b, const Word16 ght ) } #undef WMC_TOOL_SKIP +/*AddedByWMC_Tool*/ int PROM_Size_Func( test_basop ) { return 15; } diff --git a/src/wmc_tool/test_data/ref/test_basop32.c b/src/wmc_tool/test_data/ref/test_basop32.c index e0e733a..9fcdf1e 100644 --- a/src/wmc_tool/test_data/ref/test_basop32.c +++ b/src/wmc_tool/test_data/ref/test_basop32.c @@ -2430,3 +2430,4 @@ Word32 L_msu0 (Word32 L_var3, Word16 var1, Word16 var2) { #undef WMC_TOOL_SKIP /* end of file */ +/*AddedByWMC_Tool*/ int PROM_Size_Func( test_basop32 ) { return 157; } From b0566be7b591a63b600e53e30286a900b51420ae Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 24 Oct 2023 09:07:02 +0200 Subject: [PATCH 36/67] add missing instrumentation in L40_mac() fix incorrect pointer types in TotalWeightedOperation() --- src/wmc_tool/test_data/ref/wmc_auto.c | 20 +++++++++++++------- src/wmc_tool/wmc_auto_c.txt | 21 ++++++++++++++------- src/wmc_tool/wmc_auto_h.txt | 1 + 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/wmc_tool/test_data/ref/wmc_auto.c b/src/wmc_tool/test_data/ref/wmc_auto.c index fcbcb09..baa02f2 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.c +++ b/src/wmc_tool/test_data/ref/wmc_auto.c @@ -278,7 +278,7 @@ void pop_wmops( void ) tot = DeltaWeightedOperation(); ops_cnt += tot; - /* update count of current record */ + /* update count of current record */ wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt; @@ -296,6 +296,7 @@ void pop_wmops( void ) current_record = -1; } + return; } @@ -373,6 +374,7 @@ void update_wmops( void ) wmops[i].max_cnt = wmops[i].current_cnt; } + if ( wmops[i].current_cnt < wmops[i].min_cnt ) { wmops[i].min_cnt = wmops[i].current_cnt; @@ -2056,7 +2058,7 @@ int funcId_where_last_call_to_else_occurred; long funcid_total_wmops_at_last_call_to_else; int call_occurred = 1; -const BASIC_OP op_weight = { +BASIC_OP op_weight = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -2096,21 +2098,24 @@ void Set_BASOP_WMOPS_counter( int counterId ) call_occurred = 1; } +extern int32_t frame; + long TotalWeightedOperation() { int i; - const long *ptr, *ptr2; + unsigned int *ptr, *ptr2; long tot; tot = 0; - ptr = (const long *) &multiCounter[currCounter]; - ptr2 = (const long *) &op_weight; - for ( i = 0; i < ( int )( sizeof( multiCounter[currCounter] ) / sizeof( long ) ); i++ ) + ptr = (unsigned int *) &multiCounter[currCounter]; + ptr2 = (unsigned int *) &op_weight; + + for ( i = 0; i < ( int )( sizeof( multiCounter[currCounter] ) / sizeof( unsigned int ) ); i++ ) { tot += ( ( *ptr++ ) * ( *ptr2++ ) ); } - return ( (long) tot ); + return ( tot ); } long DeltaWeightedOperation( void ) @@ -2118,6 +2123,7 @@ long DeltaWeightedOperation( void ) long NewWOper, delta; NewWOper = TotalWeightedOperation(); + delta = NewWOper - wmops[currCounter].LastWOper; wmops[currCounter].LastWOper = NewWOper; diff --git a/src/wmc_tool/wmc_auto_c.txt b/src/wmc_tool/wmc_auto_c.txt index 4862418..29db27f 100644 --- a/src/wmc_tool/wmc_auto_c.txt +++ b/src/wmc_tool/wmc_auto_c.txt @@ -278,7 +278,7 @@ " tot = DeltaWeightedOperation();\r\n" " ops_cnt += tot;\r\n" "\r\n" -" /* update count of current record */\r\n" +" /* update count of current record */\r\n" " wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n" " wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt;\r\n" "\r\n" @@ -296,6 +296,7 @@ " current_record = -1;\r\n" " }\r\n" "\r\n" +"\r\n" " return;\r\n" "}\r\n" "\r\n" @@ -373,6 +374,7 @@ " wmops[i].max_cnt = wmops[i].current_cnt;\r\n" " }\r\n" "\r\n" +"\r\n" " if ( wmops[i].current_cnt < wmops[i].min_cnt )\r\n" " {\r\n" " wmops[i].min_cnt = wmops[i].current_cnt;\r\n" @@ -2056,7 +2058,7 @@ "long funcid_total_wmops_at_last_call_to_else;\r\n" "int call_occurred = 1;\r\n" "\r\n" -"const BASIC_OP op_weight = {\r\n" +"BASIC_OP op_weight = {\r\n" " 1, 1, 1, 1, 1,\r\n" " 1, 1, 1, 1, 1,\r\n" " 1, 1, 1, 1, 1,\r\n" @@ -2096,21 +2098,24 @@ " call_occurred = 1;\r\n" "}\r\n" "\r\n" +"extern int32_t frame;\r\n" +"\r\n" "long TotalWeightedOperation()\r\n" "{\r\n" " int i;\r\n" -" const long *ptr, *ptr2;\r\n" +" unsigned int *ptr, *ptr2;\r\n" " long tot; \r\n" "\r\n" " tot = 0;\r\n" -" ptr = (const long *) &multiCounter[currCounter];\r\n" -" ptr2 = (const long *) &op_weight;\r\n" -" for ( i = 0; i < ( int )( sizeof( multiCounter[currCounter] ) / sizeof( long ) ); i++ )\r\n" +" ptr = (unsigned int *) &multiCounter[currCounter];\r\n" +" ptr2 = (unsigned int *) &op_weight;\r\n" +"\r\n" +" for ( i = 0; i < ( int )( sizeof( multiCounter[currCounter] ) / sizeof( unsigned int ) ); i++ )\r\n" " {\r\n" " tot += ( ( *ptr++ ) * ( *ptr2++ ) );\r\n" " }\r\n" "\r\n" -" return ( (long) tot );\r\n" +" return ( tot );\r\n" "}\r\n" "\r\n" "long DeltaWeightedOperation( void )\r\n" @@ -2118,6 +2123,7 @@ " long NewWOper, delta;\r\n" "\r\n" " NewWOper = TotalWeightedOperation();\r\n" +"\r\n" " delta = NewWOper - wmops[currCounter].LastWOper;\r\n" " wmops[currCounter].LastWOper = NewWOper;\r\n" "\r\n" @@ -2144,4 +2150,5 @@ "\r\n" "#endif\r\n" "\r\n" +"\r\n" "\r\n" \ No newline at end of file diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index 3957924..3c35fdc 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -1438,4 +1438,5 @@ "\r\n" "#endif /* WMOPS_H */\r\n" "\r\n" +"\r\n" "\r\n" \ No newline at end of file From dc1abb04507a510c4d007e1201868dcc5d341cd3 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 24 Oct 2023 13:37:00 +0200 Subject: [PATCH 37/67] Update README.md with MAC OS compile instructions --- src/wmc_tool/README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/wmc_tool/README.md b/src/wmc_tool/README.md index 4180f2c..fa67a4f 100644 --- a/src/wmc_tool/README.md +++ b/src/wmc_tool/README.md @@ -21,6 +21,7 @@ This software is protected by copyright law and by international treaties. The s ## History 2022-10-15 First release v1.4 +2023-10-24 Update to v1.5 (fixed small errors, compilation issues, added optimizations of the source code, added instrumentation of BASOP instructions and operators) ## Authors @@ -42,6 +43,7 @@ The files `wmc_auto_h.txt` and `wmc_auto_c.txt` contain functions and definition ### Unix-based systems To build the project on Unix-based platforms invoke the following commands from the top-level directory containing the file `CMakeLists.txt`: + ``` mkdir build cd build @@ -54,6 +56,7 @@ The binary file `wmc_tool` shall be created in the top-level directory. ### Windows system To build the project on MS Windows use the `cmake` command with `-G` option specifying the target platform. For example, to build project files for 64-bit MSVC 2019, invoke the following commands from the top-level directory containing the file `CMakeLists.txt`: + ``` md build cd build @@ -63,6 +66,25 @@ msbuild wmc_tool.sln The executable file `wmc_tool.exe` shall be created in the top-level directory. Note, that it is recommended to run these commands from the `Developer Command Prompt for VS2019` opened in `Administrator` mode. This ensures that all paths to libraries including the SDK can be found by the `cmake` command. This can also be verified with the `vswhere` command. +### Mac OS X system + +To build the project on OS X patforms for both, ARM and Intel architectures, invoke the following commands from the top-level directory containing the file `CMakeLists.txt`: + +``` +mkdir build +cd build +cmake -G "Xcode" "-DCMAKE_OSX_ARCHITECTURES=x86_64;arm64" .. +cmake --build . -j +``` + +At this point the binary is not signed yet and needs the following operations before it can be executed. +- Open `wmc_tool` with Finder -> Open (an error prompt should pop-up) +- Go to System Settings -> Privacy & Security and allow the `wmc_tool` to run +- Add execution rights to `wmc_tool` with: `chmod +x wmc_tool` + +The `wmc_tool` should now be ready for execution. + + ## Testing To verify the conformance of the WMC tool it's possible to invoke the `ctest` command from the `build` directory. On Windows platforms it may be necessary to append the config type with the `-C` command-line option. If no specific config type has been specified when running the `cmake` command, then `ctest -C Debug` shall be used for testing. This runs a series of pre-defined tests using some exemplary `.c` files located in the `testv/src` folder. The instrumented files are compared with their respective references located in the `testv/ref` folder. In case of test failure it's possible to re-run the test with the `--verbose` command-line option to see the reason of failure. Note, that `ctest` uses the Python wrapper script `testv/test_wmc_tool.py` for copying the source files, running the WMC tool binary (executable) file, comparing the output to the reference and cleaning up the work. From 012ae893277f9aaf61c4daee3d9e1fe147aa32ba Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Thu, 9 Nov 2023 12:27:39 +0100 Subject: [PATCH 38/67] change default unit ion memory reports from 32b words to bytes --- src/wmc_tool/test_data/ref/wmc_auto.c | 21 ++++++++++++++++----- src/wmc_tool/test_data/ref/wmc_auto.h | 3 ++- src/wmc_tool/wmc_auto_c.txt | 21 ++++++++++++++++----- src/wmc_tool/wmc_auto_h.txt | 3 ++- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/wmc_tool/test_data/ref/wmc_auto.c b/src/wmc_tool/test_data/ref/wmc_auto.c index baa02f2..0ff7786 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.c +++ b/src/wmc_tool/test_data/ref/wmc_auto.c @@ -25,6 +25,7 @@ #include #endif +#include "options.h" #include "wmc_auto.h" #define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */ @@ -682,7 +683,7 @@ allocator_record *allocation_list = NULL; static int Num_Records, Max_Num_Records; static size_t Stat_Cnt_Size = USE_BYTES; -static const char *Count_Unit[] = { "bytes", "words", "words" }; +static const char *Count_Unit[] = { "bytes", "words", "words", "words" }; static int32_t wc_ram_size, wc_ram_frame; static int32_t current_heap_size; @@ -1895,7 +1896,16 @@ void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) for ( i = 0; i < nElem; i++ ) { - fprintf( stdout, "Program ROM size (%s): %d instruction words\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size ); + if ( Stat_Cnt_Size > 0 ) + { + /* words */ + fprintf( stdout, "Program ROM size (%s): %d words\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size ); + } + else + { + /* bytes */ + fprintf( stdout, "Program ROM size (%s): %d bytes\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size << Stat_Cnt_Size ); + } } for ( i = 0; i < nElem; i++ ) @@ -1984,11 +1994,12 @@ void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) mem_count_summary(); #endif - if ( Stat_Cnt_Size > 0 ) + if ( Stat_Cnt_Size == 0 ) { - fprintf( stdout, "\nNote: 1 word = %d bits\n", 8 << Stat_Cnt_Size ); - fprintf( stdout, "This is an optimistic estimate of memory consumption assuming that each variable type is stored with sizeof(type) bits\n" ); + /* bytes */ + fprintf( stdout, "\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bytes (%d bits)\n", 1 << Stat_Cnt_Size, 8 << Stat_Cnt_Size ); } + fprintf( stdout, "Note: The Data ROM size is calculated using the sizeof(type) built-in function\n" ); if ( n_items_wc_intra_frame_heap > 0 ) { diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index 0a13cb7..e2f2af4 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.h +++ b/src/wmc_tool/test_data/ref/wmc_auto.h @@ -981,7 +981,8 @@ typedef enum { USE_BYTES = 0, USE_16BITS = 1, - USE_32BITS = 2 + USE_32BITS = 2, + USE_64BITS = 3 } Counting_Size; #if ( defined( _WIN32 ) && ( _MSC_VER <= 1800 ) && ( _MSC_VER >= 1300 ) ) diff --git a/src/wmc_tool/wmc_auto_c.txt b/src/wmc_tool/wmc_auto_c.txt index 29db27f..9a76a24 100644 --- a/src/wmc_tool/wmc_auto_c.txt +++ b/src/wmc_tool/wmc_auto_c.txt @@ -25,6 +25,7 @@ "#include \r\n" "#endif\r\n" "\r\n" +"#include \"options.h\"\r\n" "#include \"wmc_auto.h\"\r\n" "\r\n" "#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */\r\n" @@ -682,7 +683,7 @@ "\r\n" "static int Num_Records, Max_Num_Records;\r\n" "static size_t Stat_Cnt_Size = USE_BYTES;\r\n" -"static const char *Count_Unit[] = { \"bytes\", \"words\", \"words\" };\r\n" +"static const char *Count_Unit[] = { \"bytes\", \"words\", \"words\", \"words\" };\r\n" "\r\n" "static int32_t wc_ram_size, wc_ram_frame;\r\n" "static int32_t current_heap_size;\r\n" @@ -1895,7 +1896,16 @@ "\r\n" " for ( i = 0; i < nElem; i++ )\r\n" " {\r\n" -" fprintf( stdout, \"Program ROM size (%s): %d instruction words\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size );\r\n" +" if ( Stat_Cnt_Size > 0 )\r\n" +" {\r\n" +" /* words */\r\n" +" fprintf( stdout, \"Program ROM size (%s): %d words\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size );\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" /* bytes */\r\n" +" fprintf( stdout, \"Program ROM size (%s): %d bytes\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size << Stat_Cnt_Size );\r\n" +" }\r\n" " }\r\n" "\r\n" " for ( i = 0; i < nElem; i++ )\r\n" @@ -1984,11 +1994,12 @@ " mem_count_summary();\r\n" "#endif\r\n" "\r\n" -" if ( Stat_Cnt_Size > 0 )\r\n" +" if ( Stat_Cnt_Size == 0 )\r\n" " {\r\n" -" fprintf( stdout, \"\\nNote: 1 word = %d bits\\n\", 8 << Stat_Cnt_Size );\r\n" -" fprintf( stdout, \"This is an optimistic estimate of memory consumption assuming that each variable type is stored with sizeof(type) bits\\n\" );\r\n" +" /* bytes */\r\n" +" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bytes (%d bits)\\n\", 1 << Stat_Cnt_Size, 8 << Stat_Cnt_Size );\r\n" " }\r\n" +" fprintf( stdout, \"Note: The Data ROM size is calculated using the sizeof(type) built-in function\\n\" );\r\n" "\r\n" " if ( n_items_wc_intra_frame_heap > 0 )\r\n" " {\r\n" diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index 3c35fdc..d0a6e65 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -981,7 +981,8 @@ "{\r\n" " USE_BYTES = 0,\r\n" " USE_16BITS = 1,\r\n" -" USE_32BITS = 2\r\n" +" USE_32BITS = 2,\r\n" +" USE_64BITS = 3\r\n" "} Counting_Size;\r\n" "\r\n" "#if ( defined( _WIN32 ) && ( _MSC_VER <= 1800 ) && ( _MSC_VER >= 1300 ) )\r\n" From fc187416604e9c4efd2a08234138fbd68bb5d6a1 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Thu, 9 Nov 2023 13:37:38 +0100 Subject: [PATCH 39/67] create changelog file --- src/wmc_tool/HISTORY.md | 69 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/wmc_tool/HISTORY.md diff --git a/src/wmc_tool/HISTORY.md b/src/wmc_tool/HISTORY.md new file mode 100644 index 0000000..7cbdbc0 --- /dev/null +++ b/src/wmc_tool/HISTORY.md @@ -0,0 +1,69 @@ +# History of the WMC tool + +## v1.0 + + * initial version of the WMC tool + +## v1.1 + + * added support for PROM Counting + * added support for Table ROM Instrumentation + * added support for stack counting + * added progress bar (0-100%) + * added support for `S("string")` macro in manually-instrumented sections + +## v1.2 + + * added Unident mode to remove unused left margin + * added automatic conversion of TABs to spaces + * added a command-line switch to disable all warnings (/dw99) + + * modified the atomatically-generated file "wmc_auto.h" to eliminate warnings when compiled with `gcc` + * removed `#pragma WMC_TOOL_MESSAGE` in the `rom_*.c` files + * removed `#pragma WMC_TOOL_MESSAGE` for manually-instrumented sections + + * changed the default PROM counting weights to those specified in "S4-110479 - FTO - On Program ROM measurement for EVS standardization.doc" + * fix of a small bug where using '/op2', '/op3' crashes the WMC tool + * added support for Windows 8 command line and Cygwin V1.7.17 and later versions + * fix for a bug where a `$("[]M[]")` was inserted at the end of some C source files when it was re-instrumented + +## v1.3 + + * break in early-return out of .each early with return false + * prevent adding unnecessary space by the functions `Move_on_Chars()` and `Skip_Chars()` + * optimize the function `Find_Region()` to improve the speef of instrumentation + * optimize the function calculating the next pointer address after hitting the search target + * order macro names, system functions, etc. in the highest priority order + * combine `strlno` and `strcno` inside `Make_Position_String()` + * optimize the usage of the function `Instrument_Names()` inside `Find_Keywords()` and `Find_Calls()` + * remove the cases where `item_link` is always NULL + +## v1.4 + + * first version uploaded to the Open-ITU/STL Github repository + * remove obsolete parts of the source code (e.g. FLC) + + * bug in PROM calculation fixed + * command-line options modified (`/ic` and `/op` removed) + * memory instrumentation (PROM, Table ROM, static RAM and stack) integrated within the WMC tool (auxiliary files `PROM_Size_xxx.c` no longer generated) + * merging and renaming of files: + ** `wmops.h` and `wmops.c` -> `wmc_auto.h` and `wmc_auto.c` + ** `memory.c` -> `wmc_auto.c` + ** `mem_count.h` and `mem_count.c` -> `wmc_auto.h` and `wmc_auto.c` + ** `wmc_auto.h` and `wmc_auto.c` are optionally generated by the WMC tool with the `./wmc_tool /cp dir_name` command-line option + * PROM consumption calculated during instrumentation and added at the end in each `.c` file + * total PROM consumption may be printed with the function `print_mem()` + * re-factoring of the Table ROM instrumentation, calcula + +## v1.5 + + * fixed compilation issues on MaC platforms + * fixed a problem where `NaN` was printed for a non-instrumented function having zero complexity + * dynamic allocation and re-allocation of all internal buffers tracking both heap and stack call trees + * introduction of `-f FRAME_PER_SECONDS` command-line option allowing the user to choose the number of frames per second (default is still 50.0) + * fixed a problem when `push_wmops()` was called twice when `WMOPS_DETAILS` was activated + * raise an error message if `#define WMC_TOOL_SKIP` is not paired with `#undef WMC_TOOL_SKIP` + * export information about all dynamic allocations/de-allocations occuring during the runtime of the codec to a `.csv` file + * added an exemplary Python script `mem_analysis.py` for graphical analysis and profiling of dynamic memory alloations based on the generated `.csv` file + * added support for counting complexity and PROM size of BASOP operations and BASOP functions within floating-point source code + \ No newline at end of file From fc2bedc45b9a7cc90aa21d4c52754abdb383f8b6 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Thu, 9 Nov 2023 13:44:55 +0100 Subject: [PATCH 40/67] formatting in HISTORY.md --- src/wmc_tool/HISTORY.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wmc_tool/HISTORY.md b/src/wmc_tool/HISTORY.md index 7cbdbc0..456511f 100644 --- a/src/wmc_tool/HISTORY.md +++ b/src/wmc_tool/HISTORY.md @@ -16,14 +16,14 @@ * added Unident mode to remove unused left margin * added automatic conversion of TABs to spaces - * added a command-line switch to disable all warnings (/dw99) + * added a command-line switch to disable all warnings (`/dw99`) * modified the atomatically-generated file "wmc_auto.h" to eliminate warnings when compiled with `gcc` * removed `#pragma WMC_TOOL_MESSAGE` in the `rom_*.c` files * removed `#pragma WMC_TOOL_MESSAGE` for manually-instrumented sections - * changed the default PROM counting weights to those specified in "S4-110479 - FTO - On Program ROM measurement for EVS standardization.doc" - * fix of a small bug where using '/op2', '/op3' crashes the WMC tool + * changed the default PROM counting weights to those specified in [S4-110479 - FTO - On Program ROM measurement for EVS standardization.doc] ([https://www.3gpp.org/ftp/tsg_sa/WG4_CODEC/TSGS4_64/docs/S4-110479.zip) + * fix of a small bug where using `/op2`, `/op3` crashes the WMC tool * added support for Windows 8 command line and Cygwin V1.7.17 and later versions * fix for a bug where a `$("[]M[]")` was inserted at the end of some C source files when it was re-instrumented @@ -53,7 +53,7 @@ ** `wmc_auto.h` and `wmc_auto.c` are optionally generated by the WMC tool with the `./wmc_tool /cp dir_name` command-line option * PROM consumption calculated during instrumentation and added at the end in each `.c` file * total PROM consumption may be printed with the function `print_mem()` - * re-factoring of the Table ROM instrumentation, calcula + * re-factoring of the Table ROM instrumentation, calculation and reporting ## v1.5 From 6ac728c5ba596c0bb61656d501f246ca9b3052ae Mon Sep 17 00:00:00 2001 From: malenov Date: Mon, 12 Feb 2024 15:58:47 +0100 Subject: [PATCH 41/67] add inv_sqrtf() to the list of intrinsic math functions --- src/wmc_tool/c_parser.cpp | 2 +- src/wmc_tool/wmc_auto_h.txt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 61a1c15..a209538 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -141,7 +141,7 @@ "sqr Sqr SQR " \ "square Square SQUARE " \ "sign Sign SIGN " \ - "inv_sqrt " \ + "inv_sqrt inv_sqrtf " \ "log_base_2 log2_f " \ "_round round_f " \ "_squant " \ diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index d0a6e65..0ed1d06 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -733,7 +733,8 @@ "/* Square Root and its Variants */\r\n" "#define sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf( ( x ) ) )\r\n" "/* Invert Square Root and its Variants */\r\n" -"#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) )\r\n" +"#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) )\r\n" +"#define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) )\r\n" "/* Others */\r\n" "#define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) )\r\n" "#define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) )\r\n" From d10e75906718f304a3dd5e431f30993fd4aff28d Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Mon, 26 Feb 2024 10:50:16 +0100 Subject: [PATCH 42/67] update the manual --- doc/manual/wmc_tool.tex | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/manual/wmc_tool.tex b/doc/manual/wmc_tool.tex index 7dbc960..595ab12 100644 --- a/doc/manual/wmc_tool.tex +++ b/doc/manual/wmc_tool.tex @@ -56,8 +56,11 @@ \subsection{Usage} note: filename shall point to a .c file containing the print_mem() function -b [--no-backup]: no backup of original files -c dirname [--generate-wmc-files dirname]: copy wmc_auto.h and wmc_auto.c to a user-specified directory + -f value [--frames-per-second value]: set the number of frames per second (default 50.0) \end{Verbatim} +The optional commend-line parameters may be used to control either the instrumentation or the couting process. With the \verb|-i| optional argument the WMC tool prints the list of about functions that are instrumented. It doesn't run the WMC tool. The parametr \verb|-d| runs the des-instrumentation phase only. The des-instrumentation phase removes all meta-information that has been previously added to the source code with the WMC tool. When \verb|-m| argument is provided the WMC tool adds code calculating ROM and RAM memory consumption and fills the \verb|print_mem()| function to print the statistics about memopry usage. When \verb|-m| is provided the user needs to specify the used the name of the \verb|.c| file containing the \verb|print_mem()| function. The parameter \verb|-b| instructs the WMC tool not to create backup copies of the instrumented \verb|.c| files. The parameter \verb|-c| copies the control files \verb|wmc_auto.h| and \verb|wmc_auto.c| to a user-specified directory. The control files must be added to the project for calculating the complexity and memory consumption of all instrumented source files. The \verb|-f| parameter allows the users to override the default values for the number of frames per second. This value is important for the correct calculation of complexity in "WMOPS". + \subsection{Instrumentation process} \label{ch:instrumentation_process} From 688e97c014aa971f55d8ea55d83e2955308eae7e Mon Sep 17 00:00:00 2001 From: Ludovic Malfait Date: Tue, 12 Mar 2024 09:56:00 +0000 Subject: [PATCH 43/67] Typos in wmc_tool.tex --- doc/manual/wmc_tool.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/wmc_tool.tex b/doc/manual/wmc_tool.tex index 595ab12..4e0994a 100644 --- a/doc/manual/wmc_tool.tex +++ b/doc/manual/wmc_tool.tex @@ -59,7 +59,7 @@ \subsection{Usage} -f value [--frames-per-second value]: set the number of frames per second (default 50.0) \end{Verbatim} -The optional commend-line parameters may be used to control either the instrumentation or the couting process. With the \verb|-i| optional argument the WMC tool prints the list of about functions that are instrumented. It doesn't run the WMC tool. The parametr \verb|-d| runs the des-instrumentation phase only. The des-instrumentation phase removes all meta-information that has been previously added to the source code with the WMC tool. When \verb|-m| argument is provided the WMC tool adds code calculating ROM and RAM memory consumption and fills the \verb|print_mem()| function to print the statistics about memopry usage. When \verb|-m| is provided the user needs to specify the used the name of the \verb|.c| file containing the \verb|print_mem()| function. The parameter \verb|-b| instructs the WMC tool not to create backup copies of the instrumented \verb|.c| files. The parameter \verb|-c| copies the control files \verb|wmc_auto.h| and \verb|wmc_auto.c| to a user-specified directory. The control files must be added to the project for calculating the complexity and memory consumption of all instrumented source files. The \verb|-f| parameter allows the users to override the default values for the number of frames per second. This value is important for the correct calculation of complexity in "WMOPS". +The optional command-line parameters may be used to control either the instrumentation or the couting process. With the \verb|-i| optional argument the WMC tool prints the list of functions that are instrumented. It doesn't run the WMC tool. The parameter \verb|-d| runs the des-instrumentation phase only. The des-instrumentation phase removes all meta-information that has been previously added to the source code with the WMC tool. When \verb|-m| argument is provided the WMC tool adds code calculating ROM and RAM memory consumption and fills the \verb|print_mem()| function to print the statistics about memory usage. When \verb|-m| is provided the user needs to specify the name of the \verb|.c| file containing the \verb|print_mem()| function. The parameter \verb|-b| instructs the WMC tool not to create backup copies of the instrumented \verb|.c| files. The parameter \verb|-c| copies the control files \verb|wmc_auto.h| and \verb|wmc_auto.c| to a user-specified directory. The control files must be added to the project for calculating the complexity and memory consumption of all instrumented source files. The \verb|-f| parameter allows the users to override the default values for the number of frames per second. This value is important for the correct calculation of complexity in "WMOPS". \subsection{Instrumentation process} \label{ch:instrumentation_process} From a052292a68d961ae63c7f6c9b5a3b4b0d8cbff55 Mon Sep 17 00:00:00 2001 From: Ludovic Malfait Date: Tue, 12 Mar 2024 10:00:06 +0000 Subject: [PATCH 44/67] Typos in README.md --- src/wmc_tool/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmc_tool/README.md b/src/wmc_tool/README.md index fa67a4f..4731e71 100644 --- a/src/wmc_tool/README.md +++ b/src/wmc_tool/README.md @@ -68,7 +68,7 @@ The executable file `wmc_tool.exe` shall be created in the top-level directory. ### Mac OS X system -To build the project on OS X patforms for both, ARM and Intel architectures, invoke the following commands from the top-level directory containing the file `CMakeLists.txt`: +To build the project on OS X platforms for both, ARM and Intel architectures, invoke the following commands from the top-level directory containing the file `CMakeLists.txt`: ``` mkdir build From 0d58f8d6b83d7f3d3bae05e4d355056ef01fc20a Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 13 Mar 2024 15:12:52 +0100 Subject: [PATCH 45/67] recognize "f" float variants of intrinsic mathematical functions (sinf, cosf, sqrtf, ...) --- src/wmc_tool/c_parser.cpp | 40 ++++----- src/wmc_tool/test_data/ref/wmc_auto.c | 1 + src/wmc_tool/test_data/ref/wmc_auto.h | 124 ++++++++++++------------- src/wmc_tool/wmc_auto_h.txt | 125 +++++++++++++------------- 4 files changed, 144 insertions(+), 146 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index a209538..d3ce5a2 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -124,29 +124,23 @@ #define SYSTEM_FUNCTS_STRING \ "printf fprintf " \ "fopen fclose fwrite fread " \ - "exit " \ - "assert " - -#define MATH_FUNCTS_STRING \ - "abs fabs labs " \ - "floor " \ - "sqrt sqrtf " \ - "pow exp " \ - "log log10 " \ - "cos sin tan " \ - "acos asin atan atan2 " \ - "cosh sinh tanh " \ - "fmod " \ - "min max Min Max MIN MAX " \ - "sqr Sqr SQR " \ - "square Square SQUARE " \ - "sign Sign SIGN " \ - "inv_sqrt inv_sqrtf " \ - "log_base_2 log2_f " \ - "_round round_f " \ - "_squant " \ - "set_min set_max " \ - "mac msu " + "assert exit " + +#define MATH_FUNCTS_STRING \ + "abs fabs fabsf labs " \ + "floor floorf " \ + "sqrt sqrtf inv_sqrt inv_sqrtf " \ + "pow powf exp expf " \ + "log logf log10 log10f log_base_2 log2 log2_f " \ + "cos cosf sin sinf tan tanf " \ + "acos acosf asin asinf atan atanf atan2 atan2f " \ + "cosh coshf sinh sinhf tanh tanhf " \ + "fmod fmodf " \ + "min max Min Max MIN MAX " \ + "sqr Sqr SQR square Square SQUARE " \ + "sign Sign SIGN " \ + "_round round_f " \ + "set_min set_max " #define BASOP_FUNCTS_STRING \ "add sub abs_s shl shr extract_h extract_l mult L_mult negate round " \ diff --git a/src/wmc_tool/test_data/ref/wmc_auto.c b/src/wmc_tool/test_data/ref/wmc_auto.c index 0ff7786..5e73cb9 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.c +++ b/src/wmc_tool/test_data/ref/wmc_auto.c @@ -2162,3 +2162,4 @@ void Reset_BASOP_WMOPS_counter( void ) #endif + diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index e2f2af4..d42d68e 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.h +++ b/src/wmc_tool/test_data/ref/wmc_auto.h @@ -615,14 +615,6 @@ extern int cntr_push_pop; #endif -/* mac & msu (Non Instrumented Versions) */ -#ifndef mac -#define mac( a, b, c ) ( ( a ) + ( b ) * ( c ) ) -#endif -#ifndef mac -#define msu( a, b, c ) ( ( a ) - ( b ) * ( c ) ) -#endif - #ifndef WMOPS /* DESACTIVATE the Counting Mechanism */ #define OP_COUNT_( op, n ) @@ -691,63 +683,72 @@ static int wmc_flag_ = 0; #define MISC_( x ) ABS_( x ) /* Math Operations */ -#define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs ) -#define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs ) -#define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs ) -#define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor ) -#define sqrt_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrt ) -#define pow_ OP_COUNT_WRAPPER1_( POWER_( 1 ), pow ) -#define exp_ OP_COUNT_WRAPPER1_( POWER_( 1 ), exp ) -#define log_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log ) -#define log10_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10 ) -#define cos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cos ) -#define sin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sin ) -#define tan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tan ) -#define acos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acos ) -#define asin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asin ) -#define atan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan ) -#define atan2_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2 ) -#define cosh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosh ) -#define sinh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinh ) -#define tanh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanh ) -#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod ) -/* these macros use any local macros already defined */ -/* min/max and their Variants */ -#define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) ) -#define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) ) -#define MIN_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MIN( ( a ), ( b ) ) ) -#define MAX_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MAX( ( a ), ( b ) ) ) -#define Min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Min( ( a ), ( b ) ) ) -#define Max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Max( ( a ), ( b ) ) ) -/* Square and its Variants */ -#define sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), sqr( ( x ) ) ) -#define Sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Sqr( ( x ) ) ) -#define SQR_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQR( ( x ) ) ) -#define square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), square( ( x ) ) ) -#define Square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Square( ( x ) ) ) -#define SQUARE_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQUARE( ( x ) ) ) -/* Sign and its Variants */ -#define sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), sign( ( x ) ) ) -#define Sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), Sign( ( x ) ) ) -#define SIGN_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), SIGN( ( x ) ) ) -/* Square Root and its Variants */ -#define sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf( ( x ) ) ) -/* Invert Square Root and its Variants */ -#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) ) -/* Others */ +#define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs ) +#define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs ) +#define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs ) +#define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor ) +#define floorf_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floorf ) +#define sqrt_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrt ) +#define sqrtf_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf ) +#define pow_ OP_COUNT_WRAPPER1_( POWER_( 1 ), pow ) +#define powf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), powf ) +#define exp_ OP_COUNT_WRAPPER1_( POWER_( 1 ), exp ) +#define expf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), expf ) +#define log_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log ) +#define logf_ OP_COUNT_WRAPPER1_( LOG_( 1 ), logf ) +#define log10_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10 ) +#define log10f_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10f ) +#define cos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cos ) +#define cosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosf ) +#define sin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sin ) +#define sinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinf ) +#define tan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tan ) +#define tanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanf ) +#define acos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acos ) +#define acosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acosf ) +#define asin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asin ) +#define asinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asinf ) +#define atan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan ) +#define atanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atanf ) +#define atan2_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2 ) +#define atan2f_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2f ) +#define cosh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosh ) +#define coshf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), coshf ) +#define sinh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinh ) +#define sinhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinhf ) +#define tanh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanh ) +#define tanhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanhf ) +#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod ) +#define fmodf_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmodf ) + +/* the macros below are instrumented versions of user-defined macros that might be used in the source code +/* representing some well-known and recognized mathematical operations (that are not defined in math.h) */ +/* Note: the 'wmc_flag_=wmc_flag_' is used to avoid warning: left-hand operand of comma expression has no effect with gcc */ + +#define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) ) +#define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) ) +#define MIN_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MIN( ( a ), ( b ) ) ) +#define MAX_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MAX( ( a ), ( b ) ) ) +#define Min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Min( ( a ), ( b ) ) ) +#define Max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Max( ( a ), ( b ) ) ) +#define sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), sqr( ( x ) ) ) +#define Sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Sqr( ( x ) ) ) +#define SQR_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQR( ( x ) ) ) +#define square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), square( ( x ) ) ) +#define Square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Square( ( x ) ) ) +#define SQUARE_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQUARE( ( x ) ) ) +#define sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), sign( ( x ) ) ) +#define Sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), Sign( ( x ) ) ) +#define SIGN_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), SIGN( ( x ) ) ) +#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) ) +#define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrtf( ( x ) ) ) #define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) ) +#define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) ) #define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) ) -/* The 'wmc_flag_=wmc_flag_' is Used to Avoid: "warning: left-hand operand of comma expression has no effect" - with Cygwin gcc Compiler */ -#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) ) -#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) ) -#define _squant_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _squant( ( x ) ) ) -/* Set Min/Max */ +#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) ) +#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) ) #define set_min_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_min( ( a ), ( b ) ) ) #define set_max_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_max( ( a ), ( b ) ) ) -/* mac & msu (Instrumented Versions) */ -#define mac_( a, b, c ) OP_COUNT_WRAPPER1_( MAC_( 1 ), mac( a, b, c ) ) -#define msu_( a, b, c ) OP_COUNT_WRAPPER1_( MAC_( 1 ), msu( a, b, c ) ) /* Functions */ #define func_( name, x ) OP_COUNT_WRAPPER1_( FUNC_( x ), name ) @@ -1440,3 +1441,4 @@ static __inline void incrGoto( void) { #endif /* WMOPS_H */ + diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index 0ed1d06..1950492 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -615,14 +615,6 @@ "\r\n" "#endif\r\n" "\r\n" -"/* mac & msu (Non Instrumented Versions) */\r\n" -"#ifndef mac\r\n" -"#define mac( a, b, c ) ( ( a ) + ( b ) * ( c ) )\r\n" -"#endif\r\n" -"#ifndef mac\r\n" -"#define msu( a, b, c ) ( ( a ) - ( b ) * ( c ) )\r\n" -"#endif\r\n" -"\r\n" "#ifndef WMOPS\r\n" "/* DESACTIVATE the Counting Mechanism */\r\n" "#define OP_COUNT_( op, n )\r\n" @@ -691,64 +683,73 @@ "#define MISC_( x ) ABS_( x )\r\n" "\r\n" "/* Math Operations */\r\n" -"#define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs )\r\n" -"#define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs )\r\n" -"#define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs )\r\n" -"#define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor )\r\n" -"#define sqrt_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrt )\r\n" -"#define pow_ OP_COUNT_WRAPPER1_( POWER_( 1 ), pow )\r\n" -"#define exp_ OP_COUNT_WRAPPER1_( POWER_( 1 ), exp )\r\n" -"#define log_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log )\r\n" -"#define log10_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10 )\r\n" -"#define cos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cos )\r\n" -"#define sin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sin )\r\n" -"#define tan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tan )\r\n" -"#define acos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acos )\r\n" -"#define asin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asin )\r\n" -"#define atan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan )\r\n" -"#define atan2_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2 )\r\n" -"#define cosh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosh )\r\n" -"#define sinh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinh )\r\n" -"#define tanh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanh )\r\n" -"#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod )\r\n" -"/* these macros use any local macros already defined */\r\n" -"/* min/max and their Variants */\r\n" -"#define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) )\r\n" -"#define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) )\r\n" -"#define MIN_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MIN( ( a ), ( b ) ) )\r\n" -"#define MAX_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MAX( ( a ), ( b ) ) )\r\n" -"#define Min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Min( ( a ), ( b ) ) )\r\n" -"#define Max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Max( ( a ), ( b ) ) )\r\n" -"/* Square and its Variants */\r\n" -"#define sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), sqr( ( x ) ) )\r\n" -"#define Sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Sqr( ( x ) ) )\r\n" -"#define SQR_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQR( ( x ) ) )\r\n" -"#define square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), square( ( x ) ) )\r\n" -"#define Square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Square( ( x ) ) )\r\n" -"#define SQUARE_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQUARE( ( x ) ) )\r\n" -"/* Sign and its Variants */\r\n" -"#define sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), sign( ( x ) ) )\r\n" -"#define Sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), Sign( ( x ) ) )\r\n" -"#define SIGN_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), SIGN( ( x ) ) )\r\n" -"/* Square Root and its Variants */\r\n" -"#define sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf( ( x ) ) )\r\n" -"/* Invert Square Root and its Variants */\r\n" -"#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) )\r\n" -"#define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) )\r\n" -"/* Others */\r\n" +"#define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs )\r\n" +"#define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs )\r\n" +"#define fabsf_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabsf )\r\n" +"#define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs )\r\n" +"#define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor )\r\n" +"#define floorf_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floorf )\r\n" +"#define sqrt_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrt )\r\n" +"#define sqrtf_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf )\r\n" +"#define pow_ OP_COUNT_WRAPPER1_( POWER_( 1 ), pow )\r\n" +"#define powf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), powf )\r\n" +"#define exp_ OP_COUNT_WRAPPER1_( POWER_( 1 ), exp )\r\n" +"#define expf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), expf )\r\n" +"#define log_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log )\r\n" +"#define logf_ OP_COUNT_WRAPPER1_( LOG_( 1 ), logf )\r\n" +"#define log10_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10 )\r\n" +"#define log10f_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10f )\r\n" +"#define cos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cos )\r\n" +"#define cosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosf )\r\n" +"#define sin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sin )\r\n" +"#define sinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinf )\r\n" +"#define tan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tan )\r\n" +"#define tanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanf )\r\n" +"#define acos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acos )\r\n" +"#define acosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acosf )\r\n" +"#define asin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asin )\r\n" +"#define asinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asinf )\r\n" +"#define atan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan )\r\n" +"#define atanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atanf )\r\n" +"#define atan2_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2 )\r\n" +"#define atan2f_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2f )\r\n" +"#define cosh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosh )\r\n" +"#define coshf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), coshf )\r\n" +"#define sinh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinh )\r\n" +"#define sinhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinhf )\r\n" +"#define tanh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanh )\r\n" +"#define tanhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanhf )\r\n" +"#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod )\r\n" +"#define fmodf_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmodf )\r\n" +"\r\n" +"/* the macros below are instrumented versions of user-defined macros that might be used in the source code \r\n" +"/* representing some well-known and recognized mathematical operations (that are not defined in math.h) */\r\n" +"/* Note: the 'wmc_flag_=wmc_flag_' is used to avoid warning: left-hand operand of comma expression has no effect with gcc */\r\n" +"\r\n" +"#define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) )\r\n" +"#define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) )\r\n" +"#define MIN_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MIN( ( a ), ( b ) ) )\r\n" +"#define MAX_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MAX( ( a ), ( b ) ) )\r\n" +"#define Min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Min( ( a ), ( b ) ) )\r\n" +"#define Max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Max( ( a ), ( b ) ) )\r\n" +"#define sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), sqr( ( x ) ) )\r\n" +"#define Sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Sqr( ( x ) ) )\r\n" +"#define SQR_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQR( ( x ) ) )\r\n" +"#define square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), square( ( x ) ) )\r\n" +"#define Square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Square( ( x ) ) )\r\n" +"#define SQUARE_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQUARE( ( x ) ) )\r\n" +"#define sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), sign( ( x ) ) )\r\n" +"#define Sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), Sign( ( x ) ) )\r\n" +"#define SIGN_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), SIGN( ( x ) ) )\r\n" +"#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) )\r\n" +"#define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrtf( ( x ) ) )\r\n" "#define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) )\r\n" +"#define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) )\r\n" "#define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) )\r\n" -"/* The 'wmc_flag_=wmc_flag_' is Used to Avoid: \"warning: left-hand operand of comma expression has no effect\"\r\n" -" with Cygwin gcc Compiler */\r\n" -"#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) )\r\n" -"#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) )\r\n" -"#define _squant_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _squant( ( x ) ) )\r\n" -"/* Set Min/Max */\r\n" +"#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) )\r\n" +"#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) )\r\n" "#define set_min_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_min( ( a ), ( b ) ) )\r\n" "#define set_max_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_max( ( a ), ( b ) ) )\r\n" -"/* mac & msu (Instrumented Versions) */\r\n" -"#define mac_( a, b, c ) OP_COUNT_WRAPPER1_( MAC_( 1 ), mac( a, b, c ) )\r\n" -"#define msu_( a, b, c ) OP_COUNT_WRAPPER1_( MAC_( 1 ), msu( a, b, c ) )\r\n" "\r\n" "/* Functions */\r\n" "#define func_( name, x ) OP_COUNT_WRAPPER1_( FUNC_( x ), name )\r\n" From 9882ebb39c4a99e866939aea6d9c545732ab3423 Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 13 Mar 2024 15:13:11 +0100 Subject: [PATCH 46/67] add Python requirements file --- src/wmc_tool/requirements.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/wmc_tool/requirements.txt diff --git a/src/wmc_tool/requirements.txt b/src/wmc_tool/requirements.txt new file mode 100644 index 0000000..510bec3 --- /dev/null +++ b/src/wmc_tool/requirements.txt @@ -0,0 +1,3 @@ +matplotlib>=3.8 +numpy>=1.26 +pandas>=2.2 From ed51c1e3046e59bca42fec0d63af6e9003617282 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Wed, 13 Mar 2024 15:51:51 +0100 Subject: [PATCH 47/67] update helper files --- src/wmc_tool/test_data/ref/wmc_auto.c | 15 ++++++++--- src/wmc_tool/test_data/ref/wmc_auto.h | 37 +++++++++++++-------------- src/wmc_tool/wmc_auto_c.txt | 15 ++++++++--- src/wmc_tool/wmc_auto_h.txt | 36 ++++++++++++-------------- 4 files changed, 57 insertions(+), 46 deletions(-) diff --git a/src/wmc_tool/test_data/ref/wmc_auto.c b/src/wmc_tool/test_data/ref/wmc_auto.c index 5e73cb9..7dfcf8b 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.c +++ b/src/wmc_tool/test_data/ref/wmc_auto.c @@ -42,6 +42,8 @@ #define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */ #define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */ #define DOUBLE_MAX 0x80000000 +#define FAC ( FRAMES_PER_SECOND / 1e6 ) + typedef struct { @@ -1903,8 +1905,8 @@ void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) } else { - /* bytes */ - fprintf( stdout, "Program ROM size (%s): %d bytes\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size << Stat_Cnt_Size ); + /* bytes (here, we assume that each instruction takes PROM_INST_SIZE bits of the PROM memory) */ + fprintf( stdout, "Program ROM size (%s): %d bytes\n", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size * ( PROM_INST_SIZE / 8 ) ); } } @@ -1994,10 +1996,15 @@ void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) mem_count_summary(); #endif - if ( Stat_Cnt_Size == 0 ) + if ( Stat_Cnt_Size > 0 ) + { + /* words */ + fprintf( stdout, "\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\n", 8 << Stat_Cnt_Size ); + } + else { /* bytes */ - fprintf( stdout, "\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bytes (%d bits)\n", 1 << Stat_Cnt_Size, 8 << Stat_Cnt_Size ); + fprintf( stdout, "\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\n", PROM_INST_SIZE ); } fprintf( stdout, "Note: The Data ROM size is calculated using the sizeof(type) built-in function\n" ); diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index d42d68e..3b47cee 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.h +++ b/src/wmc_tool/test_data/ref/wmc_auto.h @@ -33,10 +33,8 @@ #define INT_MAX 32767 #endif -/* Real-time relationships */ #define FRAMES_PER_SECOND 50.0 -#define WMOPS_BOOST_FAC ( 1.0f ) /* scaling factor for equalizing the difference between automatic and manual instrumentation */ -#define FAC ( FRAMES_PER_SECOND / 1e6 * WMOPS_BOOST_FAC ) +#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */ #ifdef WMOPS enum instructions @@ -662,29 +660,30 @@ static int wmc_flag_ = 0; #endif /* Define all Macros without '{' & '}' (None of these should be called externally!) */ -#define ABS_( x ) OP_COUNT_( _ABS, ( x ) / WMOPS_BOOST_FAC ) -#define ADD_( x ) OP_COUNT_( _ADD, ( x ) / WMOPS_BOOST_FAC ) -#define MULT_( x ) OP_COUNT_( _MULT, ( x ) / WMOPS_BOOST_FAC ) -#define MAC_( x ) OP_COUNT_( _MAC, ( x ) / WMOPS_BOOST_FAC ) -#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) / WMOPS_BOOST_FAC ) -#define STORE_( x ) OP_COUNT_( _STORE, ( x ) / WMOPS_BOOST_FAC ) -#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) / WMOPS_BOOST_FAC ) -#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) / WMOPS_BOOST_FAC ) -#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) / WMOPS_BOOST_FAC ) -#define DIV_( x ) OP_COUNT_( _DIV, ( x ) / WMOPS_BOOST_FAC ) -#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) / WMOPS_BOOST_FAC ) -#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) / WMOPS_BOOST_FAC ) +#define ABS_( x ) OP_COUNT_( _ABS, ( x ) ) +#define ADD_( x ) OP_COUNT_( _ADD, ( x ) ) +#define MULT_( x ) OP_COUNT_( _MULT, ( x ) ) +#define MAC_( x ) OP_COUNT_( _MAC, ( x ) ) +#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) ) +#define STORE_( x ) OP_COUNT_( _STORE, ( x ) ) +#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) ) +#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) ) +#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) ) +#define DIV_( x ) OP_COUNT_( _DIV, ( x ) ) +#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) ) +#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) ) #define POWER_( x ) TRANS_( x ) #define LOG_( x ) TRANS_( x ) -#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) / WMOPS_BOOST_FAC ) -#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) / WMOPS_BOOST_FAC ) -#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) / WMOPS_BOOST_FAC ) -#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) / WMOPS_BOOST_FAC ), OP_COUNT_( _FUNC, 1 ) ) +#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) ) +#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) ) +#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) ) +#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) ) #define MISC_( x ) ABS_( x ) /* Math Operations */ #define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs ) #define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs ) +#define fabsf_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabsf ) #define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs ) #define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor ) #define floorf_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floorf ) diff --git a/src/wmc_tool/wmc_auto_c.txt b/src/wmc_tool/wmc_auto_c.txt index 9a76a24..7d78d11 100644 --- a/src/wmc_tool/wmc_auto_c.txt +++ b/src/wmc_tool/wmc_auto_c.txt @@ -42,6 +42,8 @@ "#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */\r\n" "#define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */\r\n" "#define DOUBLE_MAX 0x80000000\r\n" +"#define FAC ( FRAMES_PER_SECOND / 1e6 )\r\n" +"\r\n" "\r\n" "typedef struct \r\n" "{\r\n" @@ -1903,8 +1905,8 @@ " }\r\n" " else\r\n" " {\r\n" -" /* bytes */\r\n" -" fprintf( stdout, \"Program ROM size (%s): %d bytes\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size << Stat_Cnt_Size );\r\n" +" /* bytes (here, we assume that each instruction takes PROM_INST_SIZE bits of the PROM memory) */\r\n" +" fprintf( stdout, \"Program ROM size (%s): %d bytes\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size * ( PROM_INST_SIZE / 8 ) );\r\n" " }\r\n" " }\r\n" "\r\n" @@ -1994,10 +1996,15 @@ " mem_count_summary();\r\n" "#endif\r\n" "\r\n" -" if ( Stat_Cnt_Size == 0 )\r\n" +" if ( Stat_Cnt_Size > 0 )\r\n" +" {\r\n" +" /* words */\r\n" +" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", 8 << Stat_Cnt_Size );\r\n" +" }\r\n" +" else\r\n" " {\r\n" " /* bytes */\r\n" -" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bytes (%d bits)\\n\", 1 << Stat_Cnt_Size, 8 << Stat_Cnt_Size );\r\n" +" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", PROM_INST_SIZE );\r\n" " }\r\n" " fprintf( stdout, \"Note: The Data ROM size is calculated using the sizeof(type) built-in function\\n\" );\r\n" "\r\n" diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index 1950492..222e554 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -33,10 +33,8 @@ "#define INT_MAX 32767\r\n" "#endif\r\n" "\r\n" -"/* Real-time relationships */\r\n" "#define FRAMES_PER_SECOND 50.0 \r\n" -"#define WMOPS_BOOST_FAC ( 1.0f ) /* scaling factor for equalizing the difference between automatic and manual instrumentation */\r\n" -"#define FAC ( FRAMES_PER_SECOND / 1e6 * WMOPS_BOOST_FAC )\r\n" +"#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */\r\n" "\r\n" "#ifdef WMOPS\r\n" "enum instructions\r\n" @@ -662,24 +660,24 @@ "#endif\r\n" "\r\n" "/* Define all Macros without '{' & '}' (None of these should be called externally!) */\r\n" -"#define ABS_( x ) OP_COUNT_( _ABS, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define ADD_( x ) OP_COUNT_( _ADD, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define MULT_( x ) OP_COUNT_( _MULT, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define MAC_( x ) OP_COUNT_( _MAC, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define STORE_( x ) OP_COUNT_( _STORE, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define DIV_( x ) OP_COUNT_( _DIV, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) / WMOPS_BOOST_FAC )\r\n" +"#define ABS_( x ) OP_COUNT_( _ABS, ( x ) )\r\n" +"#define ADD_( x ) OP_COUNT_( _ADD, ( x ) )\r\n" +"#define MULT_( x ) OP_COUNT_( _MULT, ( x ) )\r\n" +"#define MAC_( x ) OP_COUNT_( _MAC, ( x ) )\r\n" +"#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) )\r\n" +"#define STORE_( x ) OP_COUNT_( _STORE, ( x ) )\r\n" +"#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) )\r\n" +"#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) )\r\n" +"#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) )\r\n" +"#define DIV_( x ) OP_COUNT_( _DIV, ( x ) )\r\n" +"#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) )\r\n" +"#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) )\r\n" "#define POWER_( x ) TRANS_( x )\r\n" "#define LOG_( x ) TRANS_( x )\r\n" -"#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) / WMOPS_BOOST_FAC )\r\n" -"#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) / WMOPS_BOOST_FAC ), OP_COUNT_( _FUNC, 1 ) )\r\n" +"#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) )\r\n" +"#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) )\r\n" +"#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) )\r\n" +"#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) )\r\n" "#define MISC_( x ) ABS_( x )\r\n" "\r\n" "/* Math Operations */\r\n" From ae8ccf28a98e8ab75e6af6fdefbc47d6206c1d80 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Thu, 14 Mar 2024 13:31:17 +0100 Subject: [PATCH 48/67] add support for frexp() and frexpf() functions at the cost of MISC(2) --- src/wmc_tool/c_parser.cpp | 2 +- src/wmc_tool/test_data/ref/wmc_auto.h | 2 ++ src/wmc_tool/wmc_auto_h.txt | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index d3ce5a2..b207c3c 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -135,7 +135,7 @@ "cos cosf sin sinf tan tanf " \ "acos acosf asin asinf atan atanf atan2 atan2f " \ "cosh coshf sinh sinhf tanh tanhf " \ - "fmod fmodf " \ + "fmod fmodf frexp frexpf " \ "min max Min Max MIN MAX " \ "sqr Sqr SQR square Square SQUARE " \ "sign Sign SIGN " \ diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index 3b47cee..41e09b8 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.h +++ b/src/wmc_tool/test_data/ref/wmc_auto.h @@ -719,6 +719,8 @@ static int wmc_flag_ = 0; #define tanhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanhf ) #define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod ) #define fmodf_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmodf ) +#define frexp_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexp ) +#define frexpf_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexpf ) /* the macros below are instrumented versions of user-defined macros that might be used in the source code /* representing some well-known and recognized mathematical operations (that are not defined in math.h) */ diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index 222e554..c05c23d 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -719,6 +719,8 @@ "#define tanhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanhf )\r\n" "#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod )\r\n" "#define fmodf_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmodf )\r\n" +"#define frexp_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexp )\r\n" +"#define frexpf_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexpf )\r\n" "\r\n" "/* the macros below are instrumented versions of user-defined macros that might be used in the source code \r\n" "/* representing some well-known and recognized mathematical operations (that are not defined in math.h) */\r\n" From c2316471f3e69dd0f19301fcb79071fb3a18a9d9 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 19 Mar 2024 08:47:20 +0100 Subject: [PATCH 49/67] include the variants of log2() and round() functions --- src/wmc_tool/c_parser.cpp | 38 +++++++++++++-------------- src/wmc_tool/test_data/ref/wmc_auto.h | 3 +++ src/wmc_tool/wmc_auto_h.txt | 3 +++ 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index b207c3c..0a4a5e2 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -121,25 +121,25 @@ #define SYSTEM_ALLOC_FUNCTS_STRING \ "malloc calloc free " -#define SYSTEM_FUNCTS_STRING \ - "printf fprintf " \ - "fopen fclose fwrite fread " \ - "assert exit " - -#define MATH_FUNCTS_STRING \ - "abs fabs fabsf labs " \ - "floor floorf " \ - "sqrt sqrtf inv_sqrt inv_sqrtf " \ - "pow powf exp expf " \ - "log logf log10 log10f log_base_2 log2 log2_f " \ - "cos cosf sin sinf tan tanf " \ - "acos acosf asin asinf atan atanf atan2 atan2f " \ - "cosh coshf sinh sinhf tanh tanhf " \ - "fmod fmodf frexp frexpf " \ - "min max Min Max MIN MAX " \ - "sqr Sqr SQR square Square SQUARE " \ - "sign Sign SIGN " \ - "_round round_f " \ +#define SYSTEM_FUNCTS_STRING \ + "printf fprintf " \ + "fopen fclose fwrite fread " \ + "assert exit " + +#define MATH_FUNCTS_STRING \ + "abs fabs fabsf labs " \ + "floor floorf " \ + "sqrt sqrtf inv_sqrt inv_sqrtf " \ + "pow powf exp expf " \ + "log logf log10 log10f log_base_2 log2 log2f log2_f " \ + "cos cosf sin sinf tan tanf " \ + "acos acosf asin asinf atan atanf atan2 atan2f " \ + "cosh coshf sinh sinhf tanh tanhf " \ + "fmod fmodf frexp frexpf " \ + "min max Min Max MIN MAX " \ + "sqr Sqr SQR square Square SQUARE " \ + "sign Sign SIGN " \ + "_round round round_f roundf " \ "set_min set_max " #define BASOP_FUNCTS_STRING \ diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index 41e09b8..3dae42b 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.h +++ b/src/wmc_tool/test_data/ref/wmc_auto.h @@ -745,9 +745,12 @@ static int wmc_flag_ = 0; #define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrtf( ( x ) ) ) #define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) ) #define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) ) +#define log2f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2f( ( x ) ) ) #define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) ) #define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) ) +#define round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round( ( x ) ) ) #define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) ) +#define roundf_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, roundf( ( x ) ) ) #define set_min_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_min( ( a ), ( b ) ) ) #define set_max_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_max( ( a ), ( b ) ) ) diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index c05c23d..e8d3c33 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -745,9 +745,12 @@ "#define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrtf( ( x ) ) )\r\n" "#define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) )\r\n" "#define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) )\r\n" +"#define log2f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2f( ( x ) ) )\r\n" "#define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) )\r\n" "#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) )\r\n" +"#define round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round( ( x ) ) )\r\n" "#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) )\r\n" +"#define roundf_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, roundf( ( x ) ) )\r\n" "#define set_min_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_min( ( a ), ( b ) ) )\r\n" "#define set_max_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_max( ( a ), ( b ) ) )\r\n" "\r\n" From e7a4a8aa325695ab1b7957fa54d93db3da21a234 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 19 Mar 2024 09:34:37 +0100 Subject: [PATCH 50/67] Update wmc_tool.tex add explanation about where to place the push_wmops() function calls --- doc/manual/wmc_tool.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/wmc_tool.tex b/doc/manual/wmc_tool.tex index 4e0994a..2274b7d 100644 --- a/doc/manual/wmc_tool.tex +++ b/doc/manual/wmc_tool.tex @@ -438,7 +438,7 @@ \subsection{Complexity of functions and functional blocks} } \end{Verbatim} -The string inside each \verb|push_wmops()| macro shall be unique in the entire project and reflect what is being measured. It does not need to be the same as the name of the function in which it is used. The macro \verb|pop_wmops()| must \textbf{ALWAYS} be used to terminate the complexity counters associated with each \verb|push_wmops()| macro. The WMC tool supports nesting of these macro pairs. Note, that the \verb|push_wmops()| and the \verb|pop_wmops()| macros do not need to be encapsulated within the \verb|#define WMC_TOOL_SKIP| \ldots \verb|#undef WMC_TOOL_SKIP| macro pairs. +The \verb|push_wmops()| macro must be placed after the declaration of local variables. The string inside each \verb|push_wmops()| macro shall be unique in the entire project and reflect what is being measured. It does not need to be the same as the name of the function in which it is used. The macro \verb|pop_wmops()| must \textbf{ALWAYS} be used to terminate the complexity counters associated with each \verb|push_wmops()| macro. The WMC tool supports nesting of these macro pairs. Note, that the \verb|push_wmops()| and the \verb|pop_wmops()| macros do not need to be encapsulated within the \verb|#define WMC_TOOL_SKIP| \ldots \verb|#undef WMC_TOOL_SKIP| macro pairs. %----------------------------------------------------------------------------- \subsection{Printing statistics about computational complexity} From c78022107bf60d37664ea37331e2552236612eac Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Wed, 20 Mar 2024 10:46:11 +0100 Subject: [PATCH 51/67] update the WMC tool manual with additional info on how to format the source code --- doc/manual/wmc_tool.tex | 60 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/doc/manual/wmc_tool.tex b/doc/manual/wmc_tool.tex index 2274b7d..a4c85a9 100644 --- a/doc/manual/wmc_tool.tex +++ b/doc/manual/wmc_tool.tex @@ -110,7 +110,9 @@ \subsubsection{Warnings} \section{Instrumentation of complexity} \label{ch:instrumentation_of_complexity} -The WMC tool only instruments functions but not macros. System functions and functions with names that are considered as basic operations are skipped. The instrumentation mechanism has been designed to be as least intrusive as possible. The instrumentation code is inserted at the beginning of each instrumented line in the source code with a single macro that has the following form \verb|$("ops")| where \verb|ops| is a string of letters and symbols indicating individual operations. The WMC tool parses each source file and calculates the length of each instrumentation string. The maximum length is then used to indent the entire source file to make space for the instrumentation strings. This is shown in the example below. +The instrumentation mechanism has been designed to minimize intrusiveness. It skips system functions and functions labeled as basic operations. When instrumenting \verb|.c| source files, the WMC tool omits macros by default. However, it detects macros defined within the same \verb|.c| source file using the \verb|#define| pragma. Macros defined in external header files and included using \verb|#include| pragma cannot be directly detected. To address this, the instrumentation mechanism employs a heuristic: if a string contains more than 70\% capital letters, it's treated as a macro and skipped during instrumentation. + +The instrumentation code is integrated at the start of every instrumented line in the source code using a singular macro format: \verb|$("ops")|, where \verb|ops| represents a string encompassing individual operations denoted by letters and symbols. Upon parsing each source file, the WMC tool computes the length of each instrumentation string. Subsequently, the maximum length determines the indentation of the entire source file to accommodate the instrumentation strings, as illustrated in the example below. \begin{Verbatim}[fontsize=\small] float calc_shift_value( const float totalStep ) @@ -128,13 +130,13 @@ \section{Instrumentation of complexity} } \end{Verbatim} -It is always possible to remove the instrumentation from the source code with the \verb|-d| command line option. In many cases, the source file will then return to its original non-instrumented state except for whitespace characters and text alignment. The un-instrumentation process is also invoked automatically by the WMC tool as the first step in the instrumentation process. This ensures that the results are identical even when the process is repeated multiple times. This allows the users to make modifications to an already instrumented source code by simply re-instrumenting it again. Note, that the un-instrumentation process does not remove the functions \verb|push_wmops()| and \verb|pop_wmops()| and the system functions. Lines that are preceded by +The removal of instrumentation from the source code can be achieved using the \verb|-d| command line option. In many instances, executing this option restores the source file to its original non-instrumented state, with the exception of whitespace characters and text alignment. The un-instrumentation process is automatically triggered by the WMC tool as the initial step in the instrumentation procedure. This ensures consistent results even with repeated executions. Consequently, users can modify previously instrumented source code by simply re-instrumenting it. It's important to note that the un-instrumentation process does not eliminate the \verb|push_wmops()| and \verb|pop_wmops()| functions, nor does it remove system functions. Lines preceded by { {\em /*AddedByWMC\_Tool*/} } -are removed completely. At the end of the un-instrumentation process, the original indentation is restored. +are removed completely. At the end of the un-instrumentation process the original indentation is restored. If, for any reason, it is necessary to avoid the automatic instrumentation and un-instrumentation of certain parts in the source code, the user may encapsulate such parts in \verb|#define WMC_TOOL_SKIP| \ldots \verb|#undef WMC_TOOL_SKIP| macro pairs. For example @@ -227,18 +229,21 @@ \subsection{Mathematic functions} \verb|sign()| & 1 \\ \verb|round()| & 0 (not supported by the WMC tool) \\ \verb|sqrt()| and \verb|inv_sqrt()| & 10 \\ -\verb|log()|, \verb|log2()| and thier derivatives & 25 \\ +\verb|log()|, \verb|log2()| and other logarithmic functions & 25 \\ \verb|exp()| and \verb|pow()| & 25 \\ \verb|sin()|, \verb|cos()| and all other trigonometric functions & 25 \\ +\verb|frexp()| & 2 \\ +\verb|fmod()| & 18 \\ \hline \end{tabular} \label{tab:cost_of_math_functions} \end{table} + %----------------------------------------------------------------------------- \subsection{User-defined functions} -All user-defined functions in the source code are instrumented with one or more underscore '\verb|_|' symbols appended to their names. The WMC tool will count the number of arguments from the function call and insert a wrapper macro at the top of the source file, after the first \verb|#include| section. See the example below. +All user-defined functions in the source code are instrumented with one or more underscore '\verb|_|' symbols appended to their names. The WMC tool counts the number of arguments in function calls and inserts a wrapper macro at the top of the source file, after the first \verb|#include| section. See the example below. \begin{Verbatim}[fontsize=\small] #include @@ -269,6 +274,49 @@ \subsection{User-defined functions} The WMC tool appends an additional underscore symbol '\verb|_|' in each variant of the user-defined function call. This means that if a function is defined to accept a variable number of arguments the first function call will have one underscore symbol '\verb|_|' appended to its name, the second function call will have two underscore symbols '\verb|__|' appended to its name and so on. The WMC tool supports up to 10 variants (different number of arguments) of the same function. +The WMC tool may encounter difficulties in properly instrumenting one-line functions that are defined as follows + +\begin{Verbatim}[fontsize=\small] + float calculate_vector_norm( float vec[], int_16t size ) { return sum2_f(vec, size); } +\end{Verbatim} + +It's advisable to define the function body on separate lines, like this + +\begin{Verbatim}[fontsize=\small] + float calculate_vector_norm( float vec[], int_16t size ) + { + return sum2_f(vec, size); + } +\end{Verbatim} + +In a local function, all declared variables should be positioned at the start of the function body. Additionally, the initialization of local variables should be segregated from their declaration. For instance, consider the following code snippet, where the WMC tool inserts \verb|$("M")| before \verb|int ch = 0;| + +\begin{Verbatim}[fontsize=\small] + int free_structs(MY_STRUCT_INFO *ptr_dec) + { + if (ptr_dec == NULL) return -1; + +$("M") int ch = 0; + + for (ch = 0; ch < n_channels; ch++) + { + struct_free(&decoder->cfg[ch]->fft_buf); + struct_free(&decoder->cfg[ch]->ifft_buf); + } + + return 0; + } +\end{Verbatim} + +Compiling the instrumented code provided above results in the following error (gcc): + +\begin{Verbatim}[fontsize=\small] +lib_thj/struct_f.c:373:17: error: expected expression before ‘int’ + 125 | $("M") int ch = 0; + | ^~~ +\end{Verbatim} + + %----------------------------------------------------------------------------- \subsection{Operators} @@ -364,7 +412,7 @@ \subsection{Operators} %----------------------------------------------------------------------------- \subsection{Manual instrumentation} -It was already shown in the previous section in this document that it is possible to avoid the automatic instrumentation by encapsulating parts of the source code with +As demonstrated in the preceding section of this document, it's possible to bypass automatic instrumentation by encapsulating sections of the source code with \begin{Verbatim}[fontsize=\small] #define WMC_TOOL_SKIP From dba570adf0a3d30bf79bd921cdf10154d7e3be7b Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 20 Mar 2024 13:35:47 +0100 Subject: [PATCH 52/67] fix error when des-instrumenting one-line functions --- src/wmc_tool/c_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 0a4a5e2..79f1101 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -7245,7 +7245,7 @@ TOOL_ERROR DesInstrument( { /* Yes */ /* Go To Start of Line */ tmp = ParseRec_ptr->item_start; - while ( --tmp, !IS_EOL_CHAR( *tmp ) ) + while ( --tmp, (IS_SPACE_CHAR( *tmp ) && !IS_EOL_CHAR( *tmp )) ) ; /* Advance (Past EOS) */ ptr += 2; From 3e31f8dec86d8f27551498c1b5a0ec98a202076c Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Wed, 20 Mar 2024 17:03:13 +0100 Subject: [PATCH 53/67] fix the limitation of max string literals to 65535 with MSVC 2017 and older versions --- src/wmc_tool/wmc_auto_c.txt | 4344 +++++++++++++++++------------------ src/wmc_tool/wmc_auto_h.txt | 2896 +++++++++++------------ src/wmc_tool/wmc_tool.cpp | 65 +- 3 files changed, 3666 insertions(+), 3639 deletions(-) diff --git a/src/wmc_tool/wmc_auto_c.txt b/src/wmc_tool/wmc_auto_c.txt index 7d78d11..1b3b85e 100644 --- a/src/wmc_tool/wmc_auto_c.txt +++ b/src/wmc_tool/wmc_auto_c.txt @@ -1,2172 +1,2172 @@ -"/*\r\n" -" * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved.\r\n" -" *\r\n" -" * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n" -" * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n" -" * or refer to ITU-T Recommendation G.191 on \"SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS\".\r\n" -" *\r\n" -" * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor\r\n" -" * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software\r\n" -" * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE.\r\n" -" *\r\n" -" * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca)\r\n" -" */\r\n" -"\r\n" -"#include \r\n" -"#include \r\n" -"#include \r\n" -"#include \r\n" -"#include \r\n" -"\r\n" -"#ifndef _MSC_VER\r\n" -"#include \r\n" -"#include \r\n" -"#else\r\n" -"#include \r\n" -"#endif\r\n" -"\r\n" -"#include \"options.h\"\r\n" -"#include \"wmc_auto.h\"\r\n" -"\r\n" -"#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */\r\n" -"\r\n" -"#ifdef WMOPS\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * Complexity counting tool\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"#define MAX_FUNCTION_NAME_LENGTH 50 /* Maximum length of the function name */\r\n" -"#define MAX_PARAMS_LENGTH 50 /* Maximum length of the function parameter string */\r\n" -"#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> mightb be increased during runtime, if needed */\r\n" -"#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */\r\n" -"#define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */\r\n" -"#define DOUBLE_MAX 0x80000000\r\n" -"#define FAC ( FRAMES_PER_SECOND / 1e6 )\r\n" -"\r\n" -"\r\n" -"typedef struct \r\n" -"{\r\n" -" char label[MAX_FUNCTION_NAME_LENGTH];\r\n" -" long call_number;\r\n" -" long update_cnt;\r\n" -" int call_tree[MAX_CALL_TREE_DEPTH];\r\n" -" long LastWOper;\r\n" -" double start_selfcnt;\r\n" -" double current_selfcnt;\r\n" -" double max_selfcnt;\r\n" -" double min_selfcnt;\r\n" -" double tot_selfcnt;\r\n" -" double start_cnt; \r\n" -" double current_cnt;\r\n" -" double max_cnt;\r\n" -" double min_cnt;\r\n" -" double tot_cnt;\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" int32_t current_call_number;\r\n" -" double wc_cnt;\r\n" -" double wc_selfcnt;\r\n" -" int32_t wc_call_number;\r\n" -"#endif\r\n" -"} wmops_record;\r\n" -"\r\n" -"double ops_cnt;\r\n" -"double prom_cnt;\r\n" -"double inst_cnt[NUM_INST];\r\n" -"\r\n" -"static wmops_record *wmops = NULL;\r\n" -"static int num_wmops_records, max_num_wmops_records;\r\n" -"static int current_record;\r\n" -"static long update_cnt;\r\n" -"static double start_cnt;\r\n" -"static double max_cnt;\r\n" -"static double min_cnt;\r\n" -"static double inst_cnt_wc[NUM_INST];\r\n" -"static long fnum_cnt_wc;\r\n" -"static int *wmops_caller_stack = NULL, wmops_caller_stack_index, max_wmops_caller_stack_index = 0;\r\n" -"static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0;\r\n" -"\r\n" -"void reset_wmops( void )\r\n" -"{\r\n" -" int i, j;\r\n" -" unsigned int *ptr;\r\n" -"\r\n" -" num_wmops_records = 0;\r\n" -" max_num_wmops_records = MAX_NUM_RECORDS;\r\n" -" current_record = -1;\r\n" -" update_cnt = 0;\r\n" -"\r\n" -" max_cnt = 0.0;\r\n" -" min_cnt = DOUBLE_MAX;\r\n" -" start_cnt = 0.0;\r\n" -" ops_cnt = 0.0;\r\n" -"\r\n" -" /* allocate the list of wmops records */\r\n" -" if ( wmops == NULL )\r\n" -" {\r\n" -" wmops = (wmops_record *)malloc( max_num_wmops_records * sizeof( wmops_record ) );\r\n" -" }\r\n" -"\r\n" -" if ( wmops == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Records!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* allocate the BASOP WMOPS counter */\r\n" -" if ( multiCounter == NULL )\r\n" -" {\r\n" -" multiCounter = (BASIC_OP *) malloc( max_num_wmops_records * sizeof( BASIC_OP ) );\r\n" -" }\r\n" -"\r\n" -" if ( multiCounter == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Unable to Allocate the BASOP WMOPS counter!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* initilize the list of wmops records */\r\n" -" /* initilize the BASOP WMOPS counters */\r\n" -" for ( i = 0; i < max_num_wmops_records; i++ )\r\n" -" {\r\n" -" strcpy( &wmops[i].label[0], \"\\0\" );\r\n" -" wmops[i].call_number = 0;\r\n" -" wmops[i].update_cnt = 0;\r\n" -" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n" -" {\r\n" -" wmops[i].call_tree[j] = -1;\r\n" -" }\r\n" -" wmops[i].start_selfcnt = 0.0;\r\n" -" wmops[i].current_selfcnt = 0.0;\r\n" -" wmops[i].max_selfcnt = 0.0;\r\n" -" wmops[i].min_selfcnt = DOUBLE_MAX;\r\n" -" wmops[i].tot_selfcnt = 0.0;\r\n" -" wmops[i].start_cnt = 0.0;\r\n" -" wmops[i].current_cnt = 0.0;\r\n" -" wmops[i].max_cnt = 0.0;\r\n" -" wmops[i].min_cnt = DOUBLE_MAX;\r\n" -" wmops[i].tot_cnt = 0.0;\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" wmops[i].wc_cnt = 0.0;\r\n" -" wmops[i].wc_selfcnt = 0.0;\r\n" -" wmops[i].current_call_number = 0;\r\n" -" wmops[i].wc_call_number = -1;\r\n" -"#endif\r\n" -"\r\n" -" /* clear all BASOP operation counters */\r\n" -" ptr = (unsigned int*) &multiCounter[i];\r\n" -" for ( j = 0; j < (int) ( sizeof(BASIC_OP ) / sizeof( unsigned int ) ); j++ )\r\n" -" {\r\n" -" *ptr++ = 0;\r\n" -" }\r\n" -" wmops[i].LastWOper = 0;\r\n" -" }\r\n" -"\r\n" -" /* allocate the list of wmops callers to track the sequence of function calls */\r\n" -" wmops_caller_stack_index = 0;\r\n" -" max_wmops_caller_stack_index = MAX_NUM_RECORDS;\r\n" -" if ( wmops_caller_stack == NULL )\r\n" -" {\r\n" -" wmops_caller_stack = malloc( max_wmops_caller_stack_index * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" if ( wmops_caller_stack == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Callers!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" for ( i = 0; i < max_wmops_caller_stack_index; i++ )\r\n" -" {\r\n" -" wmops_caller_stack[i] = -1;\r\n" -" }\r\n" -"\r\n" -" /* initialize auxiliary BASOP WMOPS variables */\r\n" -" call_occurred = 1;\r\n" -" funcId_where_last_call_to_else_occurred = INT_MAX;\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"\r\n" -"void push_wmops( const char *label )\r\n" -"{\r\n" -" int new_flag;\r\n" -" int i, j;\r\n" -"\r\n" -" /* Check, if this is a new function label */\r\n" -" new_flag = 1;\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" if ( strcmp( wmops[i].label, label ) == 0 )\r\n" -" {\r\n" -" new_flag = 0;\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Create a new record in the list */\r\n" -" if ( new_flag )\r\n" -" {\r\n" -" if ( num_wmops_records >= max_num_wmops_records )\r\n" -" {\r\n" -" /* There is no room for a new wmops record -> reallocate the list */\r\n" -" max_num_wmops_records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" wmops = realloc( wmops, max_num_wmops_records * sizeof( wmops_record ) );\r\n" -" multiCounter = realloc( multiCounter, max_num_wmops_records * sizeof( BASIC_OP ) );\r\n" -" }\r\n" -"\r\n" -" strcpy( wmops[i].label, label );\r\n" -"\r\n" -" num_wmops_records++;\r\n" -" }\r\n" -"\r\n" -" /* Push the current context info to the new record */\r\n" -" if ( current_record >= 0 )\r\n" -" {\r\n" -" if ( wmops_caller_stack_index >= max_wmops_caller_stack_index )\r\n" -" {\r\n" -" /* There is no room for a new record -> reallocate the list */\r\n" -" max_wmops_caller_stack_index += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" wmops_caller_stack = realloc( wmops_caller_stack, max_wmops_caller_stack_index * sizeof( int ) );\r\n" -" }\r\n" -" wmops_caller_stack[wmops_caller_stack_index++] = current_record;\r\n" -"\r\n" -" /* accumulate op counts */\r\n" -" wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n" -"\r\n" -" /* update call tree */\r\n" -" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n" -" {\r\n" -" if ( wmops[i].call_tree[j] == current_record )\r\n" -" {\r\n" -" break;\r\n" -" }\r\n" -" else if ( wmops[i].call_tree[j] == -1 )\r\n" -" {\r\n" -" wmops[i].call_tree[j] = current_record;\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* update the current context info */\r\n" -" current_record = i;\r\n" -" wmops[current_record].start_selfcnt = ops_cnt;\r\n" -" wmops[current_record].start_cnt = ops_cnt;\r\n" -" wmops[current_record].call_number++;\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" wmops[current_record].current_call_number++;\r\n" -"#endif\r\n" -"\r\n" -" /* set the ID of BASOP functions counters */\r\n" -" Set_BASOP_WMOPS_counter( current_record );\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"\r\n" -"void pop_wmops( void )\r\n" -"{\r\n" -" long tot;\r\n" -"\r\n" -" /* Check for underflow */\r\n" -" if ( current_record < 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"\\r pop_wmops(): stack underflow, too many calls to pop_wmops()\\n\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* add the BASOP complexity to the counter */\r\n" -" tot = DeltaWeightedOperation();\r\n" -" ops_cnt += tot;\r\n" -"\r\n" -" /* update count of current record */\r\n" -" wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n" -" wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt;\r\n" -"\r\n" -" /* Get back previous context from stack */\r\n" -" if ( wmops_caller_stack_index > 0 )\r\n" -" {\r\n" -" current_record = wmops_caller_stack[--wmops_caller_stack_index];\r\n" -" wmops[current_record].start_selfcnt = ops_cnt;\r\n" -"\r\n" -" /* set the ID of the previous BASOP counter */\r\n" -" Set_BASOP_WMOPS_counter( current_record );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" current_record = -1;\r\n" -" }\r\n" -"\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"\r\n" -"void update_wmops( void )\r\n" -"{\r\n" -" int i;\r\n" -" double current_cnt;\r\n" -"#ifdef WMOPS_PER_FRAME\r\n" -" static FILE *fid = NULL;\r\n" -" const char filename[] = \"wmops_analysis\";\r\n" -" float tmpF;\r\n" -"#endif\r\n" -"\r\n" -" if ( wmops_caller_stack_index != 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"update_wmops(): WMOPS caller stack corrupted - check that all push_wmops() are matched with pop_wmops()!\\n\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -"#ifdef WMOPS_PER_FRAME\r\n" -" /* Check, if the output file has already been opened */\r\n" -" if ( fid == NULL )\r\n" -" {\r\n" -" fid = fopen( filename, \"wb\" );\r\n" -"\r\n" -" if ( fid == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", filename );\r\n" -" exit( -1 );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Write current complexity to the external file */\r\n" -" tmpF = (float) ( FAC * wmops[0].current_cnt );\r\n" -" fwrite( &tmpF, sizeof( float ), 1, fid );\r\n" -"#endif\r\n" -"\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" if ( ops_cnt - start_cnt > max_cnt )\r\n" -" {\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" wmops[i].wc_cnt = wmops[i].current_cnt;\r\n" -" wmops[i].wc_selfcnt = wmops[i].current_selfcnt;\r\n" -" wmops[i].wc_call_number = wmops[i].current_call_number;\r\n" -" }\r\n" -" }\r\n" -"#endif\r\n" -"\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" wmops[i].tot_selfcnt += wmops[i].current_selfcnt;\r\n" -" wmops[i].tot_cnt += wmops[i].current_cnt;\r\n" -"\r\n" -" if ( wmops[i].current_selfcnt > 0 )\r\n" -" {\r\n" -" if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt )\r\n" -" {\r\n" -" wmops[i].max_selfcnt = wmops[i].current_selfcnt;\r\n" -" }\r\n" -"\r\n" -" if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt )\r\n" -" {\r\n" -" wmops[i].min_selfcnt = wmops[i].current_selfcnt;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" wmops[i].current_selfcnt = 0;\r\n" -"\r\n" -" if ( wmops[i].current_cnt > 0 )\r\n" -" {\r\n" -" if ( wmops[i].current_cnt > wmops[i].max_cnt )\r\n" -" {\r\n" -" wmops[i].max_cnt = wmops[i].current_cnt;\r\n" -" }\r\n" -"\r\n" -"\r\n" -" if ( wmops[i].current_cnt < wmops[i].min_cnt )\r\n" -" {\r\n" -" wmops[i].min_cnt = wmops[i].current_cnt;\r\n" -" }\r\n" -"\r\n" -" wmops[i].update_cnt++;\r\n" -" }\r\n" -"\r\n" -" wmops[i].current_cnt = 0;\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" wmops[i].current_call_number = 0;\r\n" -"#endif\r\n" -"\r\n" -" /* update the WC of all BASOP counters */\r\n" -" Set_BASOP_WMOPS_counter( i );\r\n" -" Reset_BASOP_WMOPS_counter();\r\n" -" }\r\n" -"\r\n" -" current_cnt = ops_cnt - start_cnt;\r\n" -" if ( current_cnt > max_cnt )\r\n" -" {\r\n" -" max_cnt = current_cnt;\r\n" -"\r\n" -" for ( i = 0; i < NUM_INST; i++ )\r\n" -" {\r\n" -" inst_cnt_wc[i] = inst_cnt[i];\r\n" -" }\r\n" -"\r\n" -" fnum_cnt_wc = update_cnt + 1;\r\n" -" }\r\n" -"\r\n" -" if ( current_cnt < min_cnt )\r\n" -" {\r\n" -" min_cnt = current_cnt;\r\n" -" }\r\n" -"\r\n" -" for ( i = 0; i < NUM_INST; i++ )\r\n" -" {\r\n" -" inst_cnt[i] = 0.0;\r\n" -" }\r\n" -"\r\n" -" start_cnt = ops_cnt;\r\n" -"\r\n" -" /* increment frame counter */\r\n" -" update_cnt++;\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"\r\n" -"void print_wmops( void )\r\n" -"{\r\n" -" int i, label_len, max_label_len;\r\n" -"\r\n" -" char *sfmts = \"%*s %8s %8s %7s %7s\\n\";\r\n" -" char *dfmts = \"%*s %8.2f %8.3f %7.3f %7.3f\\n\";\r\n" -" char *sfmt = \"%*s %8s %8s %7s %7s %7s %7s %7s\\n\";\r\n" -" char *dfmt = \"%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\\n\";\r\n" -"\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" int j;\r\n" -" char *sfmtt = \"%20s %4s %15s\\n\";\r\n" -" char *dfmtt = \"%20s %4d \";\r\n" -"#endif\r\n" -"\r\n" -" /* calculate maximum label length for compact prinout */\r\n" -" max_label_len = 0;\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" label_len = strlen( wmops[i].label );\r\n" -" if ( label_len > max_label_len )\r\n" -" {\r\n" -" max_label_len = label_len;\r\n" -" }\r\n" -" }\r\n" -" max_label_len += 4;\r\n" -"\r\n" -" fprintf( stdout, \"\\n\\n --- Complexity analysis [WMOPS] --- \\n\\n\" );\r\n" -" \r\n" -" fprintf( stdout, \"%*s %33s %23s\\n\", max_label_len, \"\", \"|------ SELF ------|\", \"|--- CUMULATIVE ---|\" );\r\n" -" fprintf( stdout, sfmt, max_label_len, \" routine\", \" calls\", \" min \", \" max \", \" avg \", \" min \", \" max \", \" avg \" );\r\n" -" fprintf( stdout, sfmt, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\" );\r\n" -"\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" fprintf( stdout, dfmt, max_label_len, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt,\r\n" -" wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt,\r\n" -" FAC * wmops[i].max_selfcnt,\r\n" -" wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt,\r\n" -" wmops[i].min_cnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_cnt,\r\n" -" FAC * wmops[i].max_cnt,\r\n" -" wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt );\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, sfmts, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\" );\r\n" -" fprintf( stdout, dfmts, max_label_len, \"total\", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt );\r\n" -" fprintf( stdout, \"\\n\" );\r\n" -"\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" fprintf( stdout, \"\\nComplexity analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n" -" fprintf( stdout, \"%*s %8s %10s %12s\\n\", max_label_len, \" routine\", \" calls\", \" SELF\", \" CUMULATIVE\" );\r\n" -" fprintf( stdout, \"%*s %8s %10s %10s\\n\", max_label_len, \"---------------\", \"------\", \"------\", \"----------\" );\r\n" -"\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" if ( wmops[i].wc_call_number > 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"%*s %8d %10.3f %12.3f\\n\", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, \"\\nCall tree for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n" -" fprintf( stdout, sfmtt, \" function\", \"num\", \"called by \" );\r\n" -" fprintf( stdout, sfmtt, \"---------------\", \"---\", \"--------------\" );\r\n" -"\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" if ( wmops[i].wc_call_number > 0 )\r\n" -" {\r\n" -" fprintf( stdout, dfmtt, wmops[i].label, i );\r\n" -" for ( j = 0; wmops[i].call_tree[j] != -1 && j < MAX_CALL_TREE_DEPTH; j++ )\r\n" -" {\r\n" -" if ( j != 0 )\r\n" -" {\r\n" -" fprintf( stdout, \", \" );\r\n" -" }\r\n" -" fprintf( stdout, \"%d\", wmops[i].call_tree[j] );\r\n" -" }\r\n" -" fprintf( stdout, \"\\n\" );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, \"\\n\\n\" );\r\n" -"\r\n" -" fprintf( stdout, \"\\nInstruction type analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc ); \r\n" -" for ( i = 0; i < NUM_INST; i++ )\r\n" -" {\r\n" -" switch ( (enum instructions) i )\r\n" -" {\r\n" -" case _ADD:\r\n" -" fprintf( stdout, \"\\tAdds: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _ABS:\r\n" -" fprintf( stdout, \"\\tAbsolutes: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _MULT:\r\n" -" fprintf( stdout, \"\\tMultiplies: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _MAC:\r\n" -" fprintf( stdout, \"\\tMACs: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _MOVE:\r\n" -" fprintf( stdout, \"\\tMoves: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _STORE:\r\n" -" fprintf( stdout, \"\\tStores: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _LOGIC:\r\n" -" fprintf( stdout, \"\\tLogicals: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _SHIFT:\r\n" -" fprintf( stdout, \"\\tShifts: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _BRANCH:\r\n" -" fprintf( stdout, \"\\tBranches: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _DIV:\r\n" -" fprintf( stdout, \"\\tDivisions: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _SQRT:\r\n" -" fprintf( stdout, \"\\tSquare Root: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _TRANS:\r\n" -" fprintf( stdout, \"\\tTrans: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _FUNC:\r\n" -" fprintf( stdout, \"\\tFunc Call: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _LOOP:\r\n" -" fprintf( stdout, \"\\tLoop Init: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _INDIRECT:\r\n" -" fprintf( stdout, \"\\tIndirect Addr: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _PTR_INIT:\r\n" -" fprintf( stdout, \"\\tPointer Init: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _TEST:\r\n" -" fprintf( stdout, \"\\tExtra condit.: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _POWER:\r\n" -" fprintf( stdout, \"\\tExponential: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _LOG:\r\n" -" fprintf( stdout, \"\\tLogarithm: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _MISC:\r\n" -" fprintf( stdout, \"\\tAll other op.: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" default:\r\n" -" fprintf( stdout, \"\\tERROR: Invalid instruction type: %d\\n\\n\", i );\r\n" -" }\r\n" -" }\r\n" -"#endif\r\n" -"\r\n" -" /* De-allocate the list of wmops record */\r\n" -" if ( wmops != NULL )\r\n" -" {\r\n" -" free( wmops );\r\n" -" }\r\n" -"\r\n" -" /* De-allocate the list of wmops caller functions */\r\n" -" if ( wmops_caller_stack != NULL )\r\n" -" {\r\n" -" free( wmops_caller_stack );\r\n" -" }\r\n" -"\r\n" -" /* De-allocate the BASOP WMOPS counter */\r\n" -" if ( multiCounter != NULL )\r\n" -" {\r\n" -" free( multiCounter );\r\n" -" }\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * Memory counting tool measuring RAM usage (stack and heap)\r\n" -" *\r\n" -" * Maximum RAM is measured by monitoring the total allocated memory (stack and heap) in each frame.\r\n" -" *\r\n" -" * Maximum stack is measured by monitoring the difference between the 'top' and 'bottom' of the stack. The 'bottom' of the stack is updated in each function\r\n" -" * with a macro 'func_start_' which is inserted automatically to all functions during the instrumentation process.\r\n" -" *\r\n" -" * Maximum heap is measured by summing the sizes of all memory blocks allocated by malloc() or calloc() and deallocated by free(). The maximum heap size is\r\n" -" * updated each time when the macros malloc_() or calloc_() is invoked. The macros 'malloc_ and calloc_' are inserted automatically during the instrumentation process.\r\n" -" * As part of heap measurements, intra-frame heap and inter-frame heap are measured separately. Intra-frame heap refers to heap memory which is allocated and deallocated\r\n" -" * within a single frame. Inter-frame heap, on the contrary, refers to heap memory which is reserved for more than one frame.\r\n" -" *\r\n" -" * In order to run the memory counting tool the function reset_mem(cnt_size) must be called at the beginning of the encoding/decoding process.\r\n" -" * The unit in which memory consumption is reported is set via the parameter 'cnt_size'. It can be set to 0 (bytes), 1 (32b words) or 2 (64b words).\r\n" -" * At the end of the encoding/decoding process, 'print_mem()' function may be called to print basic information about memory consumption. If the macro 'MEM_COUNT_DETAILS'\r\n" -" * is activated, detailed information is printed\r\n" -" *\r\n" -" * The macro 'WMOPS' needs to be activated to enable memory counting. To avoid the instrumentation of malloc()/calloc()/free() calls, use\r\n" -" * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free().\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using\r\n" -" a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */\r\n" -"#ifdef MEM_ALIGN_64BITS\r\n" -"#define BLOCK_ROUNDING 8 /* Align on 64 Bits */\r\n" -"#else\r\n" -"#define BLOCK_ROUNDING 4 /* Align on 32 Bits */\r\n" -"#endif\r\n" -"\r\n" -"#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) )\r\n" -"#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) )\r\n" -"\r\n" -"#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */\r\n" -"#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */\r\n" -"#define OOB_START 0x1 /* Flag indicating out-of-bounds access before memory block */\r\n" -"#define OOB_END 0x2 /* Flag indicating out-of-bounds access after memory block */\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -"const char *csv_filename = \"mem_analysis.csv\";\r\n" -"static FILE *fid_csv_filename = NULL;\r\n" -"#endif\r\n" -"\r\n" -"typedef struct\r\n" -"{\r\n" -" char function_name[MAX_FUNCTION_NAME_LENGTH + 1];\r\n" -" int16_t *stack_ptr;\r\n" -"} caller_info;\r\n" -"\r\n" -"static caller_info *stack_callers[2] = {NULL, NULL};\r\n" -"\r\n" -"static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */\r\n" -"static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */\r\n" -"static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */\r\n" -"static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */\r\n" -"static int current_calls = 0, max_num_calls = MAX_NUM_RECORDS;\r\n" -"static char location_max_stack[256] = \"undefined\";\r\n" -"\r\n" -"/* Heap-related variables */\r\n" -"typedef struct\r\n" -"{\r\n" -" char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */\r\n" -" char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */\r\n" -" unsigned long hash;\r\n" -" int lineno;\r\n" -" void *block_ptr;\r\n" -" int block_size;\r\n" -" unsigned long total_block_size; /* Cumulative sum of the allocated size in the session */\r\n" -" unsigned long total_used_size; /* Cumulative sum of the used size in the session */\r\n" -" int wc_heap_size_intra_frame; /* Worst-Case Intra-Frame Heap Size */\r\n" -" int wc_heap_size_inter_frame; /* Worst-Case Inter-Frame Heap Size */\r\n" -" int frame_allocated; /* Frame number in which the Memory Block has been allocated (-1 if not allocated at the moment) */\r\n" -" int OOB_Flag;\r\n" -" int noccurances; /* Number of times that the memory block has been allocated in a frame */\r\n" -"} allocator_record;\r\n" -"\r\n" -"allocator_record *allocation_list = NULL;\r\n" -"\r\n" -"static int Num_Records, Max_Num_Records;\r\n" -"static size_t Stat_Cnt_Size = USE_BYTES;\r\n" -"static const char *Count_Unit[] = { \"bytes\", \"words\", \"words\", \"words\" };\r\n" -"\r\n" -"static int32_t wc_ram_size, wc_ram_frame;\r\n" -"static int32_t current_heap_size;\r\n" -"static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap;\r\n" -"static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap;\r\n" -"static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap;\r\n" -"\r\n" -"/* Local Functions */\r\n" -"static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str );\r\n" -"allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record );\r\n" -"static void *mem_alloc_block( size_t size, const char *size_str );\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * reset_mem()\r\n" -" *\r\n" -" * Initialize/reset memory counting tool (stack and heap)\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void reset_mem( Counting_Size cnt_size )\r\n" -"{\r\n" -" int16_t something;\r\n" -" size_t tmp_size;\r\n" -"\r\n" -" /* initialize list of stack records */\r\n" -" if ( stack_callers[0] == NULL )\r\n" -" {\r\n" -" stack_callers[0] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n" -" stack_callers[1] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n" -" }\r\n" -"\r\n" -" if ( stack_callers[0] == NULL || stack_callers[1] == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Unable to Allocate List of Stack Records!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" current_calls = 0;\r\n" -" max_num_calls = MAX_NUM_RECORDS;\r\n" -"\r\n" -" /* initialize stack pointers */\r\n" -" ptr_base_stack = &something;\r\n" -" ptr_max_stack = ptr_base_stack;\r\n" -" ptr_current_stack = ptr_base_stack;\r\n" -"\r\n" -" /* initialize the unit of memory block size */\r\n" -" Stat_Cnt_Size = cnt_size;\r\n" -"\r\n" -" /* Check, if sizeof(int32_t) is 4 bytes */\r\n" -" tmp_size = sizeof( int32_t );\r\n" -" if ( tmp_size != 4 )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Expecting 'int32_t' to be a 32 Bits Integer!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* create allocation list for malloc() memory blocks */\r\n" -" if ( allocation_list == NULL )\r\n" -" {\r\n" -" allocation_list = malloc( MAX_NUM_RECORDS * sizeof( allocator_record ) );\r\n" -" }\r\n" -"\r\n" -" if ( allocation_list == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Unable to Create List of Memory Blocks!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" Num_Records = 0;\r\n" -" Max_Num_Records = MAX_NUM_RECORDS;\r\n" -"\r\n" -" wc_ram_size = 0;\r\n" -" wc_ram_frame = -1;\r\n" -" current_heap_size = 0;\r\n" -"\r\n" -" /* heap allocation tree */\r\n" -" heap_allocation_call_tree_max_size = MAX_NUM_RECORDS;\r\n" -" if ( heap_allocation_call_tree == NULL )\r\n" -" {\r\n" -" heap_allocation_call_tree = (int *) malloc( heap_allocation_call_tree_max_size * sizeof( int ) );\r\n" -" memset( heap_allocation_call_tree, -1, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n" -" }\r\n" -" heap_allocation_call_tree_size = 0;\r\n" -"\r\n" -" /* wc intra-frame heap */\r\n" -" max_items_wc_intra_frame_heap = MAX_NUM_RECORDS;\r\n" -" if ( list_wc_intra_frame_heap == NULL )\r\n" -" {\r\n" -" list_wc_intra_frame_heap = (int *) malloc( max_items_wc_intra_frame_heap * sizeof( int ) );\r\n" -" memset( list_wc_intra_frame_heap, -1, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -" n_items_wc_intra_frame_heap = 0;\r\n" -" size_wc_intra_frame_heap = 0;\r\n" -" location_wc_intra_frame_heap = -1;\r\n" -"\r\n" -" /* current inter-frame heap */\r\n" -" max_items_current_inter_frame_heap = MAX_NUM_RECORDS;\r\n" -" if ( list_current_inter_frame_heap == NULL )\r\n" -" {\r\n" -" list_current_inter_frame_heap = (int *) malloc( max_items_current_inter_frame_heap * sizeof( int ) );\r\n" -" memset( list_current_inter_frame_heap, -1, max_items_current_inter_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -" n_items_current_inter_frame_heap = 0;\r\n" -" size_current_inter_frame_heap = 0;\r\n" -"\r\n" -" /* wc inter-frame heap */\r\n" -" max_items_wc_inter_frame_heap = MAX_NUM_RECORDS;\r\n" -" if ( list_wc_inter_frame_heap == NULL )\r\n" -" {\r\n" -" list_wc_inter_frame_heap = (int *) malloc( max_items_wc_inter_frame_heap * sizeof( int ) );\r\n" -" memset( list_wc_inter_frame_heap, -1, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -" n_items_wc_inter_frame_heap = 0;\r\n" -" size_wc_inter_frame_heap = 0;\r\n" -" location_wc_inter_frame_heap = -1;\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -" /* Check, if the .csv file has already been opened */\r\n" -" if ( fid_csv_filename == NULL )\r\n" -" {\r\n" -" fid_csv_filename = fopen( csv_filename, \"wb\" );\r\n" -"\r\n" -" if ( fid_csv_filename == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", csv_filename );\r\n" -" exit( -1 );\r\n" -" }\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" /* reset file */\r\n" -" rewind( fid_csv_filename );\r\n" -" }\r\n" -"#endif\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * reset_stack()\r\n" -" *\r\n" -" * Reset stack pointer\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void reset_stack( void )\r\n" -"{\r\n" -" int16_t something;\r\n" -"\r\n" -" /* initialize/reset stack pointers */\r\n" -" ptr_base_stack = &something;\r\n" -" ptr_max_stack = ptr_base_stack;\r\n" -" ptr_current_stack = ptr_base_stack;\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * push_stack()\r\n" -" *\r\n" -" * Check the current stack pointer and update the maximum stack pointer, if new maximum found.\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"int push_stack( const char *filename, const char *fctname )\r\n" -"{\r\n" -" int16_t something;\r\n" -" int32_t current_stack_size;\r\n" -"\r\n" -" ptr_current_stack = &something;\r\n" -"\r\n" -" (void) *filename; /* to avoid compilation warning */\r\n" -"\r\n" -" if ( current_calls >= max_num_calls )\r\n" -" {\r\n" -" /* There is no room for a new record -> reallocate the list */\r\n" -" max_num_calls += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" stack_callers[0] = realloc( stack_callers[0], max_num_calls * sizeof( caller_info ) );\r\n" -" stack_callers[1] = realloc( stack_callers[1], max_num_calls * sizeof( caller_info ) );\r\n" -" }\r\n" -"\r\n" -" /* Valid Function Name? */\r\n" -" if ( fctname[0] == 0 )\r\n" -" { /* No */\r\n" -" fprintf( stderr, \"Invalid function name for call stack info.\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* Save the Name of the Calling Function in the Table */\r\n" -" strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FUNCTION_NAME_LENGTH );\r\n" -" stack_callers[0][current_calls].function_name[MAX_FUNCTION_NAME_LENGTH] = 0; /* Nul Terminate */\r\n" -"\r\n" -" /* Save the Stack Pointer */\r\n" -" stack_callers[0][current_calls].stack_ptr = ptr_current_stack;\r\n" -"\r\n" -" /* Increase the Number of Calls in the List */\r\n" -" current_calls++;\r\n" -"\r\n" -" /* Is this the First Time or the Worst Case? */\r\n" -" if ( ptr_current_stack < ptr_max_stack || ptr_max_stack == NULL )\r\n" -" { /* Yes */\r\n" -" /* Save Info about it */\r\n" -" ptr_max_stack = ptr_current_stack;\r\n" -"\r\n" -" /* save the worst-case frame number */\r\n" -" /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */\r\n" -" wc_stack_frame = update_cnt; \r\n" -" strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 );\r\n" -" location_max_stack[sizeof( location_max_stack ) - 1] = '\\0';\r\n" -"\r\n" -" /* Save Call Tree */\r\n" -" memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls );\r\n" -"\r\n" -" /* Terminate the List with 0 (for printing purposes) */\r\n" -" if ( current_calls < max_num_calls )\r\n" -" {\r\n" -" stack_callers[1][current_calls].function_name[0] = 0;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Check, if This is the New Worst-Case RAM (stack + heap) */\r\n" -" current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) );\r\n" -"\r\n" -" if ( current_stack_size < 0 )\r\n" -" {\r\n" -" /* prevent negative stack size */\r\n" -" current_stack_size = 0;\r\n" -" }\r\n" -"\r\n" -" if ( current_stack_size + current_heap_size > wc_ram_size )\r\n" -" {\r\n" -" wc_ram_size = current_stack_size + current_heap_size;\r\n" -" wc_ram_frame = update_cnt;\r\n" -" }\r\n" -"\r\n" -" return 0 /* for Now */;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * pop_stack()\r\n" -" *\r\n" -" * Remove stack caller entry from the list\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"int pop_stack( const char *filename, const char *fctname )\r\n" -"{\r\n" -" caller_info *caller_info_ptr;\r\n" -"\r\n" -" (void) *filename; /* to avoid compilation warning */\r\n" -"\r\n" -" /* Decrease the Number of Records */\r\n" -" current_calls--;\r\n" -"\r\n" -" /* Get Pointer to Caller Information */\r\n" -" caller_info_ptr = &stack_callers[0][current_calls];\r\n" -"\r\n" -" /* Check, if the Function Names Match */\r\n" -" if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 )\r\n" -" {\r\n" -" fprintf( stderr, \"Invalid usage of pop_stack()\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* Erase Entry */\r\n" -" caller_info_ptr->function_name[0] = 0;\r\n" -"\r\n" -" /* Retrieve previous stack pointer */\r\n" -" if ( current_calls == 0 )\r\n" -" {\r\n" -" ptr_current_stack = ptr_base_stack;\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" ptr_current_stack = stack_callers[0][current_calls - 1].stack_ptr;\r\n" -" }\r\n" -"\r\n" -" return 0 /* for Now */;\r\n" -"}\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * print_stack_call_tree()\r\n" -" *\r\n" -" * Print detailed information about worst-case stack usage\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static void print_stack_call_tree( void )\r\n" -"{\r\n" -" caller_info *caller_info_ptr;\r\n" -" int call_level;\r\n" -" char fctname[MAX_FUNCTION_NAME_LENGTH + 1];\r\n" -"\r\n" -" fprintf( stdout, \"\\nList of functions when maximum stack size is reached:\\n\\n\" );\r\n" -"\r\n" -" caller_info_ptr = &stack_callers[1][0];\r\n" -" for ( call_level = 0; call_level < max_num_calls; call_level++ )\r\n" -" {\r\n" -" /* Done? */\r\n" -" if ( caller_info_ptr->function_name[0] == 0 )\r\n" -" {\r\n" -" break;\r\n" -" }\r\n" -"\r\n" -" /* Print Name */\r\n" -" strncpy( fctname, caller_info_ptr->function_name, MAX_FUNCTION_NAME_LENGTH );\r\n" -" strcat( fctname, \"()\" );\r\n" -" fprintf( stdout, \"%-42s\", fctname );\r\n" -"\r\n" -" /* Print Stack Usage (Based on Difference) */\r\n" -" if ( call_level != 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"%lu %s\\n\", ( ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" fprintf( stdout, \"%lu %s\\n\", ( ( ptr_base_stack - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -"\r\n" -" /* Advance */\r\n" -" caller_info_ptr++;\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, \"\\n\" );\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"#endif\r\n" -"\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * mem_alloc()\r\n" -" *\r\n" -" * Creates new record, stores auxiliary information about which function allocated the memory, line number, parameters, etc.\r\n" -" * Finally, it allocates physical memory using malloc()\r\n" -" * The function also updates worst-case heap size and worst-case RAM size\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void *mem_alloc(\r\n" -" const char *func_name,\r\n" -" int func_lineno,\r\n" -" size_t size,\r\n" -" char *size_str /* the first char indicates m-alloc or c-alloc */ )\r\n" -"{\r\n" -" int index_record;\r\n" -" int32_t current_stack_size;\r\n" -" unsigned long hash;\r\n" -" allocator_record *ptr_record;\r\n" -"\r\n" -" if ( size == 0 )\r\n" -" {\r\n" -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Size of Zero not Supported\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* Search for an existing record (that has been de-allocated before) */\r\n" -" index_record = 0;\r\n" -" while ( ( ptr_record = get_mem_record( &hash, func_name, func_lineno, size_str, &index_record ) ) != NULL )\r\n" -" {\r\n" -" if ( ptr_record->frame_allocated == -1 )\r\n" -" {\r\n" -" break;\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" index_record++;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Create new record */\r\n" -" if ( ptr_record == NULL )\r\n" -" {\r\n" -" if ( Num_Records >= Max_Num_Records )\r\n" -" {\r\n" -" /* There is no room for a new record -> reallocate memory */\r\n" -" Max_Num_Records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" allocation_list = realloc( allocation_list, Max_Num_Records * sizeof( allocator_record ) );\r\n" -" }\r\n" -"\r\n" -" ptr_record = &( allocation_list[Num_Records] );\r\n" -"\r\n" -" /* Initialize new record */\r\n" -" ptr_record->hash = hash;\r\n" -" ptr_record->noccurances = 0;\r\n" -" ptr_record->total_block_size = 0;\r\n" -" ptr_record->total_used_size = 0;\r\n" -" ptr_record->frame_allocated = -1;\r\n" -" ptr_record->OOB_Flag = 0;\r\n" -" ptr_record->wc_heap_size_intra_frame = -1;\r\n" -" ptr_record->wc_heap_size_inter_frame = -1;\r\n" -"\r\n" -" index_record = Num_Records;\r\n" -" Num_Records++;\r\n" -" }\r\n" -"\r\n" -" /* Allocate memory block for the new record, add signature before the beginning and after the memory block and fill it with magic value */\r\n" -" ptr_record->block_ptr = mem_alloc_block( size, size_str );\r\n" -"\r\n" -" if ( ptr_record->block_ptr == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Cannot Allocate Memory!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* Save all auxiliary information about the memory block */\r\n" -" strncpy( ptr_record->name, func_name, MAX_FUNCTION_NAME_LENGTH );\r\n" -" ptr_record->name[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n" -" strncpy( ptr_record->params, size_str, MAX_PARAMS_LENGTH ); /* Note: The size string starts with either 'm' or 'c' to indicate 'm'alloc or 'c'alloc */\r\n" -" ptr_record->params[MAX_PARAMS_LENGTH] = '\\0';\r\n" -" ptr_record->lineno = func_lineno;\r\n" -" ptr_record->block_size = size;\r\n" -" ptr_record->total_block_size += size;\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -" /* Export heap memory allocation record to the .csv file */\r\n" -" fprintf( fid_csv_filename, \"A,%d,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n" -"#endif\r\n" -"\r\n" -" if ( ptr_record->frame_allocated != -1 )\r\n" -" {\r\n" -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Attempt to Allocate the Same Memory Block with Freeing it First!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" ptr_record->frame_allocated = update_cnt; /* Store the current frame number -> later it will be used to determine the total duration */\r\n" -"\r\n" -" /* Update Heap Size in the current frame */\r\n" -" current_heap_size += ptr_record->block_size;\r\n" -"\r\n" -" /* Check, if this is the new Worst-Case RAM (stack + heap) */\r\n" -" current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) );\r\n" -" if ( current_stack_size + current_heap_size > wc_ram_size )\r\n" -" {\r\n" -" wc_ram_size = current_stack_size + current_heap_size;\r\n" -" wc_ram_frame = update_cnt;\r\n" -" }\r\n" -"\r\n" -" /* Add new entry to the heap allocation call tree */\r\n" -" if ( heap_allocation_call_tree == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Heap allocation call tree not created!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* check, if the maximum size of the call tree has been reached -> resize if so */\r\n" -" if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size )\r\n" -" {\r\n" -" heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" /* push new entry (positive number means push op, neagtive number means pop op; zero index must be converted to 0.01 :-) */\r\n" -" heap_allocation_call_tree[heap_allocation_call_tree_size++] = index_record;\r\n" -"\r\n" -" return ptr_record->block_ptr;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * mem_alloc_block()\r\n" -" *\r\n" -" * Physical allocation of memory using malloc(). Appends 'signature' before and after the block,\r\n" -" * pre-fills memory block with magic value\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static void *mem_alloc_block( size_t size, const char *size_str )\r\n" -"{\r\n" -" size_t rounded_size;\r\n" -" void *block_ptr;\r\n" -" char *tmp_ptr;\r\n" -" size_t n, f;\r\n" -" int32_t fill_value;\r\n" -" int32_t *ptr32;\r\n" -" int32_t mask, temp;\r\n" -"\r\n" -" /* Round Up Block Size */\r\n" -" rounded_size = ROUND_BLOCK_SIZE( size );\r\n" -"\r\n" -" /* Allocate memory using the standard malloc() by adding room for Signature Values */\r\n" -" block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 );\r\n" -"\r\n" -" if ( block_ptr == NULL )\r\n" -" {\r\n" -" return NULL;\r\n" -" }\r\n" -"\r\n" -" /* Add Signature Before the Start of the Block */\r\n" -" ptr32 = (int32_t *) block_ptr;\r\n" -" n = N_32BITS_BLOCKS;\r\n" -" do\r\n" -" {\r\n" -" *ptr32++ = MAGIC_VALUE_OOB;\r\n" -" } while ( --n );\r\n" -"\r\n" -" /* Fill Memory Block with Magic Value or 0 */\r\n" -" fill_value = MAGIC_VALUE_USED;\r\n" -" if ( size_str[0] == 'c' )\r\n" -" {\r\n" -" fill_value = 0x00000000;\r\n" -" }\r\n" -" n = size / sizeof( int32_t );\r\n" -" while ( n-- )\r\n" -" {\r\n" -" *ptr32++ = fill_value;\r\n" -" }\r\n" -"\r\n" -" /* Fill the Reminder of the Memory Block - After Rounding */\r\n" -" n = rounded_size - size;\r\n" -" f = n % sizeof( int32_t );\r\n" -" if ( f != 0 )\r\n" -" {\r\n" -" /* when filling with '0' need to adapt the magic value */\r\n" -" /* shift by [1->24, 2->16, 3->8] */\r\n" -" mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */\r\n" -" temp = MAGIC_VALUE_OOB & mask;\r\n" -" if ( fill_value != 0x0 )\r\n" -" { /* for malloc merge fill value */\r\n" -" temp += ( ~mask ) & MAGIC_VALUE_USED;\r\n" -" } /* for calloc the code in (1) above already introduces zeros */\r\n" -" *ptr32++ = temp;\r\n" -" }\r\n" -" n /= sizeof( int32_t );\r\n" -" n += N_32BITS_BLOCKS;\r\n" -"\r\n" -" /* Add Signature After the End of Block */\r\n" -" do\r\n" -" {\r\n" -" *ptr32++ = MAGIC_VALUE_OOB;\r\n" -" } while ( --n );\r\n" -"\r\n" -" /* Adjust the Memory Block Pointer (Magic Value Before and After the Memory Block Requested) */\r\n" -" tmp_ptr = (char *) block_ptr;\r\n" -" tmp_ptr += BLOCK_ROUNDING;\r\n" -" block_ptr = (void *) tmp_ptr;\r\n" -"\r\n" -" return block_ptr;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * mem_set_usage()\r\n" -" *\r\n" -" * Calculates actual usage of memory block by checking the magic value that was used to pre-fill\r\n" -" * each memory block during its allocation\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static int mem_set_usage( allocator_record *record_ptr )\r\n" -"{\r\n" -" int total_bytes_used;\r\n" -"\r\n" -" size_t n;\r\n" -" int32_t *ptr32;\r\n" -" char *ptr8;\r\n" -" size_t total_bytes;\r\n" -" int32_t fill_value;\r\n" -"\r\n" -" fill_value = MAGIC_VALUE_USED;\r\n" -" if ( ( record_ptr->params[0] ) == 'c' )\r\n" -" {\r\n" -" fill_value = 0x00000000;\r\n" -" }\r\n" -"\r\n" -" total_bytes = record_ptr->block_size;\r\n" -"\r\n" -" /* Check 4 bytes at a time */\r\n" -" ptr32 = (int32_t *) record_ptr->block_ptr;\r\n" -" total_bytes_used = 0;\r\n" -" for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- )\r\n" -" {\r\n" -" if ( *ptr32++ != fill_value )\r\n" -" {\r\n" -" total_bytes_used += sizeof( int32_t );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Check remaining bytes (If Applicable) 1 byte at a time */\r\n" -" ptr8 = (char *) ptr32;\r\n" -" for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- )\r\n" -" {\r\n" -" if ( *ptr8++ != (char) fill_value )\r\n" -" {\r\n" -" total_bytes_used++;\r\n" -" }\r\n" -"\r\n" -" /* Update Value */\r\n" -" fill_value >>= 8;\r\n" -" }\r\n" -"\r\n" -" return total_bytes_used;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * mem_check_OOB()\r\n" -" *\r\n" -" * Checks, if out-of-bounds access has occured. This is done by inspecting the 'signature' value\r\n" -" * taht has been added before and after the memory block during its allocation\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static unsigned int mem_check_OOB( allocator_record *record_ptr )\r\n" -"{\r\n" -" int32_t *ptr32;\r\n" -" unsigned int OOB_Flag = 0x0;\r\n" -" int32_t mask;\r\n" -" size_t i;\r\n" -" int f;\r\n" -"\r\n" -" ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS;\r\n" -"\r\n" -" /* Check the Signature at the Beginning of Memory Block */\r\n" -" i = N_32BITS_BLOCKS;\r\n" -" do\r\n" -" {\r\n" -" if ( *ptr32++ ^ MAGIC_VALUE_OOB )\r\n" -" {\r\n" -" OOB_Flag |= OOB_START;\r\n" -" }\r\n" -" } while ( --i );\r\n" -"\r\n" -" /* Advance to End (Snap to lowest 32 Bits) */\r\n" -" ptr32 += record_ptr->block_size / sizeof( int32_t );\r\n" -"\r\n" -" /* Calculate Unused Space That has been added to get to the rounded Block Size */\r\n" -" i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size;\r\n" -"\r\n" -" /* Partial Check of Signature at the End of Memory Block (for block size that has been rounded) */\r\n" -" f = i % sizeof( int32_t );\r\n" -" if ( f != 0 )\r\n" -" {\r\n" -" mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 );\r\n" -" if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask )\r\n" -" {\r\n" -" OOB_Flag |= OOB_END;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Full Check of Signature at the End of Memory Block, i.e. all 32 Bits (for the remainder after rounding) */\r\n" -" i /= sizeof( int32_t );\r\n" -" i += N_32BITS_BLOCKS;\r\n" -" do\r\n" -" {\r\n" -" if ( *ptr32++ ^ MAGIC_VALUE_OOB )\r\n" -" {\r\n" -" OOB_Flag |= OOB_END;\r\n" -" }\r\n" -" } while ( --i );\r\n" -"\r\n" -" return OOB_Flag;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * malloc_hash()\r\n" -" *\r\n" -" * Calculate hash from function name, line number and malloc size\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str )\r\n" -"{\r\n" -" unsigned long hash = 5381;\r\n" -" const char *ptr_str;\r\n" -"\r\n" -" ptr_str = func_name;\r\n" -" while ( ptr_str != NULL && *ptr_str != '\\0' )\r\n" -" {\r\n" -" hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */\r\n" -" }\r\n" -"\r\n" -" hash = ( ( hash << 5 ) + hash ) + func_lineno; /* hash * 33 + func_lineno */\r\n" -"\r\n" -" ptr_str = size_str;\r\n" -" while ( ptr_str != NULL && *ptr_str != '\\0' )\r\n" -" {\r\n" -" hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */\r\n" -" }\r\n" -"\r\n" -" return hash;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * get_mem_record()\r\n" -" *\r\n" -" * Search for memory record in the internal list, return NULL if not found\r\n" -" * Start from index_record\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record )\r\n" -"{\r\n" -" int i;\r\n" -"\r\n" -" if ( *index_record < 0 || *index_record > Num_Records )\r\n" -" {\r\n" -" return NULL;\r\n" -" }\r\n" -"\r\n" -" /* calculate hash */\r\n" -" *hash = malloc_hash( func_name, func_lineno, size_str );\r\n" -"\r\n" -" for ( i = *index_record; i < Num_Records; i++ )\r\n" -" {\r\n" -" /* check, if memory block is not allocated at the moment and the hash matches */\r\n" -" if ( allocation_list[i].block_ptr == NULL && *hash == allocation_list[i].hash )\r\n" -" {\r\n" -" *index_record = i;\r\n" -" return &( allocation_list[i] );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* not found */\r\n" -" *index_record = -1;\r\n" -" return NULL;\r\n" -"}\r\n" -"\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * mem_free()\r\n" -" *\r\n" -" * This function de-allocatesd the memory block and frees the mphysical memory with free().\r\n" -" * It also updates actual and average usage of the memory block.\r\n" -" *\r\n" -" * Note: The record is not removed from the list and may be reused later on in mem_alloc()!\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void mem_free( const char *func_name, int func_lineno, void *ptr )\r\n" -"{\r\n" -" int i, index_record;\r\n" -" char *tmp_ptr;\r\n" -" allocator_record *ptr_record;\r\n" -"\r\n" -" /* Search for the Block Pointer in the List */\r\n" -" ptr_record = NULL;\r\n" -" index_record = -1;\r\n" -" for ( i = 0; i < Num_Records; i++ )\r\n" -" {\r\n" -" if ( ptr == allocation_list[i].block_ptr )\r\n" -" { /* Yes, Found it */\r\n" -" ptr_record = &( allocation_list[i] );\r\n" -" index_record = i;\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" if ( ptr_record == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Unable to Find Record Corresponding to the Allocated Memory Block!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* Update the Heap Size */\r\n" -" current_heap_size -= ptr_record->block_size;\r\n" -"\r\n" -" /* Calculate the Actual Usage of the Memory Block (Look for Signature) */\r\n" -" ptr_record->total_used_size += mem_set_usage( ptr_record );\r\n" -"\r\n" -" /* Check, if Out-Of-Bounds Access has been Detected */\r\n" -" ptr_record->OOB_Flag = mem_check_OOB( ptr_record );\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -" /* Export heap memory de-allocation record to the .csv file */\r\n" -" fprintf( fid_csv_filename, \"D,%d,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n" -"#endif\r\n" -"\r\n" -" /* De-Allocate Memory Block */\r\n" -" tmp_ptr = (char *) ptr;\r\n" -" tmp_ptr -= BLOCK_ROUNDING;\r\n" -" ptr = (void *) tmp_ptr;\r\n" -" free( ptr );\r\n" -"\r\n" -" /* Add new entry to the heap allocation call tree */\r\n" -" if ( heap_allocation_call_tree == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Heap allocation call tree not created!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* check, if the maximum size of the call tree has been reached -> resize if so */\r\n" -" if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size )\r\n" -" {\r\n" -" heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" heap_allocation_call_tree[heap_allocation_call_tree_size++] = -index_record;\r\n" -"\r\n" -" /* Reset memory block pointer (this is checked when updating wc intra-frame and inter-frame memory) */\r\n" -" ptr_record->block_ptr = NULL;\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * update_mem()\r\n" -" *\r\n" -" * This function updates the worst-case intra-frame memory and the worst-case inter-frame memory.\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void update_mem( void )\r\n" -"{\r\n" -" int i, j, flag_alloc = -1, i_record;\r\n" -" int size_current_intra_frame_heap;\r\n" -" int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap;\r\n" -" allocator_record *ptr_record;\r\n" -"\r\n" -" /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */\r\n" -" n_items_current_intra_frame_heap = 0;\r\n" -" size_current_intra_frame_heap = 0;\r\n" -" for ( i = 0; i < heap_allocation_call_tree_size; i++ )\r\n" -" {\r\n" -" /* get the record */\r\n" -" i_record = heap_allocation_call_tree[i];\r\n" -"\r\n" -" if ( i_record > 0 )\r\n" -" {\r\n" -" flag_alloc = 1;\r\n" -" }\r\n" -" else if ( i_record < 0 )\r\n" -" {\r\n" -" flag_alloc = 0;\r\n" -" i_record = -i_record;\r\n" -" }\r\n" -" ptr_record = &( allocation_list[i_record] );\r\n" -"\r\n" -" if ( ptr_record->frame_allocated == update_cnt && ptr_record->block_ptr == NULL )\r\n" -" {\r\n" -" /* intra-frame heap memory */\r\n" -" if ( list_current_intra_frame_heap == NULL )\r\n" -" {\r\n" -" list_current_intra_frame_heap = (int *) malloc( heap_allocation_call_tree_size * sizeof( int ) );\r\n" -" memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n" -" if ( i_record == 0 )\r\n" -" {\r\n" -" flag_alloc = 1;\r\n" -" for ( j = 0; j < n_items_current_intra_frame_heap; j++ )\r\n" -" {\r\n" -" if ( list_current_intra_frame_heap[j] == i_record )\r\n" -" {\r\n" -" flag_alloc = 0;\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" if ( flag_alloc )\r\n" -" {\r\n" -" /* add to list */\r\n" -" list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record;\r\n" -" size_current_intra_frame_heap += ptr_record->block_size;\r\n" -"\r\n" -" /* no need to re-size the list -> the initially allocated size should be large enough */\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" /* remove from list */\r\n" -" for ( j = 0; j < n_items_current_intra_frame_heap; j++ )\r\n" -" {\r\n" -" if ( list_current_intra_frame_heap[j] == i_record )\r\n" -" {\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -" memmove( &list_current_intra_frame_heap[j], &list_current_intra_frame_heap[j + 1], ( n_items_current_intra_frame_heap - j ) * sizeof( int ) );\r\n" -" n_items_current_intra_frame_heap--;\r\n" -" size_current_intra_frame_heap -= ptr_record->block_size;\r\n" -"\r\n" -" /* reset block size */\r\n" -" ptr_record->frame_allocated = -1;\r\n" -" ptr_record->block_size = 0;\r\n" -" }\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" /* inter-frame heap memory */\r\n" -"\r\n" -" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n" -" if ( i_record == 0 )\r\n" -" {\r\n" -" flag_alloc = 1;\r\n" -" for ( j = 0; j < n_items_current_inter_frame_heap; j++ )\r\n" -" {\r\n" -" if ( list_current_inter_frame_heap[j] == i_record )\r\n" -" {\r\n" -" flag_alloc = 0;\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" if ( flag_alloc )\r\n" -" {\r\n" -" /* add to list */\r\n" -" if ( n_items_current_inter_frame_heap >= max_items_current_inter_frame_heap )\r\n" -" {\r\n" -" /* resize list, if needed */\r\n" -" max_items_current_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" list_current_inter_frame_heap = realloc( list_current_inter_frame_heap, max_items_current_inter_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record;\r\n" -" size_current_inter_frame_heap += ptr_record->block_size;\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" /* remove from list */\r\n" -" for ( j = 0; j < n_items_current_inter_frame_heap; j++ )\r\n" -" {\r\n" -" if ( list_current_inter_frame_heap[j] == i_record )\r\n" -" {\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -" memmove( &list_current_inter_frame_heap[j], &list_current_inter_frame_heap[j + 1], ( n_items_current_inter_frame_heap - j ) * sizeof( int ) );\r\n" -" n_items_current_inter_frame_heap--;\r\n" -" size_current_inter_frame_heap -= ptr_record->block_size;\r\n" -"\r\n" -" /* reset block size */\r\n" -" ptr_record->frame_allocated = -1;\r\n" -" ptr_record->block_size = 0;\r\n" -" }\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* check, if this is the new worst-case for intra-frame heap memory */\r\n" -" if ( size_current_intra_frame_heap > size_wc_intra_frame_heap )\r\n" -" {\r\n" -" if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap )\r\n" -" {\r\n" -" /* resize the list, if needed */\r\n" -" max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" /* copy current-frame list to worst-case list */\r\n" -" memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) );\r\n" -" n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap;\r\n" -" size_wc_intra_frame_heap = size_current_intra_frame_heap;\r\n" -" location_wc_intra_frame_heap = update_cnt;\r\n" -"\r\n" -" /* update the wc numbers in all individual records */\r\n" -" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n" -" {\r\n" -" i_record = list_wc_intra_frame_heap[i];\r\n" -" ptr_record = &( allocation_list[i_record] );\r\n" -" ptr_record->wc_heap_size_intra_frame = ptr_record->block_size;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* check, if this is the new worst-case for inter-frame heap memory */\r\n" -" if ( size_current_inter_frame_heap > size_wc_inter_frame_heap )\r\n" -" {\r\n" -" if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap )\r\n" -" {\r\n" -" /* resize list, if needed */\r\n" -" max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" /* copy current-frame list to worst-case list */\r\n" -" memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) );\r\n" -" n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap;\r\n" -" size_wc_inter_frame_heap = size_current_inter_frame_heap;\r\n" -" location_wc_inter_frame_heap = update_cnt;\r\n" -"\r\n" -" /* update the wc numbers in all individual records */\r\n" -" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n" -" {\r\n" -" i_record = list_wc_inter_frame_heap[i];\r\n" -" ptr_record = &( allocation_list[i_record] );\r\n" -" ptr_record->wc_heap_size_inter_frame = ptr_record->block_size;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* reset heap allocation call tree */\r\n" -" heap_allocation_call_tree_size = 0;\r\n" -"\r\n" -" /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */\r\n" -" if ( list_current_intra_frame_heap )\r\n" -" {\r\n" -" free( list_current_intra_frame_heap );\r\n" -" }\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * subst()\r\n" -" *\r\n" -" * Substitute character in string\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static void subst( char *s, char from, char to )\r\n" -"{\r\n" -" while ( *s == from )\r\n" -" {\r\n" -" *s++ = to;\r\n" -" }\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * mem_count_summary()\r\n" -" *\r\n" -" * Print detailed (per-item) information about heap memory usage\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static void mem_count_summary( void )\r\n" -"{\r\n" -" int i, j, index, index_record;\r\n" -" size_t length;\r\n" -" char buf[300], format_str[50], name_str[MAX_FUNCTION_NAME_LENGTH + 3], parms_str[MAX_PARAMS_LENGTH + 1], type_str[10], usage_str[20], size_str[20], line_str[10];\r\n" -" allocator_record *ptr_record, *ptr;\r\n" -"\r\n" -" /* Prepare format string */\r\n" -" sprintf( format_str, \"%%-%ds %%5s %%6s %%-%ds %%20s %%6s \", MAX_FUNCTION_NAME_LENGTH, MAX_PARAMS_LENGTH );\r\n" -"\r\n" -" if ( n_items_wc_intra_frame_heap > 0 )\r\n" -" {\r\n" -" /* Intra-Frame Heap Size */\r\n" -" fprintf( stdout, \"\\nList of memory blocks when maximum intra-frame heap size is reached:\\n\\n\" );\r\n" -"\r\n" -" /* Find duplicate records (same hash and worst-case heap size) */\r\n" -" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n" -" {\r\n" -" index_record = list_wc_intra_frame_heap[i];\r\n" -" if ( index_record == -1 )\r\n" -" {\r\n" -" continue;\r\n" -" }\r\n" -"\r\n" -" ptr_record = &( allocation_list[index_record] );\r\n" -" for ( j = i + 1; j < n_items_wc_intra_frame_heap; j++ )\r\n" -" {\r\n" -" index = list_wc_intra_frame_heap[j];\r\n" -" if ( index == -1 )\r\n" -" {\r\n" -" continue;\r\n" -" }\r\n" -" ptr = &( allocation_list[index] );\r\n" -"\r\n" -" if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_intra_frame == ptr_record->wc_heap_size_intra_frame )\r\n" -" {\r\n" -" ptr_record->noccurances++;\r\n" -" list_wc_intra_frame_heap[j] = -1;\r\n" -" }\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Print Header */\r\n" -" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Maximum Size\", \"Usage\" );\r\n" -" puts( buf );\r\n" -" length = strlen( buf );\r\n" -" sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n" -" subst( buf, '0', '-' );\r\n" -" puts( buf );\r\n" -"\r\n" -" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n" -" {\r\n" -" index_record = list_wc_intra_frame_heap[i];\r\n" -"\r\n" -" if ( index_record != -1 )\r\n" -" {\r\n" -" /* get the record */\r\n" -" ptr_record = &( allocation_list[index_record] );\r\n" -"\r\n" -" /* prepare information strings */\r\n" -" strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH );\r\n" -" strcat( name_str, \"()\" );\r\n" -" name_str[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n" -" strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH );\r\n" -" parms_str[MAX_PARAMS_LENGTH] = '\\0';\r\n" -"\r\n" -" if ( ptr_record->params[0] == 'm' )\r\n" -" {\r\n" -" strcpy( type_str, \"malloc\" );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" strcpy( type_str, \"calloc\" );\r\n" -" }\r\n" -"\r\n" -" sprintf( line_str, \"%d\", ptr_record->lineno );\r\n" -"\r\n" -" /* prepare average usage & memory size strings */\r\n" -" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) );\r\n" -"\r\n" -" if ( ptr_record->noccurances > 1 )\r\n" -" {\r\n" -" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" sprintf( size_str, \"%d %s\", (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -"\r\n" -" sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str );\r\n" -" puts( buf );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, \"\\n\" );\r\n" -" }\r\n" -"\r\n" -" if ( n_items_wc_inter_frame_heap > 0 )\r\n" -" {\r\n" -" /* Inter-Frame Heap Size */\r\n" -" fprintf( stdout, \"\\nList of memory blocks when maximum inter-frame heap size is reached:\\n\\n\" );\r\n" -"\r\n" -" /* Find duplicate records (same hash and worst-case heap size) */\r\n" -" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n" -" {\r\n" -" index_record = list_wc_inter_frame_heap[i];\r\n" -" if ( index_record == -1 )\r\n" -" {\r\n" -" continue;\r\n" -" }\r\n" -" ptr_record = &( allocation_list[index_record] );\r\n" -" ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */\r\n" -" for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ )\r\n" -" {\r\n" -" index = list_wc_inter_frame_heap[j];\r\n" -" if ( index == -1 )\r\n" -" {\r\n" -" continue;\r\n" -" }\r\n" -" ptr = &( allocation_list[index] );\r\n" -"\r\n" -" if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_inter_frame == ptr_record->wc_heap_size_inter_frame )\r\n" -" {\r\n" -" ptr_record->noccurances++;\r\n" -" list_wc_inter_frame_heap[j] = -1;\r\n" -" }\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Print Header */\r\n" -" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Memory Size\", \"Usage\" );\r\n" -" puts( buf );\r\n" -" length = strlen( buf );\r\n" -" sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n" -" subst( buf, '0', '-' );\r\n" -" puts( buf );\r\n" -"\r\n" -" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n" -" {\r\n" -" index_record = list_wc_inter_frame_heap[i];\r\n" -"\r\n" -" if ( index_record != -1 )\r\n" -" {\r\n" -" /* get the record */\r\n" -" ptr_record = &( allocation_list[index_record] );\r\n" -"\r\n" -" /* prepare information strings */\r\n" -" strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH );\r\n" -" strcat( name_str, \"()\" );\r\n" -" name_str[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n" -" strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH );\r\n" -" parms_str[MAX_PARAMS_LENGTH] = '\\0';\r\n" -"\r\n" -" if ( ptr_record->params[0] == 'm' )\r\n" -" {\r\n" -" strcpy( type_str, \"malloc\" );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" strcpy( type_str, \"calloc\" );\r\n" -" }\r\n" -"\r\n" -" sprintf( line_str, \"%d\", ptr_record->lineno );\r\n" -"\r\n" -" /* prepare average usage & memory size strings */\r\n" -" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) );\r\n" -"\r\n" -" if ( ptr_record->noccurances > 1 )\r\n" -" {\r\n" -" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" sprintf( size_str, \"%d %s\", (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -"\r\n" -" sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str );\r\n" -" puts( buf );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, \"\\n\" );\r\n" -" }\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * print_mem()\r\n" -" *\r\n" -" * Print information about ROM and RAM memory usage\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] )\r\n" -"{\r\n" -" int i, nElem;\r\n" -"\r\n" -" fprintf( stdout, \"\\n\\n --- Memory usage --- \\n\\n\" );\r\n" -"\r\n" -" if ( Const_Data_PROM_Table != NULL )\r\n" -" {\r\n" -" nElem = 0;\r\n" -" while ( strcmp( Const_Data_PROM_Table[nElem].file_spec, \"\" ) != 0 )\r\n" -" nElem++;\r\n" -"\r\n" -" for ( i = 0; i < nElem; i++ )\r\n" -" {\r\n" -" if ( Stat_Cnt_Size > 0 )\r\n" -" {\r\n" -" /* words */\r\n" -" fprintf( stdout, \"Program ROM size (%s): %d words\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" /* bytes (here, we assume that each instruction takes PROM_INST_SIZE bits of the PROM memory) */\r\n" -" fprintf( stdout, \"Program ROM size (%s): %d bytes\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size * ( PROM_INST_SIZE / 8 ) );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" for ( i = 0; i < nElem; i++ )\r\n" -" {\r\n" -" if ( Const_Data_PROM_Table[i].Get_Const_Data_Size_Func == NULL )\r\n" -" {\r\n" -" fprintf( stdout, \"Error: Cannot retrieve or calculate Table ROM size of (%s)!\\n\", Const_Data_PROM_Table[i].file_spec );\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, \"Table ROM (const data) size (%s): %d %s\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].Get_Const_Data_Size_Func() >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" fprintf( stdout, \"Program ROM size: not available\\n\" );\r\n" -" fprintf( stdout, \"Table ROM (const data) size: not available\\n\" );\r\n" -" }\r\n" -"\r\n" -" if ( wc_ram_size > 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum RAM (stack + heap) size: %d %s in frame %d\\n\", wc_ram_size >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], wc_ram_frame );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum RAM (stack + heap) size: not available\\n\" );\r\n" -" }\r\n" -"\r\n" -" /* check, if the stack is empty */\r\n" -" if ( ptr_current_stack != ptr_base_stack )\r\n" -" {\r\n" -" fprintf( stderr, \"Warning: Stack is not empty.\\n\" );\r\n" -" }\r\n" -"\r\n" -" if ( ptr_base_stack - ptr_max_stack > 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum stack size: %lu %s in frame %d\\n\", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size],\r\n" -" wc_stack_frame );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum stack size: not available\\n\" );\r\n" -" }\r\n" -"\r\n" -" /* last update of intra-frame memory and inter-frame memory, if needed */\r\n" -" if ( heap_allocation_call_tree_size > 0 )\r\n" -" {\r\n" -" update_mem();\r\n" -" }\r\n" -"\r\n" -" /* check, if all memory blocks have been deallocated (freed) */\r\n" -" for ( i = 0; i < Num_Records; i++ )\r\n" -" {\r\n" -" if ( allocation_list[i].block_ptr != NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", allocation_list[i].name, allocation_list[i].lineno, \"Error: Memory Block has not been De-Allocated with free()!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" if ( n_items_wc_intra_frame_heap > 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum intra-frame heap size: %d %s in frame %d\\n\", size_wc_intra_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_intra_frame_heap );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum intra-frame heap size: 0\\n\" );\r\n" -" }\r\n" -"\r\n" -" if ( n_items_wc_inter_frame_heap > 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum inter-frame heap size: %d %s in frame %d\\n\", size_wc_inter_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_inter_frame_heap );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum inter-frame heap size: 0\\n\" );\r\n" -" }\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -" /* Print detailed information about worst-case stack usage */\r\n" -" if ( ptr_base_stack - ptr_max_stack > 0 )\r\n" -" {\r\n" -" print_stack_call_tree();\r\n" -" }\r\n" -"\r\n" -" /* Print detailed information about worst-case heap usage */\r\n" -" mem_count_summary();\r\n" -"#endif\r\n" -"\r\n" -" if ( Stat_Cnt_Size > 0 )\r\n" -" {\r\n" -" /* words */\r\n" -" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", 8 << Stat_Cnt_Size );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" /* bytes */\r\n" -" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", PROM_INST_SIZE );\r\n" -" }\r\n" -" fprintf( stdout, \"Note: The Data ROM size is calculated using the sizeof(type) built-in function\\n\" );\r\n" -"\r\n" -" if ( n_items_wc_intra_frame_heap > 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"Intra-frame heap memory is allocated and de-allocated in the same frame\\n\" );\r\n" -" }\r\n" -"\r\n" -" /* De-allocate list of heap memory blocks */\r\n" -" if ( allocation_list != NULL )\r\n" -" {\r\n" -" free( allocation_list );\r\n" -" }\r\n" -"\r\n" -" /* De-allocate list of stack records */\r\n" -" if ( stack_callers[0] != NULL )\r\n" -" {\r\n" -" free( stack_callers[0] );\r\n" -" }\r\n" -"\r\n" -" if ( stack_callers[1] != NULL )\r\n" -" {\r\n" -" free( stack_callers[1] );\r\n" -" }\r\n" -"\r\n" -" /* De-allocate heap allocation call tree */\r\n" -" if ( heap_allocation_call_tree != NULL )\r\n" -" {\r\n" -" free( heap_allocation_call_tree );\r\n" -" }\r\n" -"\r\n" -" /* De-allocate intra-frame and inter-frame heap lists */\r\n" -" if ( list_wc_intra_frame_heap != NULL )\r\n" -" {\r\n" -" free( list_wc_intra_frame_heap );\r\n" -" }\r\n" -"\r\n" -" if ( list_current_inter_frame_heap != NULL )\r\n" -" {\r\n" -" free( list_current_inter_frame_heap );\r\n" -" }\r\n" -"\r\n" -" if ( list_wc_inter_frame_heap != NULL )\r\n" -" {\r\n" -" free( list_wc_inter_frame_heap );\r\n" -" }\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -" if ( fid_csv_filename != NULL )\r\n" -" {\r\n" -" fclose( fid_csv_filename );\r\n" -" }\r\n" -"#endif\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"#endif /* WMOPS */\r\n" -"\r\n" -"#ifndef WMOPS\r\n" -"int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */\r\n" -"#endif\r\n" -"\r\n" -"#ifdef WMOPS\r\n" -"/* Global counter for the calculation of BASOP complexity */\r\n" -"BASIC_OP *multiCounter = NULL;\r\n" -"int currCounter = 0;\r\n" -"int funcId_where_last_call_to_else_occurred;\r\n" -"long funcid_total_wmops_at_last_call_to_else;\r\n" -"int call_occurred = 1;\r\n" -"\r\n" -"BASIC_OP op_weight = {\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 2, 2, 1,\r\n" -" 1, 1, 1, 3, 1,\r\n" -"\r\n" -" 1, 1, 1, 3, 1,\r\n" -" 4, 1, 18, 1, 1,\r\n" -" 2, 1, 2, 2, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 3, 3, 3, 3, 1,\r\n" -"\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 1, 2,\r\n" -" 1, 2, 2, 4, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -"\r\n" -" 1, 1, 1, 1, 3,\r\n" -" 3, 3, 3, 3, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 1, 4, 4,\r\n" -" 4, 8, 3, 4, 4,\r\n" -"\r\n" -" 5, 32, 3\r\n" -"};\r\n" -"\r\n" -"/* Set the counter group to use, default is zero */\r\n" -"void Set_BASOP_WMOPS_counter( int counterId )\r\n" -"{\r\n" -" if ( ( counterId > num_wmops_records ) || ( counterId < 0 ) )\r\n" -" {\r\n" -" currCounter = 0;\r\n" -" return;\r\n" -" }\r\n" -" currCounter = counterId;\r\n" -" call_occurred = 1;\r\n" -"}\r\n" -"\r\n" -"extern int32_t frame;\r\n" -"\r\n" -"long TotalWeightedOperation()\r\n" -"{\r\n" -" int i;\r\n" -" unsigned int *ptr, *ptr2;\r\n" -" long tot; \r\n" -"\r\n" -" tot = 0;\r\n" -" ptr = (unsigned int *) &multiCounter[currCounter];\r\n" -" ptr2 = (unsigned int *) &op_weight;\r\n" -"\r\n" -" for ( i = 0; i < ( int )( sizeof( multiCounter[currCounter] ) / sizeof( unsigned int ) ); i++ )\r\n" -" {\r\n" -" tot += ( ( *ptr++ ) * ( *ptr2++ ) );\r\n" -" }\r\n" -"\r\n" -" return ( tot );\r\n" -"}\r\n" -"\r\n" -"long DeltaWeightedOperation( void )\r\n" -"{\r\n" -" long NewWOper, delta;\r\n" -"\r\n" -" NewWOper = TotalWeightedOperation();\r\n" -"\r\n" -" delta = NewWOper - wmops[currCounter].LastWOper;\r\n" -" wmops[currCounter].LastWOper = NewWOper;\r\n" -"\r\n" -" return ( delta );\r\n" -"}\r\n" -"\r\n" -"/* Resets the current BASOP WMOPS counter */\r\n" -"void Reset_BASOP_WMOPS_counter( void )\r\n" -"{\r\n" -" int i;\r\n" -" long *ptr;\r\n" -"\r\n" -" /* clear the current BASOP operation counter before new frame begins */\r\n" -" ptr = (long *) &multiCounter[currCounter];\r\n" -" for ( i = 0; i < (int) ( sizeof( multiCounter[currCounter] ) / sizeof( long ) ); i++ )\r\n" -" {\r\n" -" *ptr++ = 0;\r\n" -" }\r\n" -"\r\n" -" wmops[currCounter].LastWOper = 0;\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"\r\n" -"\r\n" \ No newline at end of file +"/*\r\n", +" * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved.\r\n", +" *\r\n", +" * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n", +" * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n", +" * or refer to ITU-T Recommendation G.191 on \"SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS\".\r\n", +" *\r\n", +" * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor\r\n", +" * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software\r\n", +" * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE.\r\n", +" *\r\n", +" * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca)\r\n", +" */\r\n", +"\r\n", +"#include \r\n", +"#include \r\n", +"#include \r\n", +"#include \r\n", +"#include \r\n", +"\r\n", +"#ifndef _MSC_VER\r\n", +"#include \r\n", +"#include \r\n", +"#else\r\n", +"#include \r\n", +"#endif\r\n", +"\r\n", +"#include \"options.h\"\r\n", +"#include \"wmc_auto.h\"\r\n", +"\r\n", +"#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */\r\n", +"\r\n", +"#ifdef WMOPS\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * Complexity counting tool\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"#define MAX_FUNCTION_NAME_LENGTH 50 /* Maximum length of the function name */\r\n", +"#define MAX_PARAMS_LENGTH 50 /* Maximum length of the function parameter string */\r\n", +"#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> mightb be increased during runtime, if needed */\r\n", +"#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */\r\n", +"#define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */\r\n", +"#define DOUBLE_MAX 0x80000000\r\n", +"#define FAC ( FRAMES_PER_SECOND / 1e6 )\r\n", +"\r\n", +"\r\n", +"typedef struct \r\n", +"{\r\n", +" char label[MAX_FUNCTION_NAME_LENGTH];\r\n", +" long call_number;\r\n", +" long update_cnt;\r\n", +" int call_tree[MAX_CALL_TREE_DEPTH];\r\n", +" long LastWOper;\r\n", +" double start_selfcnt;\r\n", +" double current_selfcnt;\r\n", +" double max_selfcnt;\r\n", +" double min_selfcnt;\r\n", +" double tot_selfcnt;\r\n", +" double start_cnt; \r\n", +" double current_cnt;\r\n", +" double max_cnt;\r\n", +" double min_cnt;\r\n", +" double tot_cnt;\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" int32_t current_call_number;\r\n", +" double wc_cnt;\r\n", +" double wc_selfcnt;\r\n", +" int32_t wc_call_number;\r\n", +"#endif\r\n", +"} wmops_record;\r\n", +"\r\n", +"double ops_cnt;\r\n", +"double prom_cnt;\r\n", +"double inst_cnt[NUM_INST];\r\n", +"\r\n", +"static wmops_record *wmops = NULL;\r\n", +"static int num_wmops_records, max_num_wmops_records;\r\n", +"static int current_record;\r\n", +"static long update_cnt;\r\n", +"static double start_cnt;\r\n", +"static double max_cnt;\r\n", +"static double min_cnt;\r\n", +"static double inst_cnt_wc[NUM_INST];\r\n", +"static long fnum_cnt_wc;\r\n", +"static int *wmops_caller_stack = NULL, wmops_caller_stack_index, max_wmops_caller_stack_index = 0;\r\n", +"static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0;\r\n", +"\r\n", +"void reset_wmops( void )\r\n", +"{\r\n", +" int i, j;\r\n", +" unsigned int *ptr;\r\n", +"\r\n", +" num_wmops_records = 0;\r\n", +" max_num_wmops_records = MAX_NUM_RECORDS;\r\n", +" current_record = -1;\r\n", +" update_cnt = 0;\r\n", +"\r\n", +" max_cnt = 0.0;\r\n", +" min_cnt = DOUBLE_MAX;\r\n", +" start_cnt = 0.0;\r\n", +" ops_cnt = 0.0;\r\n", +"\r\n", +" /* allocate the list of wmops records */\r\n", +" if ( wmops == NULL )\r\n", +" {\r\n", +" wmops = (wmops_record *)malloc( max_num_wmops_records * sizeof( wmops_record ) );\r\n", +" }\r\n", +"\r\n", +" if ( wmops == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Records!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* allocate the BASOP WMOPS counter */\r\n", +" if ( multiCounter == NULL )\r\n", +" {\r\n", +" multiCounter = (BASIC_OP *) malloc( max_num_wmops_records * sizeof( BASIC_OP ) );\r\n", +" }\r\n", +"\r\n", +" if ( multiCounter == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Unable to Allocate the BASOP WMOPS counter!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* initilize the list of wmops records */\r\n", +" /* initilize the BASOP WMOPS counters */\r\n", +" for ( i = 0; i < max_num_wmops_records; i++ )\r\n", +" {\r\n", +" strcpy( &wmops[i].label[0], \"\\0\" );\r\n", +" wmops[i].call_number = 0;\r\n", +" wmops[i].update_cnt = 0;\r\n", +" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n", +" {\r\n", +" wmops[i].call_tree[j] = -1;\r\n", +" }\r\n", +" wmops[i].start_selfcnt = 0.0;\r\n", +" wmops[i].current_selfcnt = 0.0;\r\n", +" wmops[i].max_selfcnt = 0.0;\r\n", +" wmops[i].min_selfcnt = DOUBLE_MAX;\r\n", +" wmops[i].tot_selfcnt = 0.0;\r\n", +" wmops[i].start_cnt = 0.0;\r\n", +" wmops[i].current_cnt = 0.0;\r\n", +" wmops[i].max_cnt = 0.0;\r\n", +" wmops[i].min_cnt = DOUBLE_MAX;\r\n", +" wmops[i].tot_cnt = 0.0;\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" wmops[i].wc_cnt = 0.0;\r\n", +" wmops[i].wc_selfcnt = 0.0;\r\n", +" wmops[i].current_call_number = 0;\r\n", +" wmops[i].wc_call_number = -1;\r\n", +"#endif\r\n", +"\r\n", +" /* clear all BASOP operation counters */\r\n", +" ptr = (unsigned int*) &multiCounter[i];\r\n", +" for ( j = 0; j < (int) ( sizeof(BASIC_OP ) / sizeof( unsigned int ) ); j++ )\r\n", +" {\r\n", +" *ptr++ = 0;\r\n", +" }\r\n", +" wmops[i].LastWOper = 0;\r\n", +" }\r\n", +"\r\n", +" /* allocate the list of wmops callers to track the sequence of function calls */\r\n", +" wmops_caller_stack_index = 0;\r\n", +" max_wmops_caller_stack_index = MAX_NUM_RECORDS;\r\n", +" if ( wmops_caller_stack == NULL )\r\n", +" {\r\n", +" wmops_caller_stack = malloc( max_wmops_caller_stack_index * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" if ( wmops_caller_stack == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Callers!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" for ( i = 0; i < max_wmops_caller_stack_index; i++ )\r\n", +" {\r\n", +" wmops_caller_stack[i] = -1;\r\n", +" }\r\n", +"\r\n", +" /* initialize auxiliary BASOP WMOPS variables */\r\n", +" call_occurred = 1;\r\n", +" funcId_where_last_call_to_else_occurred = INT_MAX;\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"\r\n", +"void push_wmops( const char *label )\r\n", +"{\r\n", +" int new_flag;\r\n", +" int i, j;\r\n", +"\r\n", +" /* Check, if this is a new function label */\r\n", +" new_flag = 1;\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" if ( strcmp( wmops[i].label, label ) == 0 )\r\n", +" {\r\n", +" new_flag = 0;\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Create a new record in the list */\r\n", +" if ( new_flag )\r\n", +" {\r\n", +" if ( num_wmops_records >= max_num_wmops_records )\r\n", +" {\r\n", +" /* There is no room for a new wmops record -> reallocate the list */\r\n", +" max_num_wmops_records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" wmops = realloc( wmops, max_num_wmops_records * sizeof( wmops_record ) );\r\n", +" multiCounter = realloc( multiCounter, max_num_wmops_records * sizeof( BASIC_OP ) );\r\n", +" }\r\n", +"\r\n", +" strcpy( wmops[i].label, label );\r\n", +"\r\n", +" num_wmops_records++;\r\n", +" }\r\n", +"\r\n", +" /* Push the current context info to the new record */\r\n", +" if ( current_record >= 0 )\r\n", +" {\r\n", +" if ( wmops_caller_stack_index >= max_wmops_caller_stack_index )\r\n", +" {\r\n", +" /* There is no room for a new record -> reallocate the list */\r\n", +" max_wmops_caller_stack_index += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" wmops_caller_stack = realloc( wmops_caller_stack, max_wmops_caller_stack_index * sizeof( int ) );\r\n", +" }\r\n", +" wmops_caller_stack[wmops_caller_stack_index++] = current_record;\r\n", +"\r\n", +" /* accumulate op counts */\r\n", +" wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n", +"\r\n", +" /* update call tree */\r\n", +" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n", +" {\r\n", +" if ( wmops[i].call_tree[j] == current_record )\r\n", +" {\r\n", +" break;\r\n", +" }\r\n", +" else if ( wmops[i].call_tree[j] == -1 )\r\n", +" {\r\n", +" wmops[i].call_tree[j] = current_record;\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* update the current context info */\r\n", +" current_record = i;\r\n", +" wmops[current_record].start_selfcnt = ops_cnt;\r\n", +" wmops[current_record].start_cnt = ops_cnt;\r\n", +" wmops[current_record].call_number++;\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" wmops[current_record].current_call_number++;\r\n", +"#endif\r\n", +"\r\n", +" /* set the ID of BASOP functions counters */\r\n", +" Set_BASOP_WMOPS_counter( current_record );\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"\r\n", +"void pop_wmops( void )\r\n", +"{\r\n", +" long tot;\r\n", +"\r\n", +" /* Check for underflow */\r\n", +" if ( current_record < 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"\\r pop_wmops(): stack underflow, too many calls to pop_wmops()\\n\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* add the BASOP complexity to the counter */\r\n", +" tot = DeltaWeightedOperation();\r\n", +" ops_cnt += tot;\r\n", +"\r\n", +" /* update count of current record */\r\n", +" wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n", +" wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt;\r\n", +"\r\n", +" /* Get back previous context from stack */\r\n", +" if ( wmops_caller_stack_index > 0 )\r\n", +" {\r\n", +" current_record = wmops_caller_stack[--wmops_caller_stack_index];\r\n", +" wmops[current_record].start_selfcnt = ops_cnt;\r\n", +"\r\n", +" /* set the ID of the previous BASOP counter */\r\n", +" Set_BASOP_WMOPS_counter( current_record );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" current_record = -1;\r\n", +" }\r\n", +"\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"\r\n", +"void update_wmops( void )\r\n", +"{\r\n", +" int i;\r\n", +" double current_cnt;\r\n", +"#ifdef WMOPS_PER_FRAME\r\n", +" static FILE *fid = NULL;\r\n", +" const char filename[] = \"wmops_analysis\";\r\n", +" float tmpF;\r\n", +"#endif\r\n", +"\r\n", +" if ( wmops_caller_stack_index != 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"update_wmops(): WMOPS caller stack corrupted - check that all push_wmops() are matched with pop_wmops()!\\n\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +"#ifdef WMOPS_PER_FRAME\r\n", +" /* Check, if the output file has already been opened */\r\n", +" if ( fid == NULL )\r\n", +" {\r\n", +" fid = fopen( filename, \"wb\" );\r\n", +"\r\n", +" if ( fid == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", filename );\r\n", +" exit( -1 );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Write current complexity to the external file */\r\n", +" tmpF = (float) ( FAC * wmops[0].current_cnt );\r\n", +" fwrite( &tmpF, sizeof( float ), 1, fid );\r\n", +"#endif\r\n", +"\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" if ( ops_cnt - start_cnt > max_cnt )\r\n", +" {\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" wmops[i].wc_cnt = wmops[i].current_cnt;\r\n", +" wmops[i].wc_selfcnt = wmops[i].current_selfcnt;\r\n", +" wmops[i].wc_call_number = wmops[i].current_call_number;\r\n", +" }\r\n", +" }\r\n", +"#endif\r\n", +"\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" wmops[i].tot_selfcnt += wmops[i].current_selfcnt;\r\n", +" wmops[i].tot_cnt += wmops[i].current_cnt;\r\n", +"\r\n", +" if ( wmops[i].current_selfcnt > 0 )\r\n", +" {\r\n", +" if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt )\r\n", +" {\r\n", +" wmops[i].max_selfcnt = wmops[i].current_selfcnt;\r\n", +" }\r\n", +"\r\n", +" if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt )\r\n", +" {\r\n", +" wmops[i].min_selfcnt = wmops[i].current_selfcnt;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" wmops[i].current_selfcnt = 0;\r\n", +"\r\n", +" if ( wmops[i].current_cnt > 0 )\r\n", +" {\r\n", +" if ( wmops[i].current_cnt > wmops[i].max_cnt )\r\n", +" {\r\n", +" wmops[i].max_cnt = wmops[i].current_cnt;\r\n", +" }\r\n", +"\r\n", +"\r\n", +" if ( wmops[i].current_cnt < wmops[i].min_cnt )\r\n", +" {\r\n", +" wmops[i].min_cnt = wmops[i].current_cnt;\r\n", +" }\r\n", +"\r\n", +" wmops[i].update_cnt++;\r\n", +" }\r\n", +"\r\n", +" wmops[i].current_cnt = 0;\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" wmops[i].current_call_number = 0;\r\n", +"#endif\r\n", +"\r\n", +" /* update the WC of all BASOP counters */\r\n", +" Set_BASOP_WMOPS_counter( i );\r\n", +" Reset_BASOP_WMOPS_counter();\r\n", +" }\r\n", +"\r\n", +" current_cnt = ops_cnt - start_cnt;\r\n", +" if ( current_cnt > max_cnt )\r\n", +" {\r\n", +" max_cnt = current_cnt;\r\n", +"\r\n", +" for ( i = 0; i < NUM_INST; i++ )\r\n", +" {\r\n", +" inst_cnt_wc[i] = inst_cnt[i];\r\n", +" }\r\n", +"\r\n", +" fnum_cnt_wc = update_cnt + 1;\r\n", +" }\r\n", +"\r\n", +" if ( current_cnt < min_cnt )\r\n", +" {\r\n", +" min_cnt = current_cnt;\r\n", +" }\r\n", +"\r\n", +" for ( i = 0; i < NUM_INST; i++ )\r\n", +" {\r\n", +" inst_cnt[i] = 0.0;\r\n", +" }\r\n", +"\r\n", +" start_cnt = ops_cnt;\r\n", +"\r\n", +" /* increment frame counter */\r\n", +" update_cnt++;\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"\r\n", +"void print_wmops( void )\r\n", +"{\r\n", +" int i, label_len, max_label_len;\r\n", +"\r\n", +" char *sfmts = \"%*s %8s %8s %7s %7s\\n\";\r\n", +" char *dfmts = \"%*s %8.2f %8.3f %7.3f %7.3f\\n\";\r\n", +" char *sfmt = \"%*s %8s %8s %7s %7s %7s %7s %7s\\n\";\r\n", +" char *dfmt = \"%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\\n\";\r\n", +"\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" int j;\r\n", +" char *sfmtt = \"%20s %4s %15s\\n\";\r\n", +" char *dfmtt = \"%20s %4d \";\r\n", +"#endif\r\n", +"\r\n", +" /* calculate maximum label length for compact prinout */\r\n", +" max_label_len = 0;\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" label_len = strlen( wmops[i].label );\r\n", +" if ( label_len > max_label_len )\r\n", +" {\r\n", +" max_label_len = label_len;\r\n", +" }\r\n", +" }\r\n", +" max_label_len += 4;\r\n", +"\r\n", +" fprintf( stdout, \"\\n\\n --- Complexity analysis [WMOPS] --- \\n\\n\" );\r\n", +" \r\n", +" fprintf( stdout, \"%*s %33s %23s\\n\", max_label_len, \"\", \"|------ SELF ------|\", \"|--- CUMULATIVE ---|\" );\r\n", +" fprintf( stdout, sfmt, max_label_len, \" routine\", \" calls\", \" min \", \" max \", \" avg \", \" min \", \" max \", \" avg \" );\r\n", +" fprintf( stdout, sfmt, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\" );\r\n", +"\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" fprintf( stdout, dfmt, max_label_len, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt,\r\n", +" wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt,\r\n", +" FAC * wmops[i].max_selfcnt,\r\n", +" wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt,\r\n", +" wmops[i].min_cnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_cnt,\r\n", +" FAC * wmops[i].max_cnt,\r\n", +" wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt );\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, sfmts, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\" );\r\n", +" fprintf( stdout, dfmts, max_label_len, \"total\", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt );\r\n", +" fprintf( stdout, \"\\n\" );\r\n", +"\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" fprintf( stdout, \"\\nComplexity analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n", +" fprintf( stdout, \"%*s %8s %10s %12s\\n\", max_label_len, \" routine\", \" calls\", \" SELF\", \" CUMULATIVE\" );\r\n", +" fprintf( stdout, \"%*s %8s %10s %10s\\n\", max_label_len, \"---------------\", \"------\", \"------\", \"----------\" );\r\n", +"\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" if ( wmops[i].wc_call_number > 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"%*s %8d %10.3f %12.3f\\n\", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, \"\\nCall tree for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n", +" fprintf( stdout, sfmtt, \" function\", \"num\", \"called by \" );\r\n", +" fprintf( stdout, sfmtt, \"---------------\", \"---\", \"--------------\" );\r\n", +"\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" if ( wmops[i].wc_call_number > 0 )\r\n", +" {\r\n", +" fprintf( stdout, dfmtt, wmops[i].label, i );\r\n", +" for ( j = 0; wmops[i].call_tree[j] != -1 && j < MAX_CALL_TREE_DEPTH; j++ )\r\n", +" {\r\n", +" if ( j != 0 )\r\n", +" {\r\n", +" fprintf( stdout, \", \" );\r\n", +" }\r\n", +" fprintf( stdout, \"%d\", wmops[i].call_tree[j] );\r\n", +" }\r\n", +" fprintf( stdout, \"\\n\" );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, \"\\n\\n\" );\r\n", +"\r\n", +" fprintf( stdout, \"\\nInstruction type analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc ); \r\n", +" for ( i = 0; i < NUM_INST; i++ )\r\n", +" {\r\n", +" switch ( (enum instructions) i )\r\n", +" {\r\n", +" case _ADD:\r\n", +" fprintf( stdout, \"\\tAdds: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _ABS:\r\n", +" fprintf( stdout, \"\\tAbsolutes: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _MULT:\r\n", +" fprintf( stdout, \"\\tMultiplies: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _MAC:\r\n", +" fprintf( stdout, \"\\tMACs: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _MOVE:\r\n", +" fprintf( stdout, \"\\tMoves: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _STORE:\r\n", +" fprintf( stdout, \"\\tStores: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _LOGIC:\r\n", +" fprintf( stdout, \"\\tLogicals: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _SHIFT:\r\n", +" fprintf( stdout, \"\\tShifts: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _BRANCH:\r\n", +" fprintf( stdout, \"\\tBranches: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _DIV:\r\n", +" fprintf( stdout, \"\\tDivisions: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _SQRT:\r\n", +" fprintf( stdout, \"\\tSquare Root: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _TRANS:\r\n", +" fprintf( stdout, \"\\tTrans: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _FUNC:\r\n", +" fprintf( stdout, \"\\tFunc Call: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _LOOP:\r\n", +" fprintf( stdout, \"\\tLoop Init: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _INDIRECT:\r\n", +" fprintf( stdout, \"\\tIndirect Addr: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _PTR_INIT:\r\n", +" fprintf( stdout, \"\\tPointer Init: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _TEST:\r\n", +" fprintf( stdout, \"\\tExtra condit.: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _POWER:\r\n", +" fprintf( stdout, \"\\tExponential: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _LOG:\r\n", +" fprintf( stdout, \"\\tLogarithm: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _MISC:\r\n", +" fprintf( stdout, \"\\tAll other op.: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" default:\r\n", +" fprintf( stdout, \"\\tERROR: Invalid instruction type: %d\\n\\n\", i );\r\n", +" }\r\n", +" }\r\n", +"#endif\r\n", +"\r\n", +" /* De-allocate the list of wmops record */\r\n", +" if ( wmops != NULL )\r\n", +" {\r\n", +" free( wmops );\r\n", +" }\r\n", +"\r\n", +" /* De-allocate the list of wmops caller functions */\r\n", +" if ( wmops_caller_stack != NULL )\r\n", +" {\r\n", +" free( wmops_caller_stack );\r\n", +" }\r\n", +"\r\n", +" /* De-allocate the BASOP WMOPS counter */\r\n", +" if ( multiCounter != NULL )\r\n", +" {\r\n", +" free( multiCounter );\r\n", +" }\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * Memory counting tool measuring RAM usage (stack and heap)\r\n", +" *\r\n", +" * Maximum RAM is measured by monitoring the total allocated memory (stack and heap) in each frame.\r\n", +" *\r\n", +" * Maximum stack is measured by monitoring the difference between the 'top' and 'bottom' of the stack. The 'bottom' of the stack is updated in each function\r\n", +" * with a macro 'func_start_' which is inserted automatically to all functions during the instrumentation process.\r\n", +" *\r\n", +" * Maximum heap is measured by summing the sizes of all memory blocks allocated by malloc() or calloc() and deallocated by free(). The maximum heap size is\r\n", +" * updated each time when the macros malloc_() or calloc_() is invoked. The macros 'malloc_ and calloc_' are inserted automatically during the instrumentation process.\r\n", +" * As part of heap measurements, intra-frame heap and inter-frame heap are measured separately. Intra-frame heap refers to heap memory which is allocated and deallocated\r\n", +" * within a single frame. Inter-frame heap, on the contrary, refers to heap memory which is reserved for more than one frame.\r\n", +" *\r\n", +" * In order to run the memory counting tool the function reset_mem(cnt_size) must be called at the beginning of the encoding/decoding process.\r\n", +" * The unit in which memory consumption is reported is set via the parameter 'cnt_size'. It can be set to 0 (bytes), 1 (32b words) or 2 (64b words).\r\n", +" * At the end of the encoding/decoding process, 'print_mem()' function may be called to print basic information about memory consumption. If the macro 'MEM_COUNT_DETAILS'\r\n", +" * is activated, detailed information is printed\r\n", +" *\r\n", +" * The macro 'WMOPS' needs to be activated to enable memory counting. To avoid the instrumentation of malloc()/calloc()/free() calls, use\r\n", +" * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free().\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using\r\n", +" a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */\r\n", +"#ifdef MEM_ALIGN_64BITS\r\n", +"#define BLOCK_ROUNDING 8 /* Align on 64 Bits */\r\n", +"#else\r\n", +"#define BLOCK_ROUNDING 4 /* Align on 32 Bits */\r\n", +"#endif\r\n", +"\r\n", +"#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) )\r\n", +"#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) )\r\n", +"\r\n", +"#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */\r\n", +"#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */\r\n", +"#define OOB_START 0x1 /* Flag indicating out-of-bounds access before memory block */\r\n", +"#define OOB_END 0x2 /* Flag indicating out-of-bounds access after memory block */\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +"const char *csv_filename = \"mem_analysis.csv\";\r\n", +"static FILE *fid_csv_filename = NULL;\r\n", +"#endif\r\n", +"\r\n", +"typedef struct\r\n", +"{\r\n", +" char function_name[MAX_FUNCTION_NAME_LENGTH + 1];\r\n", +" int16_t *stack_ptr;\r\n", +"} caller_info;\r\n", +"\r\n", +"static caller_info *stack_callers[2] = {NULL, NULL};\r\n", +"\r\n", +"static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */\r\n", +"static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */\r\n", +"static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */\r\n", +"static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */\r\n", +"static int current_calls = 0, max_num_calls = MAX_NUM_RECORDS;\r\n", +"static char location_max_stack[256] = \"undefined\";\r\n", +"\r\n", +"/* Heap-related variables */\r\n", +"typedef struct\r\n", +"{\r\n", +" char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */\r\n", +" char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */\r\n", +" unsigned long hash;\r\n", +" int lineno;\r\n", +" void *block_ptr;\r\n", +" int block_size;\r\n", +" unsigned long total_block_size; /* Cumulative sum of the allocated size in the session */\r\n", +" unsigned long total_used_size; /* Cumulative sum of the used size in the session */\r\n", +" int wc_heap_size_intra_frame; /* Worst-Case Intra-Frame Heap Size */\r\n", +" int wc_heap_size_inter_frame; /* Worst-Case Inter-Frame Heap Size */\r\n", +" int frame_allocated; /* Frame number in which the Memory Block has been allocated (-1 if not allocated at the moment) */\r\n", +" int OOB_Flag;\r\n", +" int noccurances; /* Number of times that the memory block has been allocated in a frame */\r\n", +"} allocator_record;\r\n", +"\r\n", +"allocator_record *allocation_list = NULL;\r\n", +"\r\n", +"static int Num_Records, Max_Num_Records;\r\n", +"static size_t Stat_Cnt_Size = USE_BYTES;\r\n", +"static const char *Count_Unit[] = { \"bytes\", \"words\", \"words\", \"words\" };\r\n", +"\r\n", +"static int32_t wc_ram_size, wc_ram_frame;\r\n", +"static int32_t current_heap_size;\r\n", +"static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap;\r\n", +"static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap;\r\n", +"static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap;\r\n", +"\r\n", +"/* Local Functions */\r\n", +"static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str );\r\n", +"allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record );\r\n", +"static void *mem_alloc_block( size_t size, const char *size_str );\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * reset_mem()\r\n", +" *\r\n", +" * Initialize/reset memory counting tool (stack and heap)\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"void reset_mem( Counting_Size cnt_size )\r\n", +"{\r\n", +" int16_t something;\r\n", +" size_t tmp_size;\r\n", +"\r\n", +" /* initialize list of stack records */\r\n", +" if ( stack_callers[0] == NULL )\r\n", +" {\r\n", +" stack_callers[0] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n", +" stack_callers[1] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n", +" }\r\n", +"\r\n", +" if ( stack_callers[0] == NULL || stack_callers[1] == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Unable to Allocate List of Stack Records!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" current_calls = 0;\r\n", +" max_num_calls = MAX_NUM_RECORDS;\r\n", +"\r\n", +" /* initialize stack pointers */\r\n", +" ptr_base_stack = &something;\r\n", +" ptr_max_stack = ptr_base_stack;\r\n", +" ptr_current_stack = ptr_base_stack;\r\n", +"\r\n", +" /* initialize the unit of memory block size */\r\n", +" Stat_Cnt_Size = cnt_size;\r\n", +"\r\n", +" /* Check, if sizeof(int32_t) is 4 bytes */\r\n", +" tmp_size = sizeof( int32_t );\r\n", +" if ( tmp_size != 4 )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Expecting 'int32_t' to be a 32 Bits Integer!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* create allocation list for malloc() memory blocks */\r\n", +" if ( allocation_list == NULL )\r\n", +" {\r\n", +" allocation_list = malloc( MAX_NUM_RECORDS * sizeof( allocator_record ) );\r\n", +" }\r\n", +"\r\n", +" if ( allocation_list == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Unable to Create List of Memory Blocks!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" Num_Records = 0;\r\n", +" Max_Num_Records = MAX_NUM_RECORDS;\r\n", +"\r\n", +" wc_ram_size = 0;\r\n", +" wc_ram_frame = -1;\r\n", +" current_heap_size = 0;\r\n", +"\r\n", +" /* heap allocation tree */\r\n", +" heap_allocation_call_tree_max_size = MAX_NUM_RECORDS;\r\n", +" if ( heap_allocation_call_tree == NULL )\r\n", +" {\r\n", +" heap_allocation_call_tree = (int *) malloc( heap_allocation_call_tree_max_size * sizeof( int ) );\r\n", +" memset( heap_allocation_call_tree, -1, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n", +" }\r\n", +" heap_allocation_call_tree_size = 0;\r\n", +"\r\n", +" /* wc intra-frame heap */\r\n", +" max_items_wc_intra_frame_heap = MAX_NUM_RECORDS;\r\n", +" if ( list_wc_intra_frame_heap == NULL )\r\n", +" {\r\n", +" list_wc_intra_frame_heap = (int *) malloc( max_items_wc_intra_frame_heap * sizeof( int ) );\r\n", +" memset( list_wc_intra_frame_heap, -1, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n", +" }\r\n", +" n_items_wc_intra_frame_heap = 0;\r\n", +" size_wc_intra_frame_heap = 0;\r\n", +" location_wc_intra_frame_heap = -1;\r\n", +"\r\n", +" /* current inter-frame heap */\r\n", +" max_items_current_inter_frame_heap = MAX_NUM_RECORDS;\r\n", +" if ( list_current_inter_frame_heap == NULL )\r\n", +" {\r\n", +" list_current_inter_frame_heap = (int *) malloc( max_items_current_inter_frame_heap * sizeof( int ) );\r\n", +" memset( list_current_inter_frame_heap, -1, max_items_current_inter_frame_heap * sizeof( int ) );\r\n", +" }\r\n", +" n_items_current_inter_frame_heap = 0;\r\n", +" size_current_inter_frame_heap = 0;\r\n", +"\r\n", +" /* wc inter-frame heap */\r\n", +" max_items_wc_inter_frame_heap = MAX_NUM_RECORDS;\r\n", +" if ( list_wc_inter_frame_heap == NULL )\r\n", +" {\r\n", +" list_wc_inter_frame_heap = (int *) malloc( max_items_wc_inter_frame_heap * sizeof( int ) );\r\n", +" memset( list_wc_inter_frame_heap, -1, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n", +" }\r\n", +" n_items_wc_inter_frame_heap = 0;\r\n", +" size_wc_inter_frame_heap = 0;\r\n", +" location_wc_inter_frame_heap = -1;\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +" /* Check, if the .csv file has already been opened */\r\n", +" if ( fid_csv_filename == NULL )\r\n", +" {\r\n", +" fid_csv_filename = fopen( csv_filename, \"wb\" );\r\n", +"\r\n", +" if ( fid_csv_filename == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", csv_filename );\r\n", +" exit( -1 );\r\n", +" }\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" /* reset file */\r\n", +" rewind( fid_csv_filename );\r\n", +" }\r\n", +"#endif\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * reset_stack()\r\n", +" *\r\n", +" * Reset stack pointer\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"void reset_stack( void )\r\n", +"{\r\n", +" int16_t something;\r\n", +"\r\n", +" /* initialize/reset stack pointers */\r\n", +" ptr_base_stack = &something;\r\n", +" ptr_max_stack = ptr_base_stack;\r\n", +" ptr_current_stack = ptr_base_stack;\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * push_stack()\r\n", +" *\r\n", +" * Check the current stack pointer and update the maximum stack pointer, if new maximum found.\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"int push_stack( const char *filename, const char *fctname )\r\n", +"{\r\n", +" int16_t something;\r\n", +" int32_t current_stack_size;\r\n", +"\r\n", +" ptr_current_stack = &something;\r\n", +"\r\n", +" (void) *filename; /* to avoid compilation warning */\r\n", +"\r\n", +" if ( current_calls >= max_num_calls )\r\n", +" {\r\n", +" /* There is no room for a new record -> reallocate the list */\r\n", +" max_num_calls += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" stack_callers[0] = realloc( stack_callers[0], max_num_calls * sizeof( caller_info ) );\r\n", +" stack_callers[1] = realloc( stack_callers[1], max_num_calls * sizeof( caller_info ) );\r\n", +" }\r\n", +"\r\n", +" /* Valid Function Name? */\r\n", +" if ( fctname[0] == 0 )\r\n", +" { /* No */\r\n", +" fprintf( stderr, \"Invalid function name for call stack info.\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* Save the Name of the Calling Function in the Table */\r\n", +" strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FUNCTION_NAME_LENGTH );\r\n", +" stack_callers[0][current_calls].function_name[MAX_FUNCTION_NAME_LENGTH] = 0; /* Nul Terminate */\r\n", +"\r\n", +" /* Save the Stack Pointer */\r\n", +" stack_callers[0][current_calls].stack_ptr = ptr_current_stack;\r\n", +"\r\n", +" /* Increase the Number of Calls in the List */\r\n", +" current_calls++;\r\n", +"\r\n", +" /* Is this the First Time or the Worst Case? */\r\n", +" if ( ptr_current_stack < ptr_max_stack || ptr_max_stack == NULL )\r\n", +" { /* Yes */\r\n", +" /* Save Info about it */\r\n", +" ptr_max_stack = ptr_current_stack;\r\n", +"\r\n", +" /* save the worst-case frame number */\r\n", +" /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */\r\n", +" wc_stack_frame = update_cnt; \r\n", +" strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 );\r\n", +" location_max_stack[sizeof( location_max_stack ) - 1] = '\\0';\r\n", +"\r\n", +" /* Save Call Tree */\r\n", +" memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls );\r\n", +"\r\n", +" /* Terminate the List with 0 (for printing purposes) */\r\n", +" if ( current_calls < max_num_calls )\r\n", +" {\r\n", +" stack_callers[1][current_calls].function_name[0] = 0;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Check, if This is the New Worst-Case RAM (stack + heap) */\r\n", +" current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) );\r\n", +"\r\n", +" if ( current_stack_size < 0 )\r\n", +" {\r\n", +" /* prevent negative stack size */\r\n", +" current_stack_size = 0;\r\n", +" }\r\n", +"\r\n", +" if ( current_stack_size + current_heap_size > wc_ram_size )\r\n", +" {\r\n", +" wc_ram_size = current_stack_size + current_heap_size;\r\n", +" wc_ram_frame = update_cnt;\r\n", +" }\r\n", +"\r\n", +" return 0 /* for Now */;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * pop_stack()\r\n", +" *\r\n", +" * Remove stack caller entry from the list\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"int pop_stack( const char *filename, const char *fctname )\r\n", +"{\r\n", +" caller_info *caller_info_ptr;\r\n", +"\r\n", +" (void) *filename; /* to avoid compilation warning */\r\n", +"\r\n", +" /* Decrease the Number of Records */\r\n", +" current_calls--;\r\n", +"\r\n", +" /* Get Pointer to Caller Information */\r\n", +" caller_info_ptr = &stack_callers[0][current_calls];\r\n", +"\r\n", +" /* Check, if the Function Names Match */\r\n", +" if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 )\r\n", +" {\r\n", +" fprintf( stderr, \"Invalid usage of pop_stack()\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* Erase Entry */\r\n", +" caller_info_ptr->function_name[0] = 0;\r\n", +"\r\n", +" /* Retrieve previous stack pointer */\r\n", +" if ( current_calls == 0 )\r\n", +" {\r\n", +" ptr_current_stack = ptr_base_stack;\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" ptr_current_stack = stack_callers[0][current_calls - 1].stack_ptr;\r\n", +" }\r\n", +"\r\n", +" return 0 /* for Now */;\r\n", +"}\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * print_stack_call_tree()\r\n", +" *\r\n", +" * Print detailed information about worst-case stack usage\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static void print_stack_call_tree( void )\r\n", +"{\r\n", +" caller_info *caller_info_ptr;\r\n", +" int call_level;\r\n", +" char fctname[MAX_FUNCTION_NAME_LENGTH + 1];\r\n", +"\r\n", +" fprintf( stdout, \"\\nList of functions when maximum stack size is reached:\\n\\n\" );\r\n", +"\r\n", +" caller_info_ptr = &stack_callers[1][0];\r\n", +" for ( call_level = 0; call_level < max_num_calls; call_level++ )\r\n", +" {\r\n", +" /* Done? */\r\n", +" if ( caller_info_ptr->function_name[0] == 0 )\r\n", +" {\r\n", +" break;\r\n", +" }\r\n", +"\r\n", +" /* Print Name */\r\n", +" strncpy( fctname, caller_info_ptr->function_name, MAX_FUNCTION_NAME_LENGTH );\r\n", +" strcat( fctname, \"()\" );\r\n", +" fprintf( stdout, \"%-42s\", fctname );\r\n", +"\r\n", +" /* Print Stack Usage (Based on Difference) */\r\n", +" if ( call_level != 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"%lu %s\\n\", ( ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" fprintf( stdout, \"%lu %s\\n\", ( ( ptr_base_stack - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +"\r\n", +" /* Advance */\r\n", +" caller_info_ptr++;\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, \"\\n\" );\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"#endif\r\n", +"\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * mem_alloc()\r\n", +" *\r\n", +" * Creates new record, stores auxiliary information about which function allocated the memory, line number, parameters, etc.\r\n", +" * Finally, it allocates physical memory using malloc()\r\n", +" * The function also updates worst-case heap size and worst-case RAM size\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"void *mem_alloc(\r\n", +" const char *func_name,\r\n", +" int func_lineno,\r\n", +" size_t size,\r\n", +" char *size_str /* the first char indicates m-alloc or c-alloc */ )\r\n", +"{\r\n", +" int index_record;\r\n", +" int32_t current_stack_size;\r\n", +" unsigned long hash;\r\n", +" allocator_record *ptr_record;\r\n", +"\r\n", +" if ( size == 0 )\r\n", +" {\r\n", +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Size of Zero not Supported\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* Search for an existing record (that has been de-allocated before) */\r\n", +" index_record = 0;\r\n", +" while ( ( ptr_record = get_mem_record( &hash, func_name, func_lineno, size_str, &index_record ) ) != NULL )\r\n", +" {\r\n", +" if ( ptr_record->frame_allocated == -1 )\r\n", +" {\r\n", +" break;\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" index_record++;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Create new record */\r\n", +" if ( ptr_record == NULL )\r\n", +" {\r\n", +" if ( Num_Records >= Max_Num_Records )\r\n", +" {\r\n", +" /* There is no room for a new record -> reallocate memory */\r\n", +" Max_Num_Records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" allocation_list = realloc( allocation_list, Max_Num_Records * sizeof( allocator_record ) );\r\n", +" }\r\n", +"\r\n", +" ptr_record = &( allocation_list[Num_Records] );\r\n", +"\r\n", +" /* Initialize new record */\r\n", +" ptr_record->hash = hash;\r\n", +" ptr_record->noccurances = 0;\r\n", +" ptr_record->total_block_size = 0;\r\n", +" ptr_record->total_used_size = 0;\r\n", +" ptr_record->frame_allocated = -1;\r\n", +" ptr_record->OOB_Flag = 0;\r\n", +" ptr_record->wc_heap_size_intra_frame = -1;\r\n", +" ptr_record->wc_heap_size_inter_frame = -1;\r\n", +"\r\n", +" index_record = Num_Records;\r\n", +" Num_Records++;\r\n", +" }\r\n", +"\r\n", +" /* Allocate memory block for the new record, add signature before the beginning and after the memory block and fill it with magic value */\r\n", +" ptr_record->block_ptr = mem_alloc_block( size, size_str );\r\n", +"\r\n", +" if ( ptr_record->block_ptr == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Cannot Allocate Memory!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* Save all auxiliary information about the memory block */\r\n", +" strncpy( ptr_record->name, func_name, MAX_FUNCTION_NAME_LENGTH );\r\n", +" ptr_record->name[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n", +" strncpy( ptr_record->params, size_str, MAX_PARAMS_LENGTH ); /* Note: The size string starts with either 'm' or 'c' to indicate 'm'alloc or 'c'alloc */\r\n", +" ptr_record->params[MAX_PARAMS_LENGTH] = '\\0';\r\n", +" ptr_record->lineno = func_lineno;\r\n", +" ptr_record->block_size = size;\r\n", +" ptr_record->total_block_size += size;\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +" /* Export heap memory allocation record to the .csv file */\r\n", +" fprintf( fid_csv_filename, \"A,%d,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n", +"#endif\r\n", +"\r\n", +" if ( ptr_record->frame_allocated != -1 )\r\n", +" {\r\n", +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Attempt to Allocate the Same Memory Block with Freeing it First!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" ptr_record->frame_allocated = update_cnt; /* Store the current frame number -> later it will be used to determine the total duration */\r\n", +"\r\n", +" /* Update Heap Size in the current frame */\r\n", +" current_heap_size += ptr_record->block_size;\r\n", +"\r\n", +" /* Check, if this is the new Worst-Case RAM (stack + heap) */\r\n", +" current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) );\r\n", +" if ( current_stack_size + current_heap_size > wc_ram_size )\r\n", +" {\r\n", +" wc_ram_size = current_stack_size + current_heap_size;\r\n", +" wc_ram_frame = update_cnt;\r\n", +" }\r\n", +"\r\n", +" /* Add new entry to the heap allocation call tree */\r\n", +" if ( heap_allocation_call_tree == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Heap allocation call tree not created!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* check, if the maximum size of the call tree has been reached -> resize if so */\r\n", +" if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size )\r\n", +" {\r\n", +" heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" /* push new entry (positive number means push op, neagtive number means pop op; zero index must be converted to 0.01 :-) */\r\n", +" heap_allocation_call_tree[heap_allocation_call_tree_size++] = index_record;\r\n", +"\r\n", +" return ptr_record->block_ptr;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * mem_alloc_block()\r\n", +" *\r\n", +" * Physical allocation of memory using malloc(). Appends 'signature' before and after the block,\r\n", +" * pre-fills memory block with magic value\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static void *mem_alloc_block( size_t size, const char *size_str )\r\n", +"{\r\n", +" size_t rounded_size;\r\n", +" void *block_ptr;\r\n", +" char *tmp_ptr;\r\n", +" size_t n, f;\r\n", +" int32_t fill_value;\r\n", +" int32_t *ptr32;\r\n", +" int32_t mask, temp;\r\n", +"\r\n", +" /* Round Up Block Size */\r\n", +" rounded_size = ROUND_BLOCK_SIZE( size );\r\n", +"\r\n", +" /* Allocate memory using the standard malloc() by adding room for Signature Values */\r\n", +" block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 );\r\n", +"\r\n", +" if ( block_ptr == NULL )\r\n", +" {\r\n", +" return NULL;\r\n", +" }\r\n", +"\r\n", +" /* Add Signature Before the Start of the Block */\r\n", +" ptr32 = (int32_t *) block_ptr;\r\n", +" n = N_32BITS_BLOCKS;\r\n", +" do\r\n", +" {\r\n", +" *ptr32++ = MAGIC_VALUE_OOB;\r\n", +" } while ( --n );\r\n", +"\r\n", +" /* Fill Memory Block with Magic Value or 0 */\r\n", +" fill_value = MAGIC_VALUE_USED;\r\n", +" if ( size_str[0] == 'c' )\r\n", +" {\r\n", +" fill_value = 0x00000000;\r\n", +" }\r\n", +" n = size / sizeof( int32_t );\r\n", +" while ( n-- )\r\n", +" {\r\n", +" *ptr32++ = fill_value;\r\n", +" }\r\n", +"\r\n", +" /* Fill the Reminder of the Memory Block - After Rounding */\r\n", +" n = rounded_size - size;\r\n", +" f = n % sizeof( int32_t );\r\n", +" if ( f != 0 )\r\n", +" {\r\n", +" /* when filling with '0' need to adapt the magic value */\r\n", +" /* shift by [1->24, 2->16, 3->8] */\r\n", +" mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */\r\n", +" temp = MAGIC_VALUE_OOB & mask;\r\n", +" if ( fill_value != 0x0 )\r\n", +" { /* for malloc merge fill value */\r\n", +" temp += ( ~mask ) & MAGIC_VALUE_USED;\r\n", +" } /* for calloc the code in (1) above already introduces zeros */\r\n", +" *ptr32++ = temp;\r\n", +" }\r\n", +" n /= sizeof( int32_t );\r\n", +" n += N_32BITS_BLOCKS;\r\n", +"\r\n", +" /* Add Signature After the End of Block */\r\n", +" do\r\n", +" {\r\n", +" *ptr32++ = MAGIC_VALUE_OOB;\r\n", +" } while ( --n );\r\n", +"\r\n", +" /* Adjust the Memory Block Pointer (Magic Value Before and After the Memory Block Requested) */\r\n", +" tmp_ptr = (char *) block_ptr;\r\n", +" tmp_ptr += BLOCK_ROUNDING;\r\n", +" block_ptr = (void *) tmp_ptr;\r\n", +"\r\n", +" return block_ptr;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * mem_set_usage()\r\n", +" *\r\n", +" * Calculates actual usage of memory block by checking the magic value that was used to pre-fill\r\n", +" * each memory block during its allocation\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static int mem_set_usage( allocator_record *record_ptr )\r\n", +"{\r\n", +" int total_bytes_used;\r\n", +"\r\n", +" size_t n;\r\n", +" int32_t *ptr32;\r\n", +" char *ptr8;\r\n", +" size_t total_bytes;\r\n", +" int32_t fill_value;\r\n", +"\r\n", +" fill_value = MAGIC_VALUE_USED;\r\n", +" if ( ( record_ptr->params[0] ) == 'c' )\r\n", +" {\r\n", +" fill_value = 0x00000000;\r\n", +" }\r\n", +"\r\n", +" total_bytes = record_ptr->block_size;\r\n", +"\r\n", +" /* Check 4 bytes at a time */\r\n", +" ptr32 = (int32_t *) record_ptr->block_ptr;\r\n", +" total_bytes_used = 0;\r\n", +" for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- )\r\n", +" {\r\n", +" if ( *ptr32++ != fill_value )\r\n", +" {\r\n", +" total_bytes_used += sizeof( int32_t );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Check remaining bytes (If Applicable) 1 byte at a time */\r\n", +" ptr8 = (char *) ptr32;\r\n", +" for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- )\r\n", +" {\r\n", +" if ( *ptr8++ != (char) fill_value )\r\n", +" {\r\n", +" total_bytes_used++;\r\n", +" }\r\n", +"\r\n", +" /* Update Value */\r\n", +" fill_value >>= 8;\r\n", +" }\r\n", +"\r\n", +" return total_bytes_used;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * mem_check_OOB()\r\n", +" *\r\n", +" * Checks, if out-of-bounds access has occured. This is done by inspecting the 'signature' value\r\n", +" * taht has been added before and after the memory block during its allocation\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static unsigned int mem_check_OOB( allocator_record *record_ptr )\r\n", +"{\r\n", +" int32_t *ptr32;\r\n", +" unsigned int OOB_Flag = 0x0;\r\n", +" int32_t mask;\r\n", +" size_t i;\r\n", +" int f;\r\n", +"\r\n", +" ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS;\r\n", +"\r\n", +" /* Check the Signature at the Beginning of Memory Block */\r\n", +" i = N_32BITS_BLOCKS;\r\n", +" do\r\n", +" {\r\n", +" if ( *ptr32++ ^ MAGIC_VALUE_OOB )\r\n", +" {\r\n", +" OOB_Flag |= OOB_START;\r\n", +" }\r\n", +" } while ( --i );\r\n", +"\r\n", +" /* Advance to End (Snap to lowest 32 Bits) */\r\n", +" ptr32 += record_ptr->block_size / sizeof( int32_t );\r\n", +"\r\n", +" /* Calculate Unused Space That has been added to get to the rounded Block Size */\r\n", +" i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size;\r\n", +"\r\n", +" /* Partial Check of Signature at the End of Memory Block (for block size that has been rounded) */\r\n", +" f = i % sizeof( int32_t );\r\n", +" if ( f != 0 )\r\n", +" {\r\n", +" mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 );\r\n", +" if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask )\r\n", +" {\r\n", +" OOB_Flag |= OOB_END;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Full Check of Signature at the End of Memory Block, i.e. all 32 Bits (for the remainder after rounding) */\r\n", +" i /= sizeof( int32_t );\r\n", +" i += N_32BITS_BLOCKS;\r\n", +" do\r\n", +" {\r\n", +" if ( *ptr32++ ^ MAGIC_VALUE_OOB )\r\n", +" {\r\n", +" OOB_Flag |= OOB_END;\r\n", +" }\r\n", +" } while ( --i );\r\n", +"\r\n", +" return OOB_Flag;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * malloc_hash()\r\n", +" *\r\n", +" * Calculate hash from function name, line number and malloc size\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str )\r\n", +"{\r\n", +" unsigned long hash = 5381;\r\n", +" const char *ptr_str;\r\n", +"\r\n", +" ptr_str = func_name;\r\n", +" while ( ptr_str != NULL && *ptr_str != '\\0' )\r\n", +" {\r\n", +" hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */\r\n", +" }\r\n", +"\r\n", +" hash = ( ( hash << 5 ) + hash ) + func_lineno; /* hash * 33 + func_lineno */\r\n", +"\r\n", +" ptr_str = size_str;\r\n", +" while ( ptr_str != NULL && *ptr_str != '\\0' )\r\n", +" {\r\n", +" hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */\r\n", +" }\r\n", +"\r\n", +" return hash;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * get_mem_record()\r\n", +" *\r\n", +" * Search for memory record in the internal list, return NULL if not found\r\n", +" * Start from index_record\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record )\r\n", +"{\r\n", +" int i;\r\n", +"\r\n", +" if ( *index_record < 0 || *index_record > Num_Records )\r\n", +" {\r\n", +" return NULL;\r\n", +" }\r\n", +"\r\n", +" /* calculate hash */\r\n", +" *hash = malloc_hash( func_name, func_lineno, size_str );\r\n", +"\r\n", +" for ( i = *index_record; i < Num_Records; i++ )\r\n", +" {\r\n", +" /* check, if memory block is not allocated at the moment and the hash matches */\r\n", +" if ( allocation_list[i].block_ptr == NULL && *hash == allocation_list[i].hash )\r\n", +" {\r\n", +" *index_record = i;\r\n", +" return &( allocation_list[i] );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* not found */\r\n", +" *index_record = -1;\r\n", +" return NULL;\r\n", +"}\r\n", +"\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * mem_free()\r\n", +" *\r\n", +" * This function de-allocatesd the memory block and frees the mphysical memory with free().\r\n", +" * It also updates actual and average usage of the memory block.\r\n", +" *\r\n", +" * Note: The record is not removed from the list and may be reused later on in mem_alloc()!\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"void mem_free( const char *func_name, int func_lineno, void *ptr )\r\n", +"{\r\n", +" int i, index_record;\r\n", +" char *tmp_ptr;\r\n", +" allocator_record *ptr_record;\r\n", +"\r\n", +" /* Search for the Block Pointer in the List */\r\n", +" ptr_record = NULL;\r\n", +" index_record = -1;\r\n", +" for ( i = 0; i < Num_Records; i++ )\r\n", +" {\r\n", +" if ( ptr == allocation_list[i].block_ptr )\r\n", +" { /* Yes, Found it */\r\n", +" ptr_record = &( allocation_list[i] );\r\n", +" index_record = i;\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" if ( ptr_record == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Unable to Find Record Corresponding to the Allocated Memory Block!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* Update the Heap Size */\r\n", +" current_heap_size -= ptr_record->block_size;\r\n", +"\r\n", +" /* Calculate the Actual Usage of the Memory Block (Look for Signature) */\r\n", +" ptr_record->total_used_size += mem_set_usage( ptr_record );\r\n", +"\r\n", +" /* Check, if Out-Of-Bounds Access has been Detected */\r\n", +" ptr_record->OOB_Flag = mem_check_OOB( ptr_record );\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +" /* Export heap memory de-allocation record to the .csv file */\r\n", +" fprintf( fid_csv_filename, \"D,%d,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n", +"#endif\r\n", +"\r\n", +" /* De-Allocate Memory Block */\r\n", +" tmp_ptr = (char *) ptr;\r\n", +" tmp_ptr -= BLOCK_ROUNDING;\r\n", +" ptr = (void *) tmp_ptr;\r\n", +" free( ptr );\r\n", +"\r\n", +" /* Add new entry to the heap allocation call tree */\r\n", +" if ( heap_allocation_call_tree == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Heap allocation call tree not created!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* check, if the maximum size of the call tree has been reached -> resize if so */\r\n", +" if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size )\r\n", +" {\r\n", +" heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" heap_allocation_call_tree[heap_allocation_call_tree_size++] = -index_record;\r\n", +"\r\n", +" /* Reset memory block pointer (this is checked when updating wc intra-frame and inter-frame memory) */\r\n", +" ptr_record->block_ptr = NULL;\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * update_mem()\r\n", +" *\r\n", +" * This function updates the worst-case intra-frame memory and the worst-case inter-frame memory.\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"void update_mem( void )\r\n", +"{\r\n", +" int i, j, flag_alloc = -1, i_record;\r\n", +" int size_current_intra_frame_heap;\r\n", +" int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap;\r\n", +" allocator_record *ptr_record;\r\n", +"\r\n", +" /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */\r\n", +" n_items_current_intra_frame_heap = 0;\r\n", +" size_current_intra_frame_heap = 0;\r\n", +" for ( i = 0; i < heap_allocation_call_tree_size; i++ )\r\n", +" {\r\n", +" /* get the record */\r\n", +" i_record = heap_allocation_call_tree[i];\r\n", +"\r\n", +" if ( i_record > 0 )\r\n", +" {\r\n", +" flag_alloc = 1;\r\n", +" }\r\n", +" else if ( i_record < 0 )\r\n", +" {\r\n", +" flag_alloc = 0;\r\n", +" i_record = -i_record;\r\n", +" }\r\n", +" ptr_record = &( allocation_list[i_record] );\r\n", +"\r\n", +" if ( ptr_record->frame_allocated == update_cnt && ptr_record->block_ptr == NULL )\r\n", +" {\r\n", +" /* intra-frame heap memory */\r\n", +" if ( list_current_intra_frame_heap == NULL )\r\n", +" {\r\n", +" list_current_intra_frame_heap = (int *) malloc( heap_allocation_call_tree_size * sizeof( int ) );\r\n", +" memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n", +" if ( i_record == 0 )\r\n", +" {\r\n", +" flag_alloc = 1;\r\n", +" for ( j = 0; j < n_items_current_intra_frame_heap; j++ )\r\n", +" {\r\n", +" if ( list_current_intra_frame_heap[j] == i_record )\r\n", +" {\r\n", +" flag_alloc = 0;\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" if ( flag_alloc )\r\n", +" {\r\n", +" /* add to list */\r\n", +" list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record;\r\n", +" size_current_intra_frame_heap += ptr_record->block_size;\r\n", +"\r\n", +" /* no need to re-size the list -> the initially allocated size should be large enough */\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" /* remove from list */\r\n", +" for ( j = 0; j < n_items_current_intra_frame_heap; j++ )\r\n", +" {\r\n", +" if ( list_current_intra_frame_heap[j] == i_record )\r\n", +" {\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +" memmove( &list_current_intra_frame_heap[j], &list_current_intra_frame_heap[j + 1], ( n_items_current_intra_frame_heap - j ) * sizeof( int ) );\r\n", +" n_items_current_intra_frame_heap--;\r\n", +" size_current_intra_frame_heap -= ptr_record->block_size;\r\n", +"\r\n", +" /* reset block size */\r\n", +" ptr_record->frame_allocated = -1;\r\n", +" ptr_record->block_size = 0;\r\n", +" }\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" /* inter-frame heap memory */\r\n", +"\r\n", +" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n", +" if ( i_record == 0 )\r\n", +" {\r\n", +" flag_alloc = 1;\r\n", +" for ( j = 0; j < n_items_current_inter_frame_heap; j++ )\r\n", +" {\r\n", +" if ( list_current_inter_frame_heap[j] == i_record )\r\n", +" {\r\n", +" flag_alloc = 0;\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" if ( flag_alloc )\r\n", +" {\r\n", +" /* add to list */\r\n", +" if ( n_items_current_inter_frame_heap >= max_items_current_inter_frame_heap )\r\n", +" {\r\n", +" /* resize list, if needed */\r\n", +" max_items_current_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" list_current_inter_frame_heap = realloc( list_current_inter_frame_heap, max_items_current_inter_frame_heap * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record;\r\n", +" size_current_inter_frame_heap += ptr_record->block_size;\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" /* remove from list */\r\n", +" for ( j = 0; j < n_items_current_inter_frame_heap; j++ )\r\n", +" {\r\n", +" if ( list_current_inter_frame_heap[j] == i_record )\r\n", +" {\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +" memmove( &list_current_inter_frame_heap[j], &list_current_inter_frame_heap[j + 1], ( n_items_current_inter_frame_heap - j ) * sizeof( int ) );\r\n", +" n_items_current_inter_frame_heap--;\r\n", +" size_current_inter_frame_heap -= ptr_record->block_size;\r\n", +"\r\n", +" /* reset block size */\r\n", +" ptr_record->frame_allocated = -1;\r\n", +" ptr_record->block_size = 0;\r\n", +" }\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* check, if this is the new worst-case for intra-frame heap memory */\r\n", +" if ( size_current_intra_frame_heap > size_wc_intra_frame_heap )\r\n", +" {\r\n", +" if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap )\r\n", +" {\r\n", +" /* resize the list, if needed */\r\n", +" max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" /* copy current-frame list to worst-case list */\r\n", +" memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) );\r\n", +" n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap;\r\n", +" size_wc_intra_frame_heap = size_current_intra_frame_heap;\r\n", +" location_wc_intra_frame_heap = update_cnt;\r\n", +"\r\n", +" /* update the wc numbers in all individual records */\r\n", +" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n", +" {\r\n", +" i_record = list_wc_intra_frame_heap[i];\r\n", +" ptr_record = &( allocation_list[i_record] );\r\n", +" ptr_record->wc_heap_size_intra_frame = ptr_record->block_size;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* check, if this is the new worst-case for inter-frame heap memory */\r\n", +" if ( size_current_inter_frame_heap > size_wc_inter_frame_heap )\r\n", +" {\r\n", +" if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap )\r\n", +" {\r\n", +" /* resize list, if needed */\r\n", +" max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" /* copy current-frame list to worst-case list */\r\n", +" memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) );\r\n", +" n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap;\r\n", +" size_wc_inter_frame_heap = size_current_inter_frame_heap;\r\n", +" location_wc_inter_frame_heap = update_cnt;\r\n", +"\r\n", +" /* update the wc numbers in all individual records */\r\n", +" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n", +" {\r\n", +" i_record = list_wc_inter_frame_heap[i];\r\n", +" ptr_record = &( allocation_list[i_record] );\r\n", +" ptr_record->wc_heap_size_inter_frame = ptr_record->block_size;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* reset heap allocation call tree */\r\n", +" heap_allocation_call_tree_size = 0;\r\n", +"\r\n", +" /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */\r\n", +" if ( list_current_intra_frame_heap )\r\n", +" {\r\n", +" free( list_current_intra_frame_heap );\r\n", +" }\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * subst()\r\n", +" *\r\n", +" * Substitute character in string\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static void subst( char *s, char from, char to )\r\n", +"{\r\n", +" while ( *s == from )\r\n", +" {\r\n", +" *s++ = to;\r\n", +" }\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * mem_count_summary()\r\n", +" *\r\n", +" * Print detailed (per-item) information about heap memory usage\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static void mem_count_summary( void )\r\n", +"{\r\n", +" int i, j, index, index_record;\r\n", +" size_t length;\r\n", +" char buf[300], format_str[50], name_str[MAX_FUNCTION_NAME_LENGTH + 3], parms_str[MAX_PARAMS_LENGTH + 1], type_str[10], usage_str[20], size_str[20], line_str[10];\r\n", +" allocator_record *ptr_record, *ptr;\r\n", +"\r\n", +" /* Prepare format string */\r\n", +" sprintf( format_str, \"%%-%ds %%5s %%6s %%-%ds %%20s %%6s \", MAX_FUNCTION_NAME_LENGTH, MAX_PARAMS_LENGTH );\r\n", +"\r\n", +" if ( n_items_wc_intra_frame_heap > 0 )\r\n", +" {\r\n", +" /* Intra-Frame Heap Size */\r\n", +" fprintf( stdout, \"\\nList of memory blocks when maximum intra-frame heap size is reached:\\n\\n\" );\r\n", +"\r\n", +" /* Find duplicate records (same hash and worst-case heap size) */\r\n", +" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n", +" {\r\n", +" index_record = list_wc_intra_frame_heap[i];\r\n", +" if ( index_record == -1 )\r\n", +" {\r\n", +" continue;\r\n", +" }\r\n", +"\r\n", +" ptr_record = &( allocation_list[index_record] );\r\n", +" for ( j = i + 1; j < n_items_wc_intra_frame_heap; j++ )\r\n", +" {\r\n", +" index = list_wc_intra_frame_heap[j];\r\n", +" if ( index == -1 )\r\n", +" {\r\n", +" continue;\r\n", +" }\r\n", +" ptr = &( allocation_list[index] );\r\n", +"\r\n", +" if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_intra_frame == ptr_record->wc_heap_size_intra_frame )\r\n", +" {\r\n", +" ptr_record->noccurances++;\r\n", +" list_wc_intra_frame_heap[j] = -1;\r\n", +" }\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Print Header */\r\n", +" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Maximum Size\", \"Usage\" );\r\n", +" puts( buf );\r\n", +" length = strlen( buf );\r\n", +" sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n", +" subst( buf, '0', '-' );\r\n", +" puts( buf );\r\n", +"\r\n", +" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n", +" {\r\n", +" index_record = list_wc_intra_frame_heap[i];\r\n", +"\r\n", +" if ( index_record != -1 )\r\n", +" {\r\n", +" /* get the record */\r\n", +" ptr_record = &( allocation_list[index_record] );\r\n", +"\r\n", +" /* prepare information strings */\r\n", +" strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH );\r\n", +" strcat( name_str, \"()\" );\r\n", +" name_str[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n", +" strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH );\r\n", +" parms_str[MAX_PARAMS_LENGTH] = '\\0';\r\n", +"\r\n", +" if ( ptr_record->params[0] == 'm' )\r\n", +" {\r\n", +" strcpy( type_str, \"malloc\" );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" strcpy( type_str, \"calloc\" );\r\n", +" }\r\n", +"\r\n", +" sprintf( line_str, \"%d\", ptr_record->lineno );\r\n", +"\r\n", +" /* prepare average usage & memory size strings */\r\n", +" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) );\r\n", +"\r\n", +" if ( ptr_record->noccurances > 1 )\r\n", +" {\r\n", +" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" sprintf( size_str, \"%d %s\", (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +"\r\n", +" sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str );\r\n", +" puts( buf );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, \"\\n\" );\r\n", +" }\r\n", +"\r\n", +" if ( n_items_wc_inter_frame_heap > 0 )\r\n", +" {\r\n", +" /* Inter-Frame Heap Size */\r\n", +" fprintf( stdout, \"\\nList of memory blocks when maximum inter-frame heap size is reached:\\n\\n\" );\r\n", +"\r\n", +" /* Find duplicate records (same hash and worst-case heap size) */\r\n", +" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n", +" {\r\n", +" index_record = list_wc_inter_frame_heap[i];\r\n", +" if ( index_record == -1 )\r\n", +" {\r\n", +" continue;\r\n", +" }\r\n", +" ptr_record = &( allocation_list[index_record] );\r\n", +" ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */\r\n", +" for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ )\r\n", +" {\r\n", +" index = list_wc_inter_frame_heap[j];\r\n", +" if ( index == -1 )\r\n", +" {\r\n", +" continue;\r\n", +" }\r\n", +" ptr = &( allocation_list[index] );\r\n", +"\r\n", +" if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_inter_frame == ptr_record->wc_heap_size_inter_frame )\r\n", +" {\r\n", +" ptr_record->noccurances++;\r\n", +" list_wc_inter_frame_heap[j] = -1;\r\n", +" }\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Print Header */\r\n", +" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Memory Size\", \"Usage\" );\r\n", +" puts( buf );\r\n", +" length = strlen( buf );\r\n", +" sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n", +" subst( buf, '0', '-' );\r\n", +" puts( buf );\r\n", +"\r\n", +" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n", +" {\r\n", +" index_record = list_wc_inter_frame_heap[i];\r\n", +"\r\n", +" if ( index_record != -1 )\r\n", +" {\r\n", +" /* get the record */\r\n", +" ptr_record = &( allocation_list[index_record] );\r\n", +"\r\n", +" /* prepare information strings */\r\n", +" strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH );\r\n", +" strcat( name_str, \"()\" );\r\n", +" name_str[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n", +" strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH );\r\n", +" parms_str[MAX_PARAMS_LENGTH] = '\\0';\r\n", +"\r\n", +" if ( ptr_record->params[0] == 'm' )\r\n", +" {\r\n", +" strcpy( type_str, \"malloc\" );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" strcpy( type_str, \"calloc\" );\r\n", +" }\r\n", +"\r\n", +" sprintf( line_str, \"%d\", ptr_record->lineno );\r\n", +"\r\n", +" /* prepare average usage & memory size strings */\r\n", +" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) );\r\n", +"\r\n", +" if ( ptr_record->noccurances > 1 )\r\n", +" {\r\n", +" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" sprintf( size_str, \"%d %s\", (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +"\r\n", +" sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str );\r\n", +" puts( buf );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, \"\\n\" );\r\n", +" }\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * print_mem()\r\n", +" *\r\n", +" * Print information about ROM and RAM memory usage\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] )\r\n", +"{\r\n", +" int i, nElem;\r\n", +"\r\n", +" fprintf( stdout, \"\\n\\n --- Memory usage --- \\n\\n\" );\r\n", +"\r\n", +" if ( Const_Data_PROM_Table != NULL )\r\n", +" {\r\n", +" nElem = 0;\r\n", +" while ( strcmp( Const_Data_PROM_Table[nElem].file_spec, \"\" ) != 0 )\r\n", +" nElem++;\r\n", +"\r\n", +" for ( i = 0; i < nElem; i++ )\r\n", +" {\r\n", +" if ( Stat_Cnt_Size > 0 )\r\n", +" {\r\n", +" /* words */\r\n", +" fprintf( stdout, \"Program ROM size (%s): %d words\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" /* bytes (here, we assume that each instruction takes PROM_INST_SIZE bits of the PROM memory) */\r\n", +" fprintf( stdout, \"Program ROM size (%s): %d bytes\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size * ( PROM_INST_SIZE / 8 ) );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" for ( i = 0; i < nElem; i++ )\r\n", +" {\r\n", +" if ( Const_Data_PROM_Table[i].Get_Const_Data_Size_Func == NULL )\r\n", +" {\r\n", +" fprintf( stdout, \"Error: Cannot retrieve or calculate Table ROM size of (%s)!\\n\", Const_Data_PROM_Table[i].file_spec );\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, \"Table ROM (const data) size (%s): %d %s\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].Get_Const_Data_Size_Func() >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" fprintf( stdout, \"Program ROM size: not available\\n\" );\r\n", +" fprintf( stdout, \"Table ROM (const data) size: not available\\n\" );\r\n", +" }\r\n", +"\r\n", +" if ( wc_ram_size > 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum RAM (stack + heap) size: %d %s in frame %d\\n\", wc_ram_size >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], wc_ram_frame );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum RAM (stack + heap) size: not available\\n\" );\r\n", +" }\r\n", +"\r\n", +" /* check, if the stack is empty */\r\n", +" if ( ptr_current_stack != ptr_base_stack )\r\n", +" {\r\n", +" fprintf( stderr, \"Warning: Stack is not empty.\\n\" );\r\n", +" }\r\n", +"\r\n", +" if ( ptr_base_stack - ptr_max_stack > 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum stack size: %lu %s in frame %d\\n\", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size],\r\n", +" wc_stack_frame );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum stack size: not available\\n\" );\r\n", +" }\r\n", +"\r\n", +" /* last update of intra-frame memory and inter-frame memory, if needed */\r\n", +" if ( heap_allocation_call_tree_size > 0 )\r\n", +" {\r\n", +" update_mem();\r\n", +" }\r\n", +"\r\n", +" /* check, if all memory blocks have been deallocated (freed) */\r\n", +" for ( i = 0; i < Num_Records; i++ )\r\n", +" {\r\n", +" if ( allocation_list[i].block_ptr != NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", allocation_list[i].name, allocation_list[i].lineno, \"Error: Memory Block has not been De-Allocated with free()!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" if ( n_items_wc_intra_frame_heap > 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum intra-frame heap size: %d %s in frame %d\\n\", size_wc_intra_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_intra_frame_heap );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum intra-frame heap size: 0\\n\" );\r\n", +" }\r\n", +"\r\n", +" if ( n_items_wc_inter_frame_heap > 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum inter-frame heap size: %d %s in frame %d\\n\", size_wc_inter_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_inter_frame_heap );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum inter-frame heap size: 0\\n\" );\r\n", +" }\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +" /* Print detailed information about worst-case stack usage */\r\n", +" if ( ptr_base_stack - ptr_max_stack > 0 )\r\n", +" {\r\n", +" print_stack_call_tree();\r\n", +" }\r\n", +"\r\n", +" /* Print detailed information about worst-case heap usage */\r\n", +" mem_count_summary();\r\n", +"#endif\r\n", +"\r\n", +" if ( Stat_Cnt_Size > 0 )\r\n", +" {\r\n", +" /* words */\r\n", +" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", 8 << Stat_Cnt_Size );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" /* bytes */\r\n", +" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", PROM_INST_SIZE );\r\n", +" }\r\n", +" fprintf( stdout, \"Note: The Data ROM size is calculated using the sizeof(type) built-in function\\n\" );\r\n", +"\r\n", +" if ( n_items_wc_intra_frame_heap > 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"Intra-frame heap memory is allocated and de-allocated in the same frame\\n\" );\r\n", +" }\r\n", +"\r\n", +" /* De-allocate list of heap memory blocks */\r\n", +" if ( allocation_list != NULL )\r\n", +" {\r\n", +" free( allocation_list );\r\n", +" }\r\n", +"\r\n", +" /* De-allocate list of stack records */\r\n", +" if ( stack_callers[0] != NULL )\r\n", +" {\r\n", +" free( stack_callers[0] );\r\n", +" }\r\n", +"\r\n", +" if ( stack_callers[1] != NULL )\r\n", +" {\r\n", +" free( stack_callers[1] );\r\n", +" }\r\n", +"\r\n", +" /* De-allocate heap allocation call tree */\r\n", +" if ( heap_allocation_call_tree != NULL )\r\n", +" {\r\n", +" free( heap_allocation_call_tree );\r\n", +" }\r\n", +"\r\n", +" /* De-allocate intra-frame and inter-frame heap lists */\r\n", +" if ( list_wc_intra_frame_heap != NULL )\r\n", +" {\r\n", +" free( list_wc_intra_frame_heap );\r\n", +" }\r\n", +"\r\n", +" if ( list_current_inter_frame_heap != NULL )\r\n", +" {\r\n", +" free( list_current_inter_frame_heap );\r\n", +" }\r\n", +"\r\n", +" if ( list_wc_inter_frame_heap != NULL )\r\n", +" {\r\n", +" free( list_wc_inter_frame_heap );\r\n", +" }\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +" if ( fid_csv_filename != NULL )\r\n", +" {\r\n", +" fclose( fid_csv_filename );\r\n", +" }\r\n", +"#endif\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"#endif /* WMOPS */\r\n", +"\r\n", +"#ifndef WMOPS\r\n", +"int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */\r\n", +"#endif\r\n", +"\r\n", +"#ifdef WMOPS\r\n", +"/* Global counter for the calculation of BASOP complexity */\r\n", +"BASIC_OP *multiCounter = NULL;\r\n", +"int currCounter = 0;\r\n", +"int funcId_where_last_call_to_else_occurred;\r\n", +"long funcid_total_wmops_at_last_call_to_else;\r\n", +"int call_occurred = 1;\r\n", +"\r\n", +"BASIC_OP op_weight = {\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 2, 2, 1,\r\n", +" 1, 1, 1, 3, 1,\r\n", +"\r\n", +" 1, 1, 1, 3, 1,\r\n", +" 4, 1, 18, 1, 1,\r\n", +" 2, 1, 2, 2, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 3, 3, 3, 3, 1,\r\n", +"\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 1, 2,\r\n", +" 1, 2, 2, 4, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +"\r\n", +" 1, 1, 1, 1, 3,\r\n", +" 3, 3, 3, 3, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 1, 4, 4,\r\n", +" 4, 8, 3, 4, 4,\r\n", +"\r\n", +" 5, 32, 3\r\n", +"};\r\n", +"\r\n", +"/* Set the counter group to use, default is zero */\r\n", +"void Set_BASOP_WMOPS_counter( int counterId )\r\n", +"{\r\n", +" if ( ( counterId > num_wmops_records ) || ( counterId < 0 ) )\r\n", +" {\r\n", +" currCounter = 0;\r\n", +" return;\r\n", +" }\r\n", +" currCounter = counterId;\r\n", +" call_occurred = 1;\r\n", +"}\r\n", +"\r\n", +"extern int32_t frame;\r\n", +"\r\n", +"long TotalWeightedOperation()\r\n", +"{\r\n", +" int i;\r\n", +" unsigned int *ptr, *ptr2;\r\n", +" long tot; \r\n", +"\r\n", +" tot = 0;\r\n", +" ptr = (unsigned int *) &multiCounter[currCounter];\r\n", +" ptr2 = (unsigned int *) &op_weight;\r\n", +"\r\n", +" for ( i = 0; i < ( int )( sizeof( multiCounter[currCounter] ) / sizeof( unsigned int ) ); i++ )\r\n", +" {\r\n", +" tot += ( ( *ptr++ ) * ( *ptr2++ ) );\r\n", +" }\r\n", +"\r\n", +" return ( tot );\r\n", +"}\r\n", +"\r\n", +"long DeltaWeightedOperation( void )\r\n", +"{\r\n", +" long NewWOper, delta;\r\n", +"\r\n", +" NewWOper = TotalWeightedOperation();\r\n", +"\r\n", +" delta = NewWOper - wmops[currCounter].LastWOper;\r\n", +" wmops[currCounter].LastWOper = NewWOper;\r\n", +"\r\n", +" return ( delta );\r\n", +"}\r\n", +"\r\n", +"/* Resets the current BASOP WMOPS counter */\r\n", +"void Reset_BASOP_WMOPS_counter( void )\r\n", +"{\r\n", +" int i;\r\n", +" long *ptr;\r\n", +"\r\n", +" /* clear the current BASOP operation counter before new frame begins */\r\n", +" ptr = (long *) &multiCounter[currCounter];\r\n", +" for ( i = 0; i < (int) ( sizeof( multiCounter[currCounter] ) / sizeof( long ) ); i++ )\r\n", +" {\r\n", +" *ptr++ = 0;\r\n", +" }\r\n", +"\r\n", +" wmops[currCounter].LastWOper = 0;\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"\r\n", +"\r\n", \ No newline at end of file diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index e8d3c33..caed270 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -1,1448 +1,1448 @@ -"/*\r\n" -" * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved.\r\n" -" *\r\n" -" * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n" -" * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n" -" * or refer to ITU-T Recommendation G.191 on \"SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS\".\r\n" -" *\r\n" -" * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor\r\n" -" * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software\r\n" -" * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE.\r\n" -" *\r\n" -" * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca)\r\n" -" */\r\n" -"\r\n" -"#ifndef WMOPS_H\r\n" -"#define WMOPS_H\r\n" -"\r\n" -"#ifndef EXIT_FAILURE\r\n" -"#include /* stdlib is needed for exit() */\r\n" -"#endif\r\n" -"\r\n" -"#ifndef EOF\r\n" -"#include /* stdio is needed for fprintf() */\r\n" -"#endif\r\n" -"\r\n" -"\r\n" -"/* To Prevent \"warning: '$' in identifier or number\" message under GCC */\r\n" -"#ifdef __GNUC__\r\n" -"#pragma GCC system_header\r\n" -"#endif\r\n" -"\r\n" -"#ifndef INT_MAX\r\n" -"#define INT_MAX 32767\r\n" -"#endif\r\n" -"\r\n" -"#define FRAMES_PER_SECOND 50.0 \r\n" -"#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */\r\n" -"\r\n" -"#ifdef WMOPS\r\n" -"enum instructions\r\n" -"{\r\n" -" _ADD,\r\n" -" _ABS,\r\n" -" _MULT,\r\n" -" _MAC,\r\n" -" _MOVE,\r\n" -" _STORE,\r\n" -" _LOGIC,\r\n" -" _SHIFT,\r\n" -" _BRANCH,\r\n" -" _DIV,\r\n" -" _SQRT,\r\n" -" _TRANS,\r\n" -" _FUNC,\r\n" -" _LOOP,\r\n" -" _INDIRECT,\r\n" -" _PTR_INIT,\r\n" -" _TEST,\r\n" -" _POWER,\r\n" -" _LOG,\r\n" -" _MISC,\r\n" -" NUM_INST\r\n" -"};\r\n" -"\r\n" -"#define _ADD_C 1\r\n" -"#define _ABS_C 1\r\n" -"#define _MULT_C 1\r\n" -"#define _MAC_C 1\r\n" -"#define _MOVE_C 1\r\n" -"#define _STORE_C 1\r\n" -"#define _LOGIC_C 1\r\n" -"#define _SHIFT_C 1\r\n" -"#define _BRANCH_C 4\r\n" -"#define _DIV_C 18\r\n" -"#define _SQRT_C 10\r\n" -"#define _TRANS_C 25\r\n" -"#define _FUNC_C 2 /* need to add number of arguments */\r\n" -"#define _LOOP_C 3\r\n" -"#define _INDIRECT_C 2\r\n" -"#define _PTR_INIT_C 1\r\n" -"#define _TEST_C 2\r\n" -"#define _POWER_C 25\r\n" -"#define _LOG_C 25\r\n" -"#define _MISC_C 1\r\n" -"\r\n" -"#define _ADD_P 1\r\n" -"#define _ABS_P 1\r\n" -"#define _MULT_P 1\r\n" -"#define _MAC_P 1\r\n" -"#define _MOVE_P 1\r\n" -"#define _STORE_P 0\r\n" -"#define _LOGIC_P 1\r\n" -"#define _SHIFT_P 1\r\n" -"#define _BRANCH_P 2\r\n" -"#define _DIV_P 2\r\n" -"#define _SQRT_P 2\r\n" -"#define _TRANS_P 2\r\n" -"#define _FUNC_P 2 /* need to add number of arguments */\r\n" -"#define _LOOP_P 1\r\n" -"#define _INDIRECT_P 2\r\n" -"#define _PTR_INIT_P 1\r\n" -"#define _TEST_P 1\r\n" -"#define _POWER_P 2\r\n" -"#define _LOG_P 2\r\n" -"#define _MISC_P 1\r\n" -"\r\n" -"#define ADD( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _ADD_C * ( x ) ); \\\r\n" -" inst_cnt[_ADD] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _ADD_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define ABS( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _ABS_C * ( x ) ); \\\r\n" -" inst_cnt[_ABS] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _ABS_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define MULT( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _MULT_C * ( x ) ); \\\r\n" -" inst_cnt[_MULT] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _MULT_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define MAC( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _MAC_C * ( x ) ); \\\r\n" -" inst_cnt[_MAC] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _MAC_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define MOVE( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _MOVE_C * ( x ) ); \\\r\n" -" inst_cnt[_MOVE] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _MOVE_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define STORE( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _STORE_C * ( x ) ); \\\r\n" -" inst_cnt[_STORE] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _STORE_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define LOGIC( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _LOGIC_C * ( x ) ); \\\r\n" -" inst_cnt[_LOGIC] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _LOGIC_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define SHIFT( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _SHIFT_C * ( x ) ); \\\r\n" -" inst_cnt[_SHIFT] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _SHIFT_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define BRANCH( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _BRANCH_C * ( x ) ); \\\r\n" -" inst_cnt[_BRANCH] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _BRANCH_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define DIV( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _DIV_C * ( x ) ); \\\r\n" -" inst_cnt[_DIV] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _DIV_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define SQRT( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _SQRT_C * ( x ) ); \\\r\n" -" inst_cnt[_SQRT] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _SQRT_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define TRANS( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _TRANS_C * ( x ) ); \\\r\n" -" inst_cnt[_TRANS] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _TRANS_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define LOOP( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _LOOP_C * ( x ) ); \\\r\n" -" inst_cnt[_LOOP] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _LOOP_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define INDIRECT( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _INDIRECT_C * ( x ) ); \\\r\n" -" inst_cnt[_INDIRECT] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _INDIRECT_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define PTR_INIT( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _PTR_INIT_C * ( x ) ); \\\r\n" -" inst_cnt[_PTR_INIT] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _PTR_INIT_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define TEST( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _TEST_C * ( x ) ); \\\r\n" -" inst_cnt[_TEST] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _TEST_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define POWER( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _POWER_C * ( x ) ); \\\r\n" -" inst_cnt[_POWER] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _POWER_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define LOG( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _LOG_C * ( x ) ); \\\r\n" -" inst_cnt[_LOG] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _LOG_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define MISC( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _MISC_C * ( x ) ); \\\r\n" -" inst_cnt[_MISC] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _MISC_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"\r\n" -"#define FUNC( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( _FUNC_C + _MOVE_C * ( x ) ); \\\r\n" -" inst_cnt[_FUNC]++; \\\r\n" -" inst_cnt[_MOVE] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _FUNC_P + _MOVE_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"\r\n" -"#define DADD( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _ADD_C * ( x ) ); \\\r\n" -" inst_cnt[_ADD] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _ADD_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define DMULT( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _MULT_C * ( x ) ); \\\r\n" -" inst_cnt[_MULT] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _MULT_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define DMAC( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _MAC_C * ( x ) ); \\\r\n" -" inst_cnt[_MAC] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _MAC_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define DMOVE( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _MOVE_C * ( x ) ); \\\r\n" -" inst_cnt[_MOVE] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _MOVE_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define DSTORE( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _STORE_C * ( x ) ); \\\r\n" -" inst_cnt[_STORE] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _STORE_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define DLOGIC( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _LOGIC_C * ( x ) ); \\\r\n" -" inst_cnt[_LOGIC] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _LOGIC_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define DSHIFT( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _SHIFT_C * ( x ) ); \\\r\n" -" inst_cnt[_SHIFT] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _SHIFT_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define DDIV( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _DIV_C * ( x ) ); \\\r\n" -" inst_cnt[_DIV] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _DIV_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define DSQRT( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _SQRT_C * ( x ) ); \\\r\n" -" inst_cnt[_SQRT] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _SQRT_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"#define DTRANS( x ) \\\r\n" -" { \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _TRANS_C * ( x ) ); \\\r\n" -" inst_cnt[_TRANS] += ( x ); \\\r\n" -" { \\\r\n" -" static int pcnt; \\\r\n" -" if ( !pcnt ) \\\r\n" -" { \\\r\n" -" pcnt = 1; \\\r\n" -" prom_cnt += ( _TRANS_P * ( x ) ); \\\r\n" -" } \\\r\n" -" } \\\r\n" -" } \\\r\n" -" }\r\n" -"\r\n" -"extern double ops_cnt;\r\n" -"extern double prom_cnt;\r\n" -"extern double inst_cnt[NUM_INST];\r\n" -"\r\n" -"void reset_wmops( void );\r\n" -"void push_wmops( const char *label );\r\n" -"void pop_wmops( void );\r\n" -"void update_wmops( void );\r\n" -"void update_mem( void );\r\n" -"void print_wmops( void );\r\n" -"\r\n" -"#else /* WMOPS counting disabled */\r\n" -"\r\n" -"#define reset_wmops()\r\n" -"extern int cntr_push_pop;\r\n" -"#define push_wmops( x ) ( cntr_push_pop++ )\r\n" -"#define pop_wmops() ( cntr_push_pop-- )\r\n" -"#define update_wmops() ( assert( cntr_push_pop == 0 ) )\r\n" -"#define update_mem()\r\n" -"#define print_wmops()\r\n" -"\r\n" -"#define ADD( x )\r\n" -"#define ABS( x )\r\n" -"#define MULT( x )\r\n" -"#define MAC( x )\r\n" -"#define MOVE( x )\r\n" -"#define STORE( x )\r\n" -"#define LOGIC( x )\r\n" -"#define SHIFT( x )\r\n" -"#define BRANCH( x )\r\n" -"#define DIV( x )\r\n" -"#define SQRT( x )\r\n" -"#define TRANS( x )\r\n" -"#define FUNC( x )\r\n" -"#define LOOP( x )\r\n" -"#define INDIRECT( x )\r\n" -"#define PTR_INIT( x )\r\n" -"#define TEST( x )\r\n" -"#define POWER( x )\r\n" -"#define LOG( x )\r\n" -"#define MISC( x )\r\n" -"\r\n" -"#define DADD( x )\r\n" -"#define DMULT( x )\r\n" -"#define DMAC( x )\r\n" -"#define DMOVE( x )\r\n" -"#define DSTORE( x )\r\n" -"#define DLOGIC( x )\r\n" -"#define DSHIFT( x )\r\n" -"#define DDIV( x )\r\n" -"#define DSQRT( x )\r\n" -"#define DTRANS( x )\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"#ifndef WMOPS\r\n" -"/* DESACTIVATE the Counting Mechanism */\r\n" -"#define OP_COUNT_( op, n )\r\n" -"\r\n" -"/* DESACTIVATE Operation Counter Wrappers */\r\n" -"#define OP_COUNT_WRAPPER1_( op, val ) ( val )\r\n" -"#define OP_COUNT_WRAPPER2_( expr )\r\n" -"#define OP_COUNT_WRAPPER3_( op, expr ) expr\r\n" -"\r\n" -"/* DESACTIVATE Logical & Ternary Operators */\r\n" -"#define __\r\n" -"#define _\r\n" -"\r\n" -"#else\r\n" -"\r\n" -"/* '*ops_cnt_ptr' is Used to Avoid: \"warning: operation on 'ops_cnt' may be undefined\" with Cygwin gcc Compiler */\r\n" -"static double *ops_cnt_ptr = &ops_cnt;\r\n" -"#define OP_COUNT_( op, x ) ( *ops_cnt_ptr += ( op##_C * ( x ) ), inst_cnt[op] += ( x ) )\r\n" -"\r\n" -"/******************************************************************/\r\n" -"/* NOTES: */\r\n" -"/* The 'wmc_flag_' flag is global to avoid declaration in every */\r\n" -"/* function and 'static' to avoid clashing with other modules */\r\n" -"/* that include this header file. */\r\n" -"/* */\r\n" -"/* The declarations of 'wmc_flag_' and 'wops_' in this header */\r\n" -"/* file prevent the addition of a 'C' file to the Project. */\r\n" -"/******************************************************************/\r\n" -"\r\n" -"/* General Purpose Global Flag */\r\n" -"static int wmc_flag_ = 0;\r\n" -"\r\n" -"/* Operation Counter Wrappers */\r\n" -"#define OP_COUNT_WRAPPER1_( op, val ) ( op, val )\r\n" -"#define OP_COUNT_WRAPPER2_( expr ) \\\r\n" -" if ( expr, 0 ) \\\r\n" -" ; \\\r\n" -" else\r\n" -"#define OP_COUNT_WRAPPER3_( op, expr ) \\\r\n" -" if ( op, 0 ) \\\r\n" -" ; \\\r\n" -" else \\\r\n" -" expr\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"/* Define all Macros without '{' & '}' (None of these should be called externally!) */\r\n" -"#define ABS_( x ) OP_COUNT_( _ABS, ( x ) )\r\n" -"#define ADD_( x ) OP_COUNT_( _ADD, ( x ) )\r\n" -"#define MULT_( x ) OP_COUNT_( _MULT, ( x ) )\r\n" -"#define MAC_( x ) OP_COUNT_( _MAC, ( x ) )\r\n" -"#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) )\r\n" -"#define STORE_( x ) OP_COUNT_( _STORE, ( x ) )\r\n" -"#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) )\r\n" -"#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) )\r\n" -"#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) )\r\n" -"#define DIV_( x ) OP_COUNT_( _DIV, ( x ) )\r\n" -"#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) )\r\n" -"#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) )\r\n" -"#define POWER_( x ) TRANS_( x )\r\n" -"#define LOG_( x ) TRANS_( x )\r\n" -"#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) )\r\n" -"#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) )\r\n" -"#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) )\r\n" -"#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) )\r\n" -"#define MISC_( x ) ABS_( x )\r\n" -"\r\n" -"/* Math Operations */\r\n" -"#define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs )\r\n" -"#define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs )\r\n" -"#define fabsf_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabsf )\r\n" -"#define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs )\r\n" -"#define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor )\r\n" -"#define floorf_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floorf )\r\n" -"#define sqrt_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrt )\r\n" -"#define sqrtf_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf )\r\n" -"#define pow_ OP_COUNT_WRAPPER1_( POWER_( 1 ), pow )\r\n" -"#define powf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), powf )\r\n" -"#define exp_ OP_COUNT_WRAPPER1_( POWER_( 1 ), exp )\r\n" -"#define expf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), expf )\r\n" -"#define log_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log )\r\n" -"#define logf_ OP_COUNT_WRAPPER1_( LOG_( 1 ), logf )\r\n" -"#define log10_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10 )\r\n" -"#define log10f_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10f )\r\n" -"#define cos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cos )\r\n" -"#define cosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosf )\r\n" -"#define sin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sin )\r\n" -"#define sinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinf )\r\n" -"#define tan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tan )\r\n" -"#define tanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanf )\r\n" -"#define acos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acos )\r\n" -"#define acosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acosf )\r\n" -"#define asin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asin )\r\n" -"#define asinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asinf )\r\n" -"#define atan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan )\r\n" -"#define atanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atanf )\r\n" -"#define atan2_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2 )\r\n" -"#define atan2f_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2f )\r\n" -"#define cosh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosh )\r\n" -"#define coshf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), coshf )\r\n" -"#define sinh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinh )\r\n" -"#define sinhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinhf )\r\n" -"#define tanh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanh )\r\n" -"#define tanhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanhf )\r\n" -"#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod )\r\n" -"#define fmodf_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmodf )\r\n" -"#define frexp_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexp )\r\n" -"#define frexpf_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexpf )\r\n" -"\r\n" -"/* the macros below are instrumented versions of user-defined macros that might be used in the source code \r\n" -"/* representing some well-known and recognized mathematical operations (that are not defined in math.h) */\r\n" -"/* Note: the 'wmc_flag_=wmc_flag_' is used to avoid warning: left-hand operand of comma expression has no effect with gcc */\r\n" -"\r\n" -"#define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) )\r\n" -"#define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) )\r\n" -"#define MIN_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MIN( ( a ), ( b ) ) )\r\n" -"#define MAX_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MAX( ( a ), ( b ) ) )\r\n" -"#define Min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Min( ( a ), ( b ) ) )\r\n" -"#define Max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Max( ( a ), ( b ) ) )\r\n" -"#define sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), sqr( ( x ) ) )\r\n" -"#define Sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Sqr( ( x ) ) )\r\n" -"#define SQR_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQR( ( x ) ) )\r\n" -"#define square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), square( ( x ) ) )\r\n" -"#define Square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Square( ( x ) ) )\r\n" -"#define SQUARE_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQUARE( ( x ) ) )\r\n" -"#define sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), sign( ( x ) ) )\r\n" -"#define Sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), Sign( ( x ) ) )\r\n" -"#define SIGN_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), SIGN( ( x ) ) )\r\n" -"#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) )\r\n" -"#define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrtf( ( x ) ) )\r\n" -"#define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) )\r\n" -"#define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) )\r\n" -"#define log2f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2f( ( x ) ) )\r\n" -"#define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) )\r\n" -"#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) )\r\n" -"#define round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round( ( x ) ) )\r\n" -"#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) )\r\n" -"#define roundf_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, roundf( ( x ) ) )\r\n" -"#define set_min_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_min( ( a ), ( b ) ) )\r\n" -"#define set_max_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_max( ( a ), ( b ) ) )\r\n" -"\r\n" -"/* Functions */\r\n" -"#define func_( name, x ) OP_COUNT_WRAPPER1_( FUNC_( x ), name )\r\n" -"\r\n" -"/* Logical Operators */\r\n" -"#ifndef __\r\n" -"#define __ ( BRANCH_( 1 ), 1 ) &&\r\n" -"#endif\r\n" -"\r\n" -"/* Ternary Operators (? and :) */\r\n" -"#ifndef _\r\n" -"#define _ ( BRANCH_( 1 ), 0 ) ? 0:\r\n" -"#endif\r\n" -"\r\n" -"/* Flow Control keywords */\r\n" -"#define if_ \\\r\n" -" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n" -" if\r\n" -"#define for_ OP_COUNT_WRAPPER2_( LOOP_(1)) for\r\n" -"#define while_( c ) \\\r\n" -" while \\\r\n" -" OP_COUNT_WRAPPER1_( BRANCH_( 1 ), ( c ) ) /* needs extra \"()\" if ',' encountered */\r\n" -"#define do_ \\\r\n" -" do \\\r\n" -" {\r\n" -"#define _while \\\r\n" -" BRANCH_( 1 ); \\\r\n" -" } \\\r\n" -" while\r\n" -"\r\n" -"#define goto_ \\\r\n" -" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n" -" goto\r\n" -"#define break_ \\\r\n" -" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n" -" break\r\n" -"#define continue_ \\\r\n" -" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n" -" continue\r\n" -"#define return_ \\\r\n" -" OP_COUNT_WRAPPER2_( ( wmc_flag_ = stack_tree_level_, STACK_DEPTH_FCT_RETURN ) ) \\\r\n" -" return\r\n" -"\r\n" -"#define switch_ \\\r\n" -" OP_COUNT_WRAPPER2_( ( BRANCH_( 1 ), wmc_flag_ = 1 ) ) \\\r\n" -" switch\r\n" -"#define cost_( n ) OP_COUNT_WRAPPER2_( wmc_flag_ ? ( ADD_( n ), BRANCH_( n ), wmc_flag_ = 0 ) : 0 );\r\n" -"\r\n" -"#ifdef WMOPS\r\n" -"\r\n" -"#define ACC 2\r\n" -"#define MUL 1\r\n" -"\r\n" -"/* Counting Function (should not be called externally!) */\r\n" -"static void wops_( const char *ops )\r\n" -"{\r\n" -" char lm = 0; /* lm: Last Operation is Math */\r\n" -" static char lo = 0; /* Last Operation */\r\n" -"\r\n" -" void ( *fct )( const char *ops ) = wops_;\r\n" -"\r\n" -"st:\r\n" -" while ( *ops != '\\0' )\r\n" -" {\r\n" -" switch ( *ops++ )\r\n" -" {\r\n" -" int cnt;\r\n" -" case '-':\r\n" -" for ( cnt = 0; ops[cnt] == '>'; cnt++ )\r\n" -" ;\r\n" -" if ( cnt & 1 )\r\n" -" goto ind;\r\n" -" case '+':\r\n" -" lm = 2;\r\n" -" if ( lo & MUL )\r\n" -" {\r\n" -" MULT_( -1 );\r\n" -" MAC_( 1 );\r\n" -" break;\r\n" -" }\r\n" -" lo = ACC << 2;\r\n" -" case 'U':\r\n" -" case 'D':\r\n" -" ADD_( 1 );\r\n" -" break;\r\n" -" case '*':\r\n" -" lm = 2;\r\n" -" if ( lo & ACC )\r\n" -" {\r\n" -" ADD_( -1 );\r\n" -" MAC_( 1 );\r\n" -" break;\r\n" -" }\r\n" -" lo = MUL << 2;\r\n" -" MULT_( 1 );\r\n" -" break;\r\n" -" case '/':\r\n" -" case '%':\r\n" -" lm = 2;\r\n" -" DIV_( 1 );\r\n" -" break;\r\n" -" case '&':\r\n" -" case '|':\r\n" -" case '^':\r\n" -" lm = 2;\r\n" -" case '~':\r\n" -" LOGIC_( 1 );\r\n" -" break;\r\n" -" case '<':\r\n" -" case '>':\r\n" -" if ( *ops != ops[-1] )\r\n" -" goto error;\r\n" -" ops++;\r\n" -" case -85:\r\n" -" case -69:\r\n" -" lm = 2;\r\n" -" SHIFT_( 1 );\r\n" -" break;\r\n" -" case 'L':\r\n" -" case 'G':\r\n" -" if ( *ops == 't' )\r\n" -" goto comp;\r\n" -" case 'E':\r\n" -" case 'N':\r\n" -" if ( *ops != 'e' )\r\n" -" goto error;\r\n" -" comp:\r\n" -" ops++;\r\n" -" ADD_( 1 );\r\n" -" break;\r\n" -" case '!':\r\n" -" MISC_( 2 );\r\n" -" break;\r\n" -" case 'M':\r\n" -" MOVE_( 1 );\r\n" -" break;\r\n" -" case 'S':\r\n" -" STORE_( 1 );\r\n" -" break;\r\n" -" case 'P':\r\n" -" PTR_INIT_( 1 );\r\n" -" break;\r\n" -" case '[':\r\n" -" case ']':\r\n" -" goto st;\r\n" -" ind:\r\n" -" ops++;\r\n" -" case 'I':\r\n" -" case '.':\r\n" -" INDIRECT_( 1 );\r\n" -" break;\r\n" -" case '=':\r\n" -" if ( lm )\r\n" -" goto st;\r\n" -" case '\\0':\r\n" -" /* This Shouldn't Happen */\r\n" -" /* These are Used to Avoid: \"warning: 'name' defined but not used\" with Cygwin gcc Compiler */\r\n" -" wmc_flag_ = wmc_flag_;\r\n" -" ops_cnt_ptr = ops_cnt_ptr;\r\n" -" fct( \"\" );\r\n" -" error:\r\n" -" default:\r\n" -" fprintf( stderr, \"\\r wops: Invalid Counting Operation '%s'\\n\", ops - 1 );\r\n" -" exit( -1 );\r\n" -" }\r\n" -" lm >>= 1;\r\n" -" lo >>= 2;\r\n" -" }\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"/* All Other Operations */\r\n" -"#define $( str ) OP_COUNT_WRAPPER2_( wops_( str ) )\r\n" -"\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * Memory counting tool\r\n" -" *-------------------------------------------------------------------*/\r\n" -"\r\n" -"/* Enhanced Const Data Size Counting (Rounding Up to the Nearest 'Integer' Size) */\r\n" -"#define rsize( item ) ( ( sizeof( item ) + sizeof( int ) - 1 ) / sizeof( int ) * sizeof( int ) )\r\n" -"\r\n" -"#ifdef _MSC_VER\r\n" -"/* Disable \"warning C4210: nonstandard extension used : function given file scope\" with Visual Studio Compiler */\r\n" -"#pragma warning( disable : 4210 )\r\n" -"#endif\r\n" -"\r\n" -"/* Const Data Size and PROM Size Wrapper Functions */\r\n" -"#define Const_Data_Size_Func( file ) Const_Data_Size_##file( void )\r\n" -"#define Get_Const_Data_Size( file, val_ptr ) \\\r\n" -" { \\\r\n" -" extern int Const_Data_Size_##file( void ); \\\r\n" -" *( val_ptr ) = Const_Data_Size_##file(); \\\r\n" -" }\r\n" -"#define PROM_Size_Func( file ) PROM_Size_##file( void )\r\n" -"#define Get_PROM_Size( file, val_ptr ) \\\r\n" -" { \\\r\n" -" int PROM_Size_##file( void ); \\\r\n" -" *( val_ptr ) = PROM_Size_##file(); \\\r\n" -" }\r\n" -"\r\n" -"/* ROM Size Lookup Table - contains information about PROM size and Const Data Size in all source files */\r\n" -"/* The print_mem() function looks for this table to print the results of Const Data usage and PROM usage */\r\n" -"typedef struct ROM_Size_Lookup_Table\r\n" -"{\r\n" -" const char file_spec[255];\r\n" -" int PROM_size;\r\n" -" int ( *Get_Const_Data_Size_Func )( void );\r\n" -"} ROM_Size_Lookup_Table;\r\n" -"\r\n" -"/* The WMC tool inserts the following declaration during the innstrumentation process in the .c file where the function print_mem() is located */\r\n" -"/* and modifies it to print_mem(Const_Data_PROM_Table) */\r\n" -"\r\n" -"/* #ifdef WMOPS\r\n" -" * ROM_Size_Lookup_Table Const_Data_PROM_Table[] =\r\n" -" * {\r\n" -" * {\"../lib_enc/rom_enc.c\", 0, NULL},\r\n" -" * {\"../lib_com/*.c\", 0, NULL},\r\n" -" * {\"\", -1, NULL}\r\n" -" * };\r\n" -" * #endif\r\n" -" */\r\n" -"\r\n" -"/*#define MEM_ALIGN_64BITS */ /* Define this when using 64 Bits values in the code (ex: double), otherwise it will align on 32 Bits */\r\n" -"/*#define MEM_COUNT_DETAILS*/\r\n" -"\r\n" -"typedef enum\r\n" -"{\r\n" -" USE_BYTES = 0,\r\n" -" USE_16BITS = 1,\r\n" -" USE_32BITS = 2,\r\n" -" USE_64BITS = 3\r\n" -"} Counting_Size;\r\n" -"\r\n" -"#if ( defined( _WIN32 ) && ( _MSC_VER <= 1800 ) && ( _MSC_VER >= 1300 ) )\r\n" -"#define __func__ __FUNCTION__\r\n" -"#elif defined( __STDC_VERSION__ ) && __STDC_VERSION__ < 199901L\r\n" -"#if ( __GNUC__ >= 2 )\r\n" -"#define __func__ __FUNCTION__\r\n" -"#else\r\n" -"#define __func__ \"\"\r\n" -"#endif\r\n" -"#elif defined( __GNUC__ )\r\n" -"#define __func__ __extension__ __FUNCTION__\r\n" -"#endif\r\n" -"\r\n" -"\r\n" -"#ifdef WMOPS\r\n" -"\r\n" -"void *mem_alloc( const char *func_name, int func_lineno, size_t size, char *alloc_str );\r\n" -"void mem_free( const char *func_name, int func_lineno, void *ptr );\r\n" -"\r\n" -"#define malloc_( size ) mem_alloc( __func__, __LINE__, size, \"m:\" #size )\r\n" -"#define calloc_( n, size ) mem_alloc( __func__, __LINE__, ( n ) * ( size ), \"c:\" #n \", \" #size )\r\n" -"#define free_( ptr ) mem_free( __func__, __LINE__, ptr )\r\n" -"\r\n" -"void reset_mem( Counting_Size cnt_size );\r\n" -"void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] );\r\n" -"\r\n" -"int push_stack( const char *filename, const char *fctname );\r\n" -"int pop_stack( const char *filename, const char *fctname );\r\n" -"\r\n" -"#ifdef WMOPS_DETAIL\r\n" -"#define STACK_DEPTH_FCT_CALL ( push_wmops( __FUNCTION__ \" [WMC_AUTO]\" ), push_stack( __FILE__, __FUNCTION__ ) ) /* add push_wmops() in all function calls */\r\n" -"#define STACK_DEPTH_FCT_RETURN ( pop_wmops(), pop_stack( __FILE__, __FUNCTION__ ) ) /* add pop_wmops() in all function returns */\r\n" -"#else\r\n" -"#define STACK_DEPTH_FCT_CALL push_stack( __FILE__, __FUNCTION__ )\r\n" -"#define STACK_DEPTH_FCT_RETURN pop_stack( __FILE__, __FUNCTION__ )\r\n" -"#endif\r\n" -"\r\n" -"void reset_stack( void );\r\n" -"#define func_start_ int stack_tree_level_ = STACK_DEPTH_FCT_CALL;\r\n" -"\r\n" -"#else\r\n" -"#define malloc_( n1 ) malloc( n1 )\r\n" -"#define calloc_( n1, n2 ) calloc( n1, n2 )\r\n" -"#define free_( ptr ) free( ptr )\r\n" -"#define reset_mem( cnt_size )\r\n" -"#define print_mem( Const_Data_PROM_Table )\r\n" -"\r\n" -"#define push_stack( file, fct )\r\n" -"#define pop_stack( file, fct )\r\n" -"#define reset_stack()\r\n" -"#define func_start_\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"\r\n" -"/* Global counter variable for calculation of complexity weight */\r\n" -"typedef struct\r\n" -"{\r\n" -" unsigned int add; /* Complexity Weight of 1 */\r\n" -" unsigned int sub; /* Complexity Weight of 1 */\r\n" -" unsigned int abs_s; /* Complexity Weight of 1 */\r\n" -" unsigned int shl; /* Complexity Weight of 1 */\r\n" -" unsigned int shr; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int extract_h; /* Complexity Weight of 1 */\r\n" -" unsigned int extract_l; /* Complexity Weight of 1 */\r\n" -" unsigned int mult; /* Complexity Weight of 1 */\r\n" -" unsigned int L_mult; /* Complexity Weight of 1 */\r\n" -" unsigned int negate; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int round; /* Complexity Weight of 1 */\r\n" -" unsigned int L_mac; /* Complexity Weight of 1 */\r\n" -" unsigned int L_msu; /* Complexity Weight of 1 */\r\n" -" unsigned int L_macNs; /* Complexity Weight of 1 */\r\n" -" unsigned int L_msuNs; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L_add; /* Complexity Weight of 1 */\r\n" -" unsigned int L_sub; /* Complexity Weight of 1 */\r\n" -" unsigned int L_add_c; /* Complexity Weight of 2 */\r\n" -" unsigned int L_sub_c; /* Complexity Weight of 2 */\r\n" -" unsigned int L_negate; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L_shl; /* Complexity Weight of 1 */\r\n" -" unsigned int L_shr; /* Complexity Weight of 1 */\r\n" -" unsigned int mult_r; /* Complexity Weight of 1 */\r\n" -" unsigned int shr_r; /* Complexity Weight of 3 */\r\n" -" unsigned int mac_r; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int msu_r; /* Complexity Weight of 1 */\r\n" -" unsigned int L_deposit_h; /* Complexity Weight of 1 */\r\n" -" unsigned int L_deposit_l; /* Complexity Weight of 1 */\r\n" -" unsigned int L_shr_r; /* Complexity Weight of 3 */\r\n" -" unsigned int L_abs; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L_sat; /* Complexity Weight of 4 */\r\n" -" unsigned int norm_s; /* Complexity Weight of 1 */\r\n" -" unsigned int div_s; /* Complexity Weight of 18 */\r\n" -" unsigned int norm_l; /* Complexity Weight of 1 */\r\n" -" unsigned int move16; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int move32; /* Complexity Weight of 2 */\r\n" -" unsigned int Logic16; /* Complexity Weight of 1 */\r\n" -" unsigned int Logic32; /* Complexity Weight of 2 */\r\n" -" unsigned int Test; /* Complexity Weight of 2 */\r\n" -" unsigned int s_max; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int s_min; /* Complexity Weight of 1 */\r\n" -" unsigned int L_max; /* Complexity Weight of 1 */\r\n" -" unsigned int L_min; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_max; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_min; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int shl_r; /* Complexity Weight of 3 */\r\n" -" unsigned int L_shl_r; /* Complexity Weight of 3 */\r\n" -" unsigned int L40_shr_r; /* Complexity Weight of 3 */\r\n" -" unsigned int L40_shl_r; /* Complexity Weight of 3 */\r\n" -" unsigned int norm_L40; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L40_shl; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_shr; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_negate; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_add; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_sub; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L40_abs; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_mult; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_mac; /* Complexity Weight of 1 */\r\n" -" unsigned int mac_r40; /* Complexity Weight of 2 */\r\n" -"\r\n" -" unsigned int L40_msu; /* Complexity Weight of 1 */\r\n" -" unsigned int msu_r40; /* Complexity Weight of 2 */\r\n" -" unsigned int Mpy_32_16_ss; /* Complexity Weight of 2 */\r\n" -" unsigned int Mpy_32_32_ss; /* Complexity Weight of 4 */\r\n" -" unsigned int L_mult0; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L_mac0; /* Complexity Weight of 1 */\r\n" -" unsigned int L_msu0; /* Complexity Weight of 1 */\r\n" -" unsigned int lshl; /* Complexity Weight of 1 */\r\n" -" unsigned int lshr; /* Complexity Weight of 1 */\r\n" -" unsigned int L_lshl; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L_lshr; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_lshl; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_lshr; /* Complexity Weight of 1 */\r\n" -" unsigned int s_and; /* Complexity Weight of 1 */\r\n" -" unsigned int s_or; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int s_xor; /* Complexity Weight of 1 */\r\n" -" unsigned int L_and; /* Complexity Weight of 1 */\r\n" -" unsigned int L_or; /* Complexity Weight of 1 */\r\n" -" unsigned int L_xor; /* Complexity Weight of 1 */\r\n" -" unsigned int rotl; /* Complexity Weight of 3 */\r\n" -"\r\n" -" unsigned int rotr; /* Complexity Weight of 3 */\r\n" -" unsigned int L_rotl; /* Complexity Weight of 3 */\r\n" -" unsigned int L_rotr; /* Complexity Weight of 3 */\r\n" -" unsigned int L40_set; /* Complexity Weight of 3 */\r\n" -" unsigned int L40_deposit_h; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L40_deposit_l; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_deposit32; /* Complexity Weight of 1 */\r\n" -" unsigned int Extract40_H; /* Complexity Weight of 1 */\r\n" -" unsigned int Extract40_L; /* Complexity Weight of 1 */\r\n" -" unsigned int L_Extract40; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L40_round; /* Complexity Weight of 1 */\r\n" -" unsigned int L_saturate40; /* Complexity Weight of 1 */\r\n" -" unsigned int round40; /* Complexity Weight of 1 */\r\n" -" unsigned int If; /* Complexity Weight of 4 */\r\n" -" unsigned int Goto; /* Complexity Weight of 4 */\r\n" -"\r\n" -" unsigned int Break; /* Complexity Weight of 4 */\r\n" -" unsigned int Switch; /* Complexity Weight of 8 */\r\n" -" unsigned int For; /* Complexity Weight of 3 */\r\n" -" unsigned int While; /* Complexity Weight of 4 */\r\n" -" unsigned int Continue; /* Complexity Weight of 4 */\r\n" -"\r\n" -" unsigned int L_mls; /* Complexity Weight of 6 */\r\n" -" unsigned int div_l; /* Complexity Weight of 32 */\r\n" -" unsigned int i_mult; /* Complexity Weight of 3 */\r\n" -"} BASIC_OP;\r\n" -"\r\n" -"#ifdef WMOPS\r\n" -"extern BASIC_OP *multiCounter;\r\n" -"extern int currCounter;\r\n" -"\r\n" -"/* Technical note :\r\n" -" * The following 3 variables are only used for correct complexity\r\n" -" * evaluation of the following structure :\r\n" -" * IF{\r\n" -" * ...\r\n" -" * } ELSE IF {\r\n" -" * ...\r\n" -" * } ELSE IF {\r\n" -" * ...\r\n" -" * }\r\n" -" * ...\r\n" -" * } ELSE {\r\n" -" * ...\r\n" -" * }\r\n" -" */\r\n" -"extern int funcId_where_last_call_to_else_occurred;\r\n" -"extern long funcid_total_wmops_at_last_call_to_else;\r\n" -"extern int call_occurred;\r\n" -"\r\n" -"extern long TotalWeightedOperation( void );\r\n" -"long DeltaWeightedOperation( void );\r\n" -"\r\n" -"void Set_BASOP_WMOPS_counter( int counterId );\r\n" -"void Reset_BASOP_WMOPS_counter( void );\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : FOR\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro FOR should be used instead of the 'for' C statement.\r\n" -" * The complexity is independent of the number of loop iterations that are\r\n" -" * performed.\r\n" -" *\r\n" -" * Complexity weight : 3 (regardless of number of iterations).\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define FOR( a) for( a)\r\n" -"\r\n" -"#else \r\n" -"#define FOR( a) if( incrFor(), 0); else for( a)\r\n" -"\r\n" -"static __inline void incrFor( void) {\r\n" -" multiCounter[currCounter].For++;\r\n" -"}\r\n" -"#endif \r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : WHILE\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro WHILE should be used instead of the 'while' C statement.\r\n" -" * The complexity is proportional to the number of loop iterations that\r\n" -" * are performed.\r\n" -" *\r\n" -" * Complexity weight : 4 x 'number of loop iterations'.\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define WHILE( a) while( a)\r\n" -"\r\n" -"#else \r\n" -"#define WHILE( a) while( incrWhile(), a)\r\n" -"\r\n" -"static __inline void incrWhile( void) {\r\n" -" multiCounter[currCounter].While++;\r\n" -"}\r\n" -"#endif \r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : DO\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro DO should be used instead of the 'do' C statement.\r\n" -" *\r\n" -" * Complexity weight : 0 (complexity counted by WHILE macro).\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define DO do\r\n" -"\r\n" -"#else \r\n" -"#define DO do\r\n" -"\r\n" -"#endif \r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : IF\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro IF should :\r\n" -" *\r\n" -" * - not be used when :\r\n" -" * - the 'if' structure does not have any 'else if' nor 'else' statement\r\n" -" * - and it conditions only one DSP basic operations.\r\n" -" *\r\n" -" * - be used instead of the 'if' C statement in every other case :\r\n" -" * - when there is an 'else' or 'else if' statement,\r\n" -" * - or when the 'if' conditions several DSP basic operations,\r\n" -" * - or when the 'if' conditions a function call.\r\n" -" *\r\n" -" * Complexity weight : 4\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define IF( a) if( a)\r\n" -"\r\n" -"#else \r\n" -"#define IF( a) if( incrIf(), a)\r\n" -"\r\n" -"static __inline void incrIf( void) {\r\n" -" /* Technical note :\r\n" -" * If the \"IF\" operator comes just after an \"ELSE\", its counter\r\n" -" * must not be incremented.\r\n" -" */\r\n" -" if ( ( currCounter != funcId_where_last_call_to_else_occurred ) || ( TotalWeightedOperation() != funcid_total_wmops_at_last_call_to_else ) || ( call_occurred == 1 ) )\r\n" -" {\r\n" -" multiCounter[currCounter].If++;\r\n" -" }\r\n" -"\r\n" -" call_occurred = 0;\r\n" -" funcId_where_last_call_to_else_occurred = INT_MAX;\r\n" -"}\r\n" -"#endif \r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : ELSE\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro ELSE should be used instead of the 'else' C statement.\r\n" -" *\r\n" -" * Complexity weight : 4\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define ELSE else\r\n" -"\r\n" -"#else \r\n" -"#define ELSE else if( incrElse(), 0) ; else\r\n" -"\r\n" -"static __inline void incrElse( void) {\r\n" -" multiCounter[currCounter].If++;\r\n" -"\r\n" -" /* We keep track of the funcId of the last function\r\n" -" * which used ELSE {...} structure.\r\n" -" */\r\n" -" funcId_where_last_call_to_else_occurred = currCounter;\r\n" -"\r\n" -" /* We keep track of the number of WMOPS of this funcId\r\n" -" * when the ELSE macro was called.\r\n" -" */\r\n" -" funcid_total_wmops_at_last_call_to_else = TotalWeightedOperation();\r\n" -"\r\n" -" /* call_occurred is set to 0, in order to count the next IF (if necessary)\r\n" -" */\r\n" -" call_occurred = 0;\r\n" -"}\r\n" -"#endif \r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : SWITCH\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro SWITCH should be used instead of the 'switch' C statement.\r\n" -" *\r\n" -" * Complexity weight : 8\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define SWITCH( a) switch( a)\r\n" -"\r\n" -"#else \r\n" -"#define SWITCH( a) switch( incrSwitch(), a)\r\n" -"\r\n" -"static __inline void incrSwitch( void) {\r\n" -" multiCounter[currCounter].Switch++;\r\n" -"}\r\n" -"#endif \r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : CONTINUE\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro CONTINUE should be used instead of the 'continue' C statement.\r\n" -" *\r\n" -" * Complexity weight : 4\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define CONTINUE continue\r\n" -"\r\n" -"#else \r\n" -"#define CONTINUE if( incrContinue(), 0); else continue\r\n" -"\r\n" -"static __inline void incrContinue( void) {\r\n" -" multiCounter[currCounter].Continue++;\r\n" -"}\r\n" -"#endif \r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : BREAK\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro BREAK should be used instead of the 'break' C statement.\r\n" -" *\r\n" -" * Complexity weight : 4\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define BREAK break\r\n" -"\r\n" -"#else \r\n" -"#define BREAK if( incrBreak(), 0) break; else break\r\n" -"\r\n" -"static __inline void incrBreak( void) {\r\n" -" multiCounter[currCounter].Break++;\r\n" -"}\r\n" -"#endif \r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : GOTO\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro GOTO should be used instead of the 'goto' C statement.\r\n" -" *\r\n" -" * Complexity weight : 4\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define GOTO goto\r\n" -"\r\n" -"#else \r\n" -"#define GOTO if( incrGoto(), 0); else goto\r\n" -"\r\n" -"static __inline void incrGoto( void) {\r\n" -" multiCounter[currCounter].Goto++;\r\n" -"}\r\n" -"#endif \r\n" -"\r\n" -"#endif /* WMOPS_H */\r\n" -"\r\n" -"\r\n" -"\r\n" \ No newline at end of file +"/*\r\n", +" * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved.\r\n", +" *\r\n", +" * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n", +" * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n", +" * or refer to ITU-T Recommendation G.191 on \"SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS\".\r\n", +" *\r\n", +" * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor\r\n", +" * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software\r\n", +" * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE.\r\n", +" *\r\n", +" * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca)\r\n", +" */\r\n", +"\r\n", +"#ifndef WMOPS_H\r\n", +"#define WMOPS_H\r\n", +"\r\n", +"#ifndef EXIT_FAILURE\r\n", +"#include /* stdlib is needed for exit() */\r\n", +"#endif\r\n", +"\r\n", +"#ifndef EOF\r\n", +"#include /* stdio is needed for fprintf() */\r\n", +"#endif\r\n", +"\r\n", +"\r\n", +"/* To Prevent \"warning: '$' in identifier or number\" message under GCC */\r\n", +"#ifdef __GNUC__\r\n", +"#pragma GCC system_header\r\n", +"#endif\r\n", +"\r\n", +"#ifndef INT_MAX\r\n", +"#define INT_MAX 32767\r\n", +"#endif\r\n", +"\r\n", +"#define FRAMES_PER_SECOND 50.0 \r\n", +"#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */\r\n", +"\r\n", +"#ifdef WMOPS\r\n", +"enum instructions\r\n", +"{\r\n", +" _ADD,\r\n", +" _ABS,\r\n", +" _MULT,\r\n", +" _MAC,\r\n", +" _MOVE,\r\n", +" _STORE,\r\n", +" _LOGIC,\r\n", +" _SHIFT,\r\n", +" _BRANCH,\r\n", +" _DIV,\r\n", +" _SQRT,\r\n", +" _TRANS,\r\n", +" _FUNC,\r\n", +" _LOOP,\r\n", +" _INDIRECT,\r\n", +" _PTR_INIT,\r\n", +" _TEST,\r\n", +" _POWER,\r\n", +" _LOG,\r\n", +" _MISC,\r\n", +" NUM_INST\r\n", +"};\r\n", +"\r\n", +"#define _ADD_C 1\r\n", +"#define _ABS_C 1\r\n", +"#define _MULT_C 1\r\n", +"#define _MAC_C 1\r\n", +"#define _MOVE_C 1\r\n", +"#define _STORE_C 1\r\n", +"#define _LOGIC_C 1\r\n", +"#define _SHIFT_C 1\r\n", +"#define _BRANCH_C 4\r\n", +"#define _DIV_C 18\r\n", +"#define _SQRT_C 10\r\n", +"#define _TRANS_C 25\r\n", +"#define _FUNC_C 2 /* need to add number of arguments */\r\n", +"#define _LOOP_C 3\r\n", +"#define _INDIRECT_C 2\r\n", +"#define _PTR_INIT_C 1\r\n", +"#define _TEST_C 2\r\n", +"#define _POWER_C 25\r\n", +"#define _LOG_C 25\r\n", +"#define _MISC_C 1\r\n", +"\r\n", +"#define _ADD_P 1\r\n", +"#define _ABS_P 1\r\n", +"#define _MULT_P 1\r\n", +"#define _MAC_P 1\r\n", +"#define _MOVE_P 1\r\n", +"#define _STORE_P 0\r\n", +"#define _LOGIC_P 1\r\n", +"#define _SHIFT_P 1\r\n", +"#define _BRANCH_P 2\r\n", +"#define _DIV_P 2\r\n", +"#define _SQRT_P 2\r\n", +"#define _TRANS_P 2\r\n", +"#define _FUNC_P 2 /* need to add number of arguments */\r\n", +"#define _LOOP_P 1\r\n", +"#define _INDIRECT_P 2\r\n", +"#define _PTR_INIT_P 1\r\n", +"#define _TEST_P 1\r\n", +"#define _POWER_P 2\r\n", +"#define _LOG_P 2\r\n", +"#define _MISC_P 1\r\n", +"\r\n", +"#define ADD( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _ADD_C * ( x ) ); \\\r\n", +" inst_cnt[_ADD] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _ADD_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define ABS( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _ABS_C * ( x ) ); \\\r\n", +" inst_cnt[_ABS] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _ABS_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define MULT( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _MULT_C * ( x ) ); \\\r\n", +" inst_cnt[_MULT] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _MULT_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define MAC( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _MAC_C * ( x ) ); \\\r\n", +" inst_cnt[_MAC] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _MAC_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define MOVE( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _MOVE_C * ( x ) ); \\\r\n", +" inst_cnt[_MOVE] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _MOVE_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define STORE( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _STORE_C * ( x ) ); \\\r\n", +" inst_cnt[_STORE] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _STORE_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define LOGIC( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _LOGIC_C * ( x ) ); \\\r\n", +" inst_cnt[_LOGIC] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _LOGIC_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define SHIFT( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _SHIFT_C * ( x ) ); \\\r\n", +" inst_cnt[_SHIFT] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _SHIFT_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define BRANCH( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _BRANCH_C * ( x ) ); \\\r\n", +" inst_cnt[_BRANCH] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _BRANCH_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define DIV( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _DIV_C * ( x ) ); \\\r\n", +" inst_cnt[_DIV] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _DIV_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define SQRT( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _SQRT_C * ( x ) ); \\\r\n", +" inst_cnt[_SQRT] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _SQRT_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define TRANS( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _TRANS_C * ( x ) ); \\\r\n", +" inst_cnt[_TRANS] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _TRANS_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define LOOP( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _LOOP_C * ( x ) ); \\\r\n", +" inst_cnt[_LOOP] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _LOOP_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define INDIRECT( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _INDIRECT_C * ( x ) ); \\\r\n", +" inst_cnt[_INDIRECT] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _INDIRECT_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define PTR_INIT( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _PTR_INIT_C * ( x ) ); \\\r\n", +" inst_cnt[_PTR_INIT] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _PTR_INIT_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define TEST( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _TEST_C * ( x ) ); \\\r\n", +" inst_cnt[_TEST] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _TEST_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define POWER( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _POWER_C * ( x ) ); \\\r\n", +" inst_cnt[_POWER] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _POWER_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define LOG( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _LOG_C * ( x ) ); \\\r\n", +" inst_cnt[_LOG] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _LOG_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define MISC( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _MISC_C * ( x ) ); \\\r\n", +" inst_cnt[_MISC] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _MISC_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"\r\n", +"#define FUNC( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( _FUNC_C + _MOVE_C * ( x ) ); \\\r\n", +" inst_cnt[_FUNC]++; \\\r\n", +" inst_cnt[_MOVE] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _FUNC_P + _MOVE_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"\r\n", +"#define DADD( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _ADD_C * ( x ) ); \\\r\n", +" inst_cnt[_ADD] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _ADD_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define DMULT( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _MULT_C * ( x ) ); \\\r\n", +" inst_cnt[_MULT] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _MULT_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define DMAC( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _MAC_C * ( x ) ); \\\r\n", +" inst_cnt[_MAC] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _MAC_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define DMOVE( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _MOVE_C * ( x ) ); \\\r\n", +" inst_cnt[_MOVE] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _MOVE_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define DSTORE( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _STORE_C * ( x ) ); \\\r\n", +" inst_cnt[_STORE] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _STORE_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define DLOGIC( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _LOGIC_C * ( x ) ); \\\r\n", +" inst_cnt[_LOGIC] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _LOGIC_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define DSHIFT( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _SHIFT_C * ( x ) ); \\\r\n", +" inst_cnt[_SHIFT] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _SHIFT_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define DDIV( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _DIV_C * ( x ) ); \\\r\n", +" inst_cnt[_DIV] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _DIV_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define DSQRT( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _SQRT_C * ( x ) ); \\\r\n", +" inst_cnt[_SQRT] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _SQRT_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"#define DTRANS( x ) \\\r\n", +" { \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _TRANS_C * ( x ) ); \\\r\n", +" inst_cnt[_TRANS] += ( x ); \\\r\n", +" { \\\r\n", +" static int pcnt; \\\r\n", +" if ( !pcnt ) \\\r\n", +" { \\\r\n", +" pcnt = 1; \\\r\n", +" prom_cnt += ( _TRANS_P * ( x ) ); \\\r\n", +" } \\\r\n", +" } \\\r\n", +" } \\\r\n", +" }\r\n", +"\r\n", +"extern double ops_cnt;\r\n", +"extern double prom_cnt;\r\n", +"extern double inst_cnt[NUM_INST];\r\n", +"\r\n", +"void reset_wmops( void );\r\n", +"void push_wmops( const char *label );\r\n", +"void pop_wmops( void );\r\n", +"void update_wmops( void );\r\n", +"void update_mem( void );\r\n", +"void print_wmops( void );\r\n", +"\r\n", +"#else /* WMOPS counting disabled */\r\n", +"\r\n", +"#define reset_wmops()\r\n", +"extern int cntr_push_pop;\r\n", +"#define push_wmops( x ) ( cntr_push_pop++ )\r\n", +"#define pop_wmops() ( cntr_push_pop-- )\r\n", +"#define update_wmops() ( assert( cntr_push_pop == 0 ) )\r\n", +"#define update_mem()\r\n", +"#define print_wmops()\r\n", +"\r\n", +"#define ADD( x )\r\n", +"#define ABS( x )\r\n", +"#define MULT( x )\r\n", +"#define MAC( x )\r\n", +"#define MOVE( x )\r\n", +"#define STORE( x )\r\n", +"#define LOGIC( x )\r\n", +"#define SHIFT( x )\r\n", +"#define BRANCH( x )\r\n", +"#define DIV( x )\r\n", +"#define SQRT( x )\r\n", +"#define TRANS( x )\r\n", +"#define FUNC( x )\r\n", +"#define LOOP( x )\r\n", +"#define INDIRECT( x )\r\n", +"#define PTR_INIT( x )\r\n", +"#define TEST( x )\r\n", +"#define POWER( x )\r\n", +"#define LOG( x )\r\n", +"#define MISC( x )\r\n", +"\r\n", +"#define DADD( x )\r\n", +"#define DMULT( x )\r\n", +"#define DMAC( x )\r\n", +"#define DMOVE( x )\r\n", +"#define DSTORE( x )\r\n", +"#define DLOGIC( x )\r\n", +"#define DSHIFT( x )\r\n", +"#define DDIV( x )\r\n", +"#define DSQRT( x )\r\n", +"#define DTRANS( x )\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"#ifndef WMOPS\r\n", +"/* DESACTIVATE the Counting Mechanism */\r\n", +"#define OP_COUNT_( op, n )\r\n", +"\r\n", +"/* DESACTIVATE Operation Counter Wrappers */\r\n", +"#define OP_COUNT_WRAPPER1_( op, val ) ( val )\r\n", +"#define OP_COUNT_WRAPPER2_( expr )\r\n", +"#define OP_COUNT_WRAPPER3_( op, expr ) expr\r\n", +"\r\n", +"/* DESACTIVATE Logical & Ternary Operators */\r\n", +"#define __\r\n", +"#define _\r\n", +"\r\n", +"#else\r\n", +"\r\n", +"/* '*ops_cnt_ptr' is Used to Avoid: \"warning: operation on 'ops_cnt' may be undefined\" with Cygwin gcc Compiler */\r\n", +"static double *ops_cnt_ptr = &ops_cnt;\r\n", +"#define OP_COUNT_( op, x ) ( *ops_cnt_ptr += ( op##_C * ( x ) ), inst_cnt[op] += ( x ) )\r\n", +"\r\n", +"/******************************************************************/\r\n", +"/* NOTES: */\r\n", +"/* The 'wmc_flag_' flag is global to avoid declaration in every */\r\n", +"/* function and 'static' to avoid clashing with other modules */\r\n", +"/* that include this header file. */\r\n", +"/* */\r\n", +"/* The declarations of 'wmc_flag_' and 'wops_' in this header */\r\n", +"/* file prevent the addition of a 'C' file to the Project. */\r\n", +"/******************************************************************/\r\n", +"\r\n", +"/* General Purpose Global Flag */\r\n", +"static int wmc_flag_ = 0;\r\n", +"\r\n", +"/* Operation Counter Wrappers */\r\n", +"#define OP_COUNT_WRAPPER1_( op, val ) ( op, val )\r\n", +"#define OP_COUNT_WRAPPER2_( expr ) \\\r\n", +" if ( expr, 0 ) \\\r\n", +" ; \\\r\n", +" else\r\n", +"#define OP_COUNT_WRAPPER3_( op, expr ) \\\r\n", +" if ( op, 0 ) \\\r\n", +" ; \\\r\n", +" else \\\r\n", +" expr\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"/* Define all Macros without '{' & '}' (None of these should be called externally!) */\r\n", +"#define ABS_( x ) OP_COUNT_( _ABS, ( x ) )\r\n", +"#define ADD_( x ) OP_COUNT_( _ADD, ( x ) )\r\n", +"#define MULT_( x ) OP_COUNT_( _MULT, ( x ) )\r\n", +"#define MAC_( x ) OP_COUNT_( _MAC, ( x ) )\r\n", +"#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) )\r\n", +"#define STORE_( x ) OP_COUNT_( _STORE, ( x ) )\r\n", +"#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) )\r\n", +"#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) )\r\n", +"#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) )\r\n", +"#define DIV_( x ) OP_COUNT_( _DIV, ( x ) )\r\n", +"#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) )\r\n", +"#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) )\r\n", +"#define POWER_( x ) TRANS_( x )\r\n", +"#define LOG_( x ) TRANS_( x )\r\n", +"#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) )\r\n", +"#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) )\r\n", +"#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) )\r\n", +"#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) )\r\n", +"#define MISC_( x ) ABS_( x )\r\n", +"\r\n", +"/* Math Operations */\r\n", +"#define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs )\r\n", +"#define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs )\r\n", +"#define fabsf_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabsf )\r\n", +"#define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs )\r\n", +"#define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor )\r\n", +"#define floorf_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floorf )\r\n", +"#define sqrt_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrt )\r\n", +"#define sqrtf_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf )\r\n", +"#define pow_ OP_COUNT_WRAPPER1_( POWER_( 1 ), pow )\r\n", +"#define powf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), powf )\r\n", +"#define exp_ OP_COUNT_WRAPPER1_( POWER_( 1 ), exp )\r\n", +"#define expf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), expf )\r\n", +"#define log_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log )\r\n", +"#define logf_ OP_COUNT_WRAPPER1_( LOG_( 1 ), logf )\r\n", +"#define log10_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10 )\r\n", +"#define log10f_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10f )\r\n", +"#define cos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cos )\r\n", +"#define cosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosf )\r\n", +"#define sin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sin )\r\n", +"#define sinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinf )\r\n", +"#define tan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tan )\r\n", +"#define tanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanf )\r\n", +"#define acos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acos )\r\n", +"#define acosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acosf )\r\n", +"#define asin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asin )\r\n", +"#define asinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asinf )\r\n", +"#define atan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan )\r\n", +"#define atanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atanf )\r\n", +"#define atan2_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2 )\r\n", +"#define atan2f_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2f )\r\n", +"#define cosh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosh )\r\n", +"#define coshf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), coshf )\r\n", +"#define sinh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinh )\r\n", +"#define sinhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinhf )\r\n", +"#define tanh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanh )\r\n", +"#define tanhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanhf )\r\n", +"#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod )\r\n", +"#define fmodf_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmodf )\r\n", +"#define frexp_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexp )\r\n", +"#define frexpf_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexpf )\r\n", +"\r\n", +"/* the macros below are instrumented versions of user-defined macros that might be used in the source code \r\n", +"/* representing some well-known and recognized mathematical operations (that are not defined in math.h) */\r\n", +"/* Note: the 'wmc_flag_=wmc_flag_' is used to avoid warning: left-hand operand of comma expression has no effect with gcc */\r\n", +"\r\n", +"#define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) )\r\n", +"#define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) )\r\n", +"#define MIN_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MIN( ( a ), ( b ) ) )\r\n", +"#define MAX_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MAX( ( a ), ( b ) ) )\r\n", +"#define Min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Min( ( a ), ( b ) ) )\r\n", +"#define Max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Max( ( a ), ( b ) ) )\r\n", +"#define sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), sqr( ( x ) ) )\r\n", +"#define Sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Sqr( ( x ) ) )\r\n", +"#define SQR_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQR( ( x ) ) )\r\n", +"#define square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), square( ( x ) ) )\r\n", +"#define Square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Square( ( x ) ) )\r\n", +"#define SQUARE_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQUARE( ( x ) ) )\r\n", +"#define sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), sign( ( x ) ) )\r\n", +"#define Sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), Sign( ( x ) ) )\r\n", +"#define SIGN_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), SIGN( ( x ) ) )\r\n", +"#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) )\r\n", +"#define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrtf( ( x ) ) )\r\n", +"#define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) )\r\n", +"#define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) )\r\n", +"#define log2f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2f( ( x ) ) )\r\n", +"#define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) )\r\n", +"#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) )\r\n", +"#define round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round( ( x ) ) )\r\n", +"#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) )\r\n", +"#define roundf_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, roundf( ( x ) ) )\r\n", +"#define set_min_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_min( ( a ), ( b ) ) )\r\n", +"#define set_max_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_max( ( a ), ( b ) ) )\r\n", +"\r\n", +"/* Functions */\r\n", +"#define func_( name, x ) OP_COUNT_WRAPPER1_( FUNC_( x ), name )\r\n", +"\r\n", +"/* Logical Operators */\r\n", +"#ifndef __\r\n", +"#define __ ( BRANCH_( 1 ), 1 ) &&\r\n", +"#endif\r\n", +"\r\n", +"/* Ternary Operators (? and :) */\r\n", +"#ifndef _\r\n", +"#define _ ( BRANCH_( 1 ), 0 ) ? 0:\r\n", +"#endif\r\n", +"\r\n", +"/* Flow Control keywords */\r\n", +"#define if_ \\\r\n", +" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n", +" if\r\n", +"#define for_ OP_COUNT_WRAPPER2_( LOOP_(1)) for\r\n", +"#define while_( c ) \\\r\n", +" while \\\r\n", +" OP_COUNT_WRAPPER1_( BRANCH_( 1 ), ( c ) ) /* needs extra \"()\" if ',' encountered */\r\n", +"#define do_ \\\r\n", +" do \\\r\n", +" {\r\n", +"#define _while \\\r\n", +" BRANCH_( 1 ); \\\r\n", +" } \\\r\n", +" while\r\n", +"\r\n", +"#define goto_ \\\r\n", +" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n", +" goto\r\n", +"#define break_ \\\r\n", +" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n", +" break\r\n", +"#define continue_ \\\r\n", +" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n", +" continue\r\n", +"#define return_ \\\r\n", +" OP_COUNT_WRAPPER2_( ( wmc_flag_ = stack_tree_level_, STACK_DEPTH_FCT_RETURN ) ) \\\r\n", +" return\r\n", +"\r\n", +"#define switch_ \\\r\n", +" OP_COUNT_WRAPPER2_( ( BRANCH_( 1 ), wmc_flag_ = 1 ) ) \\\r\n", +" switch\r\n", +"#define cost_( n ) OP_COUNT_WRAPPER2_( wmc_flag_ ? ( ADD_( n ), BRANCH_( n ), wmc_flag_ = 0 ) : 0 );\r\n", +"\r\n", +"#ifdef WMOPS\r\n", +"\r\n", +"#define ACC 2\r\n", +"#define MUL 1\r\n", +"\r\n", +"/* Counting Function (should not be called externally!) */\r\n", +"static void wops_( const char *ops )\r\n", +"{\r\n", +" char lm = 0; /* lm: Last Operation is Math */\r\n", +" static char lo = 0; /* Last Operation */\r\n", +"\r\n", +" void ( *fct )( const char *ops ) = wops_;\r\n", +"\r\n", +"st:\r\n", +" while ( *ops != '\\0' )\r\n", +" {\r\n", +" switch ( *ops++ )\r\n", +" {\r\n", +" int cnt;\r\n", +" case '-':\r\n", +" for ( cnt = 0; ops[cnt] == '>'; cnt++ )\r\n", +" ;\r\n", +" if ( cnt & 1 )\r\n", +" goto ind;\r\n", +" case '+':\r\n", +" lm = 2;\r\n", +" if ( lo & MUL )\r\n", +" {\r\n", +" MULT_( -1 );\r\n", +" MAC_( 1 );\r\n", +" break;\r\n", +" }\r\n", +" lo = ACC << 2;\r\n", +" case 'U':\r\n", +" case 'D':\r\n", +" ADD_( 1 );\r\n", +" break;\r\n", +" case '*':\r\n", +" lm = 2;\r\n", +" if ( lo & ACC )\r\n", +" {\r\n", +" ADD_( -1 );\r\n", +" MAC_( 1 );\r\n", +" break;\r\n", +" }\r\n", +" lo = MUL << 2;\r\n", +" MULT_( 1 );\r\n", +" break;\r\n", +" case '/':\r\n", +" case '%':\r\n", +" lm = 2;\r\n", +" DIV_( 1 );\r\n", +" break;\r\n", +" case '&':\r\n", +" case '|':\r\n", +" case '^':\r\n", +" lm = 2;\r\n", +" case '~':\r\n", +" LOGIC_( 1 );\r\n", +" break;\r\n", +" case '<':\r\n", +" case '>':\r\n", +" if ( *ops != ops[-1] )\r\n", +" goto error;\r\n", +" ops++;\r\n", +" case -85:\r\n", +" case -69:\r\n", +" lm = 2;\r\n", +" SHIFT_( 1 );\r\n", +" break;\r\n", +" case 'L':\r\n", +" case 'G':\r\n", +" if ( *ops == 't' )\r\n", +" goto comp;\r\n", +" case 'E':\r\n", +" case 'N':\r\n", +" if ( *ops != 'e' )\r\n", +" goto error;\r\n", +" comp:\r\n", +" ops++;\r\n", +" ADD_( 1 );\r\n", +" break;\r\n", +" case '!':\r\n", +" MISC_( 2 );\r\n", +" break;\r\n", +" case 'M':\r\n", +" MOVE_( 1 );\r\n", +" break;\r\n", +" case 'S':\r\n", +" STORE_( 1 );\r\n", +" break;\r\n", +" case 'P':\r\n", +" PTR_INIT_( 1 );\r\n", +" break;\r\n", +" case '[':\r\n", +" case ']':\r\n", +" goto st;\r\n", +" ind:\r\n", +" ops++;\r\n", +" case 'I':\r\n", +" case '.':\r\n", +" INDIRECT_( 1 );\r\n", +" break;\r\n", +" case '=':\r\n", +" if ( lm )\r\n", +" goto st;\r\n", +" case '\\0':\r\n", +" /* This Shouldn't Happen */\r\n", +" /* These are Used to Avoid: \"warning: 'name' defined but not used\" with Cygwin gcc Compiler */\r\n", +" wmc_flag_ = wmc_flag_;\r\n", +" ops_cnt_ptr = ops_cnt_ptr;\r\n", +" fct( \"\" );\r\n", +" error:\r\n", +" default:\r\n", +" fprintf( stderr, \"\\r wops: Invalid Counting Operation '%s'\\n\", ops - 1 );\r\n", +" exit( -1 );\r\n", +" }\r\n", +" lm >>= 1;\r\n", +" lo >>= 2;\r\n", +" }\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"/* All Other Operations */\r\n", +"#define $( str ) OP_COUNT_WRAPPER2_( wops_( str ) )\r\n", +"\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * Memory counting tool\r\n", +" *-------------------------------------------------------------------*/\r\n", +"\r\n", +"/* Enhanced Const Data Size Counting (Rounding Up to the Nearest 'Integer' Size) */\r\n", +"#define rsize( item ) ( ( sizeof( item ) + sizeof( int ) - 1 ) / sizeof( int ) * sizeof( int ) )\r\n", +"\r\n", +"#ifdef _MSC_VER\r\n", +"/* Disable \"warning C4210: nonstandard extension used : function given file scope\" with Visual Studio Compiler */\r\n", +"#pragma warning( disable : 4210 )\r\n", +"#endif\r\n", +"\r\n", +"/* Const Data Size and PROM Size Wrapper Functions */\r\n", +"#define Const_Data_Size_Func( file ) Const_Data_Size_##file( void )\r\n", +"#define Get_Const_Data_Size( file, val_ptr ) \\\r\n", +" { \\\r\n", +" extern int Const_Data_Size_##file( void ); \\\r\n", +" *( val_ptr ) = Const_Data_Size_##file(); \\\r\n", +" }\r\n", +"#define PROM_Size_Func( file ) PROM_Size_##file( void )\r\n", +"#define Get_PROM_Size( file, val_ptr ) \\\r\n", +" { \\\r\n", +" int PROM_Size_##file( void ); \\\r\n", +" *( val_ptr ) = PROM_Size_##file(); \\\r\n", +" }\r\n", +"\r\n", +"/* ROM Size Lookup Table - contains information about PROM size and Const Data Size in all source files */\r\n", +"/* The print_mem() function looks for this table to print the results of Const Data usage and PROM usage */\r\n", +"typedef struct ROM_Size_Lookup_Table\r\n", +"{\r\n", +" const char file_spec[255];\r\n", +" int PROM_size;\r\n", +" int ( *Get_Const_Data_Size_Func )( void );\r\n", +"} ROM_Size_Lookup_Table;\r\n", +"\r\n", +"/* The WMC tool inserts the following declaration during the innstrumentation process in the .c file where the function print_mem() is located */\r\n", +"/* and modifies it to print_mem(Const_Data_PROM_Table) */\r\n", +"\r\n", +"/* #ifdef WMOPS\r\n", +" * ROM_Size_Lookup_Table Const_Data_PROM_Table[] =\r\n", +" * {\r\n", +" * {\"../lib_enc/rom_enc.c\", 0, NULL},\r\n", +" * {\"../lib_com/*.c\", 0, NULL},\r\n", +" * {\"\", -1, NULL}\r\n", +" * };\r\n", +" * #endif\r\n", +" */\r\n", +"\r\n", +"/*#define MEM_ALIGN_64BITS */ /* Define this when using 64 Bits values in the code (ex: double), otherwise it will align on 32 Bits */\r\n", +"/*#define MEM_COUNT_DETAILS*/\r\n", +"\r\n", +"typedef enum\r\n", +"{\r\n", +" USE_BYTES = 0,\r\n", +" USE_16BITS = 1,\r\n", +" USE_32BITS = 2,\r\n", +" USE_64BITS = 3\r\n", +"} Counting_Size;\r\n", +"\r\n", +"#if ( defined( _WIN32 ) && ( _MSC_VER <= 1800 ) && ( _MSC_VER >= 1300 ) )\r\n", +"#define __func__ __FUNCTION__\r\n", +"#elif defined( __STDC_VERSION__ ) && __STDC_VERSION__ < 199901L\r\n", +"#if ( __GNUC__ >= 2 )\r\n", +"#define __func__ __FUNCTION__\r\n", +"#else\r\n", +"#define __func__ \"\"\r\n", +"#endif\r\n", +"#elif defined( __GNUC__ )\r\n", +"#define __func__ __extension__ __FUNCTION__\r\n", +"#endif\r\n", +"\r\n", +"\r\n", +"#ifdef WMOPS\r\n", +"\r\n", +"void *mem_alloc( const char *func_name, int func_lineno, size_t size, char *alloc_str );\r\n", +"void mem_free( const char *func_name, int func_lineno, void *ptr );\r\n", +"\r\n", +"#define malloc_( size ) mem_alloc( __func__, __LINE__, size, \"m:\" #size )\r\n", +"#define calloc_( n, size ) mem_alloc( __func__, __LINE__, ( n ) * ( size ), \"c:\" #n \", \" #size )\r\n", +"#define free_( ptr ) mem_free( __func__, __LINE__, ptr )\r\n", +"\r\n", +"void reset_mem( Counting_Size cnt_size );\r\n", +"void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] );\r\n", +"\r\n", +"int push_stack( const char *filename, const char *fctname );\r\n", +"int pop_stack( const char *filename, const char *fctname );\r\n", +"\r\n", +"#ifdef WMOPS_DETAIL\r\n", +"#define STACK_DEPTH_FCT_CALL ( push_wmops( __FUNCTION__ \" [WMC_AUTO]\" ), push_stack( __FILE__, __FUNCTION__ ) ) /* add push_wmops() in all function calls */\r\n", +"#define STACK_DEPTH_FCT_RETURN ( pop_wmops(), pop_stack( __FILE__, __FUNCTION__ ) ) /* add pop_wmops() in all function returns */\r\n", +"#else\r\n", +"#define STACK_DEPTH_FCT_CALL push_stack( __FILE__, __FUNCTION__ )\r\n", +"#define STACK_DEPTH_FCT_RETURN pop_stack( __FILE__, __FUNCTION__ )\r\n", +"#endif\r\n", +"\r\n", +"void reset_stack( void );\r\n", +"#define func_start_ int stack_tree_level_ = STACK_DEPTH_FCT_CALL;\r\n", +"\r\n", +"#else\r\n", +"#define malloc_( n1 ) malloc( n1 )\r\n", +"#define calloc_( n1, n2 ) calloc( n1, n2 )\r\n", +"#define free_( ptr ) free( ptr )\r\n", +"#define reset_mem( cnt_size )\r\n", +"#define print_mem( Const_Data_PROM_Table )\r\n", +"\r\n", +"#define push_stack( file, fct )\r\n", +"#define pop_stack( file, fct )\r\n", +"#define reset_stack()\r\n", +"#define func_start_\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"\r\n", +"/* Global counter variable for calculation of complexity weight */\r\n", +"typedef struct\r\n", +"{\r\n", +" unsigned int add; /* Complexity Weight of 1 */\r\n", +" unsigned int sub; /* Complexity Weight of 1 */\r\n", +" unsigned int abs_s; /* Complexity Weight of 1 */\r\n", +" unsigned int shl; /* Complexity Weight of 1 */\r\n", +" unsigned int shr; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int extract_h; /* Complexity Weight of 1 */\r\n", +" unsigned int extract_l; /* Complexity Weight of 1 */\r\n", +" unsigned int mult; /* Complexity Weight of 1 */\r\n", +" unsigned int L_mult; /* Complexity Weight of 1 */\r\n", +" unsigned int negate; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int round; /* Complexity Weight of 1 */\r\n", +" unsigned int L_mac; /* Complexity Weight of 1 */\r\n", +" unsigned int L_msu; /* Complexity Weight of 1 */\r\n", +" unsigned int L_macNs; /* Complexity Weight of 1 */\r\n", +" unsigned int L_msuNs; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L_add; /* Complexity Weight of 1 */\r\n", +" unsigned int L_sub; /* Complexity Weight of 1 */\r\n", +" unsigned int L_add_c; /* Complexity Weight of 2 */\r\n", +" unsigned int L_sub_c; /* Complexity Weight of 2 */\r\n", +" unsigned int L_negate; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L_shl; /* Complexity Weight of 1 */\r\n", +" unsigned int L_shr; /* Complexity Weight of 1 */\r\n", +" unsigned int mult_r; /* Complexity Weight of 1 */\r\n", +" unsigned int shr_r; /* Complexity Weight of 3 */\r\n", +" unsigned int mac_r; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int msu_r; /* Complexity Weight of 1 */\r\n", +" unsigned int L_deposit_h; /* Complexity Weight of 1 */\r\n", +" unsigned int L_deposit_l; /* Complexity Weight of 1 */\r\n", +" unsigned int L_shr_r; /* Complexity Weight of 3 */\r\n", +" unsigned int L_abs; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L_sat; /* Complexity Weight of 4 */\r\n", +" unsigned int norm_s; /* Complexity Weight of 1 */\r\n", +" unsigned int div_s; /* Complexity Weight of 18 */\r\n", +" unsigned int norm_l; /* Complexity Weight of 1 */\r\n", +" unsigned int move16; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int move32; /* Complexity Weight of 2 */\r\n", +" unsigned int Logic16; /* Complexity Weight of 1 */\r\n", +" unsigned int Logic32; /* Complexity Weight of 2 */\r\n", +" unsigned int Test; /* Complexity Weight of 2 */\r\n", +" unsigned int s_max; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int s_min; /* Complexity Weight of 1 */\r\n", +" unsigned int L_max; /* Complexity Weight of 1 */\r\n", +" unsigned int L_min; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_max; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_min; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int shl_r; /* Complexity Weight of 3 */\r\n", +" unsigned int L_shl_r; /* Complexity Weight of 3 */\r\n", +" unsigned int L40_shr_r; /* Complexity Weight of 3 */\r\n", +" unsigned int L40_shl_r; /* Complexity Weight of 3 */\r\n", +" unsigned int norm_L40; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L40_shl; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_shr; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_negate; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_add; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_sub; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L40_abs; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_mult; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_mac; /* Complexity Weight of 1 */\r\n", +" unsigned int mac_r40; /* Complexity Weight of 2 */\r\n", +"\r\n", +" unsigned int L40_msu; /* Complexity Weight of 1 */\r\n", +" unsigned int msu_r40; /* Complexity Weight of 2 */\r\n", +" unsigned int Mpy_32_16_ss; /* Complexity Weight of 2 */\r\n", +" unsigned int Mpy_32_32_ss; /* Complexity Weight of 4 */\r\n", +" unsigned int L_mult0; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L_mac0; /* Complexity Weight of 1 */\r\n", +" unsigned int L_msu0; /* Complexity Weight of 1 */\r\n", +" unsigned int lshl; /* Complexity Weight of 1 */\r\n", +" unsigned int lshr; /* Complexity Weight of 1 */\r\n", +" unsigned int L_lshl; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L_lshr; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_lshl; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_lshr; /* Complexity Weight of 1 */\r\n", +" unsigned int s_and; /* Complexity Weight of 1 */\r\n", +" unsigned int s_or; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int s_xor; /* Complexity Weight of 1 */\r\n", +" unsigned int L_and; /* Complexity Weight of 1 */\r\n", +" unsigned int L_or; /* Complexity Weight of 1 */\r\n", +" unsigned int L_xor; /* Complexity Weight of 1 */\r\n", +" unsigned int rotl; /* Complexity Weight of 3 */\r\n", +"\r\n", +" unsigned int rotr; /* Complexity Weight of 3 */\r\n", +" unsigned int L_rotl; /* Complexity Weight of 3 */\r\n", +" unsigned int L_rotr; /* Complexity Weight of 3 */\r\n", +" unsigned int L40_set; /* Complexity Weight of 3 */\r\n", +" unsigned int L40_deposit_h; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L40_deposit_l; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_deposit32; /* Complexity Weight of 1 */\r\n", +" unsigned int Extract40_H; /* Complexity Weight of 1 */\r\n", +" unsigned int Extract40_L; /* Complexity Weight of 1 */\r\n", +" unsigned int L_Extract40; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L40_round; /* Complexity Weight of 1 */\r\n", +" unsigned int L_saturate40; /* Complexity Weight of 1 */\r\n", +" unsigned int round40; /* Complexity Weight of 1 */\r\n", +" unsigned int If; /* Complexity Weight of 4 */\r\n", +" unsigned int Goto; /* Complexity Weight of 4 */\r\n", +"\r\n", +" unsigned int Break; /* Complexity Weight of 4 */\r\n", +" unsigned int Switch; /* Complexity Weight of 8 */\r\n", +" unsigned int For; /* Complexity Weight of 3 */\r\n", +" unsigned int While; /* Complexity Weight of 4 */\r\n", +" unsigned int Continue; /* Complexity Weight of 4 */\r\n", +"\r\n", +" unsigned int L_mls; /* Complexity Weight of 6 */\r\n", +" unsigned int div_l; /* Complexity Weight of 32 */\r\n", +" unsigned int i_mult; /* Complexity Weight of 3 */\r\n", +"} BASIC_OP;\r\n", +"\r\n", +"#ifdef WMOPS\r\n", +"extern BASIC_OP *multiCounter;\r\n", +"extern int currCounter;\r\n", +"\r\n", +"/* Technical note :\r\n", +" * The following 3 variables are only used for correct complexity\r\n", +" * evaluation of the following structure :\r\n", +" * IF{\r\n", +" * ...\r\n", +" * } ELSE IF {\r\n", +" * ...\r\n", +" * } ELSE IF {\r\n", +" * ...\r\n", +" * }\r\n", +" * ...\r\n", +" * } ELSE {\r\n", +" * ...\r\n", +" * }\r\n", +" */\r\n", +"extern int funcId_where_last_call_to_else_occurred;\r\n", +"extern long funcid_total_wmops_at_last_call_to_else;\r\n", +"extern int call_occurred;\r\n", +"\r\n", +"extern long TotalWeightedOperation( void );\r\n", +"long DeltaWeightedOperation( void );\r\n", +"\r\n", +"void Set_BASOP_WMOPS_counter( int counterId );\r\n", +"void Reset_BASOP_WMOPS_counter( void );\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : FOR\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro FOR should be used instead of the 'for' C statement.\r\n", +" * The complexity is independent of the number of loop iterations that are\r\n", +" * performed.\r\n", +" *\r\n", +" * Complexity weight : 3 (regardless of number of iterations).\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define FOR( a) for( a)\r\n", +"\r\n", +"#else \r\n", +"#define FOR( a) if( incrFor(), 0); else for( a)\r\n", +"\r\n", +"static __inline void incrFor( void) {\r\n", +" multiCounter[currCounter].For++;\r\n", +"}\r\n", +"#endif \r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : WHILE\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro WHILE should be used instead of the 'while' C statement.\r\n", +" * The complexity is proportional to the number of loop iterations that\r\n", +" * are performed.\r\n", +" *\r\n", +" * Complexity weight : 4 x 'number of loop iterations'.\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define WHILE( a) while( a)\r\n", +"\r\n", +"#else \r\n", +"#define WHILE( a) while( incrWhile(), a)\r\n", +"\r\n", +"static __inline void incrWhile( void) {\r\n", +" multiCounter[currCounter].While++;\r\n", +"}\r\n", +"#endif \r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : DO\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro DO should be used instead of the 'do' C statement.\r\n", +" *\r\n", +" * Complexity weight : 0 (complexity counted by WHILE macro).\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define DO do\r\n", +"\r\n", +"#else \r\n", +"#define DO do\r\n", +"\r\n", +"#endif \r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : IF\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro IF should :\r\n", +" *\r\n", +" * - not be used when :\r\n", +" * - the 'if' structure does not have any 'else if' nor 'else' statement\r\n", +" * - and it conditions only one DSP basic operations.\r\n", +" *\r\n", +" * - be used instead of the 'if' C statement in every other case :\r\n", +" * - when there is an 'else' or 'else if' statement,\r\n", +" * - or when the 'if' conditions several DSP basic operations,\r\n", +" * - or when the 'if' conditions a function call.\r\n", +" *\r\n", +" * Complexity weight : 4\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define IF( a) if( a)\r\n", +"\r\n", +"#else \r\n", +"#define IF( a) if( incrIf(), a)\r\n", +"\r\n", +"static __inline void incrIf( void) {\r\n", +" /* Technical note :\r\n", +" * If the \"IF\" operator comes just after an \"ELSE\", its counter\r\n", +" * must not be incremented.\r\n", +" */\r\n", +" if ( ( currCounter != funcId_where_last_call_to_else_occurred ) || ( TotalWeightedOperation() != funcid_total_wmops_at_last_call_to_else ) || ( call_occurred == 1 ) )\r\n", +" {\r\n", +" multiCounter[currCounter].If++;\r\n", +" }\r\n", +"\r\n", +" call_occurred = 0;\r\n", +" funcId_where_last_call_to_else_occurred = INT_MAX;\r\n", +"}\r\n", +"#endif \r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : ELSE\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro ELSE should be used instead of the 'else' C statement.\r\n", +" *\r\n", +" * Complexity weight : 4\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define ELSE else\r\n", +"\r\n", +"#else \r\n", +"#define ELSE else if( incrElse(), 0) ; else\r\n", +"\r\n", +"static __inline void incrElse( void) {\r\n", +" multiCounter[currCounter].If++;\r\n", +"\r\n", +" /* We keep track of the funcId of the last function\r\n", +" * which used ELSE {...} structure.\r\n", +" */\r\n", +" funcId_where_last_call_to_else_occurred = currCounter;\r\n", +"\r\n", +" /* We keep track of the number of WMOPS of this funcId\r\n", +" * when the ELSE macro was called.\r\n", +" */\r\n", +" funcid_total_wmops_at_last_call_to_else = TotalWeightedOperation();\r\n", +"\r\n", +" /* call_occurred is set to 0, in order to count the next IF (if necessary)\r\n", +" */\r\n", +" call_occurred = 0;\r\n", +"}\r\n", +"#endif \r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : SWITCH\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro SWITCH should be used instead of the 'switch' C statement.\r\n", +" *\r\n", +" * Complexity weight : 8\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define SWITCH( a) switch( a)\r\n", +"\r\n", +"#else \r\n", +"#define SWITCH( a) switch( incrSwitch(), a)\r\n", +"\r\n", +"static __inline void incrSwitch( void) {\r\n", +" multiCounter[currCounter].Switch++;\r\n", +"}\r\n", +"#endif \r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : CONTINUE\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro CONTINUE should be used instead of the 'continue' C statement.\r\n", +" *\r\n", +" * Complexity weight : 4\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define CONTINUE continue\r\n", +"\r\n", +"#else \r\n", +"#define CONTINUE if( incrContinue(), 0); else continue\r\n", +"\r\n", +"static __inline void incrContinue( void) {\r\n", +" multiCounter[currCounter].Continue++;\r\n", +"}\r\n", +"#endif \r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : BREAK\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro BREAK should be used instead of the 'break' C statement.\r\n", +" *\r\n", +" * Complexity weight : 4\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define BREAK break\r\n", +"\r\n", +"#else \r\n", +"#define BREAK if( incrBreak(), 0) break; else break\r\n", +"\r\n", +"static __inline void incrBreak( void) {\r\n", +" multiCounter[currCounter].Break++;\r\n", +"}\r\n", +"#endif \r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : GOTO\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro GOTO should be used instead of the 'goto' C statement.\r\n", +" *\r\n", +" * Complexity weight : 4\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define GOTO goto\r\n", +"\r\n", +"#else \r\n", +"#define GOTO if( incrGoto(), 0); else goto\r\n", +"\r\n", +"static __inline void incrGoto( void) {\r\n", +" multiCounter[currCounter].Goto++;\r\n", +"}\r\n", +"#endif \r\n", +"\r\n", +"#endif /* WMOPS_H */\r\n", +"\r\n", +"\r\n", +"\r\n", \ No newline at end of file diff --git a/src/wmc_tool/wmc_tool.cpp b/src/wmc_tool/wmc_tool.cpp index d0d7df2..dac4c48 100644 --- a/src/wmc_tool/wmc_tool.cpp +++ b/src/wmc_tool/wmc_tool.cpp @@ -1028,23 +1028,44 @@ static TOOL_ERROR Output_Wmops_File( char *PathName, float frames_per_sec, bool { TOOL_ERROR ErrCode = NO_ERR; FILE *TargetFile; - int i, len; + int i, j, len, num_strings, offset; char SrcFileName[MAX_PATH + 1]; /* +1 for NUL Char*/ char TargetFileName[MAX_PATH + 1]; /* +1 for NUL Char*/ - char *text = NULL, *p_str, temp_str[50]; + char *text = NULL, temp_str[50]; const char* wmops_auto_files[] = { "wmc_auto.h", "wmc_auto.c" }; - static const char wmops_auto_file_h[] = -#include "wmc_auto_h.txt" - ; - static const char wmops_auto_file_c[] = -#include "wmc_auto_c.txt" - ; + const char** wmops_auto_file; + const char* wmops_auto_file_h[] = { + #include "wmc_auto_h.txt" + }; + const char* wmops_auto_file_c[] = { + #include "wmc_auto_c.txt" + }; for (i = 0; i < 2; i++) { - /* Allocate a char * buffer for further manipulation of the source file text */ - text = (char*)calloc(i == 0 ? sizeof(wmops_auto_file_h) : sizeof(wmops_auto_file_c), sizeof(char)); + /* get the pointer */ + if (i == 0) + { + wmops_auto_file = wmops_auto_file_h; + num_strings = sizeof(wmops_auto_file_h) / sizeof(char*); + } + else + { + wmops_auto_file = wmops_auto_file_c; + num_strings = sizeof(wmops_auto_file_c) / sizeof(char*); + } + + /* calculate the total length required */ + len = 0; + for (j = 0; j < num_strings; j++) + { + len += (int) strlen(wmops_auto_file[j]); + } + len++; + + /* allocate a char * buffer for further manipulation of the source file text */ + text = (char*) calloc(len, sizeof(char)); if (text == NULL) { ErrCode = ERR_FILE_READ; @@ -1052,16 +1073,22 @@ static TOOL_ERROR Output_Wmops_File( char *PathName, float frames_per_sec, bool goto ret; } - /* copy the source file contents to a char * buffer for further manipulation */ - strcpy(text, i == 0 ? wmops_auto_file_h : wmops_auto_file_c); - - /* Replace the constant FRAMES_PER_SECOND */ - p_str = strstr(text, "#define FRAMES_PER_SECOND"); - - if (p_str != NULL) + /* copy each string */ + offset = 0; + for (j = 0; j < num_strings; j++) { - sprintf(temp_str, "#define FRAMES_PER_SECOND %-8.1f", frames_per_sec); - strncpy(p_str, temp_str, strlen(temp_str)); + if (strstr(wmops_auto_file[j], "#define FRAMES_PER_SECOND") != NULL) + { + /* replace the declaration of FRAMES_PER_SECOND with user-defined value */ + sprintf(temp_str, "#define FRAMES_PER_SECOND %-8.1f", frames_per_sec); + strcpy(text + offset, temp_str); + offset += (int) strlen(temp_str); + } + else + { + strcpy(text + offset, wmops_auto_file[j]); + offset += (int) strlen(wmops_auto_file[j]); + } } /* Create Target Filename */ From aadcb104a9c24cf7d54656d93d0e2ebeee11a29c Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Mon, 22 Jul 2024 08:57:07 +0200 Subject: [PATCH 54/67] correction of Python interpreter in findpackage() not supported by later versions of Cmake --- src/wmc_tool/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wmc_tool/CMakeLists.txt b/src/wmc_tool/CMakeLists.txt index 858ee70..465c5e1 100644 --- a/src/wmc_tool/CMakeLists.txt +++ b/src/wmc_tool/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.5) project(wmc_tool) include(CTest) @@ -10,8 +10,8 @@ if(WIN32) ) endif() -add_executable(wmc_tool c_parser.cpp output.cpp text_utils.cpp wmc_tool.cpp) -find_package(PythonInterp) +add_executable(wmc_tool parsing_defs.h c_parser.h c_parser.cpp output.h output.cpp text_utils.h text_utils.cpp constants.h wmc_tool.h wmc_tool.cpp) +find_package (Python COMPONENTS Interpreter) # Testing file(TO_CMAKE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/test_data TEST_DIR) From 0400207a09efdb11fa33cb48bcc0ba74a2e70be6 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Mon, 22 Jul 2024 08:59:13 +0200 Subject: [PATCH 55/67] addition of --skip-cmplx-instrumentation command-line option allowing skipping complexity instrumentation in function bodies --- src/wmc_tool/HISTORY.md | 4 +++ src/wmc_tool/c_parser.cpp | 64 ++++++++++++++++++++++++--------------- src/wmc_tool/c_parser.h | 2 +- src/wmc_tool/wmc_tool.cpp | 19 ++++++++++-- src/wmc_tool/wmc_tool.h | 2 +- 5 files changed, 61 insertions(+), 30 deletions(-) diff --git a/src/wmc_tool/HISTORY.md b/src/wmc_tool/HISTORY.md index 456511f..988cc26 100644 --- a/src/wmc_tool/HISTORY.md +++ b/src/wmc_tool/HISTORY.md @@ -66,4 +66,8 @@ * export information about all dynamic allocations/de-allocations occuring during the runtime of the codec to a `.csv` file * added an exemplary Python script `mem_analysis.py` for graphical analysis and profiling of dynamic memory alloations based on the generated `.csv` file * added support for counting complexity and PROM size of BASOP operations and BASOP functions within floating-point source code + +## v1.5.1 + + * added the -s (--skip_cmplx_instrumentation) command-line option, which avoids the instrumentation of function bodies. The func_start_ and return_ keywords, along with the remaining functionality, remain unchanged. \ No newline at end of file diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 79f1101..95ccf5e 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -4667,7 +4667,8 @@ static TOOL_ERROR Instrument_Switch( * Instrument_Keywords *-------------------------------------------------------------------*/ static TOOL_ERROR Instrument_Keywords( - Parse_Context_def *ParseCtx_ptr ) + Parse_Context_def *ParseCtx_ptr, + bool skip_cmplx_instrum) { TOOL_ERROR ErrCode = NO_ERR; @@ -4696,7 +4697,7 @@ static TOOL_ERROR Instrument_Keywords( item_type = ParseRec_ptr->item_type; /* Skipped? */ - unless( item_type & ITEM_SKIPPED ) + if( !(item_type & ITEM_SKIPPED) ) { /* No */ /* In Skipped or Non-Instrumented Region? */ if ( Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED | ITEM_INSTRUMENTATION_OFF ) < 0 @@ -4704,13 +4705,21 @@ static TOOL_ERROR Instrument_Keywords( || ( item_type == ITEM_KEYWORD_RETURN /* 'return not' Instrumented in Skipped Regions */ && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED ) < 0 - && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_FUNC_BLOCK ) < 0 && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_FUNC_BLOCK | ITEM_FUNC_MATH ) < 0 && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_FUNC_BLOCK | ITEM_FUNC_SYSTEM ) < 0 ) ) + && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_FUNC_BLOCK ) < 0 + && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_FUNC_BLOCK | ITEM_FUNC_MATH ) < 0 + && Find_Region( ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_FUNC_BLOCK | ITEM_FUNC_SYSTEM ) < 0 ) ) { /* No */ /* Instrument After (by default) */ ptr = ParseRec_ptr->item_end; - /* Is it a 'while' that is part of a 'do' Block? */ - /* Insert Instrumentation Character */ + if (skip_cmplx_instrum && item_type != ITEM_KEYWORD_RETURN) + { + /* skip the instrumentation if the user specified so on the command-line */ + /* with the exception of the 'return' keywords */ + continue; + } + + /* Insert Instrumentation Character '_' */ if ( ( ErrCode = Add_Insertion( &ParseCtx_ptr->InsertTbl, ptr, WORD_INSTRUMENT_STRING ) ) != NO_ERR ) { goto ret; @@ -4719,29 +4728,28 @@ static TOOL_ERROR Instrument_Keywords( /* Is it a 'while'? Auto Instrumentation Macro for 'while' in a 'do' Block can handle multiple Condition. */ - if ( item_type == ITEM_KEYWORD_WHILE - /* 'while' from 'do/while' now Needs Extra () for Multiple Condition*/ - || item_type == ITEM_KEYWORD_WHILE2 - ) + if (item_type == ITEM_KEYWORD_WHILE + /* 'while' from 'do/while' now Needs Extra () for Multiple Condition*/ + || item_type == ITEM_KEYWORD_WHILE2 ) { /* Yes */ /* Advance to Parameters Record */ ParseRec_ptr++; /* More than one Condition? */ - if ( Count_Args( ParseRec_ptr->item_start, - ParseRec_ptr->item_end - 1, - ParseTbl_ptr ) > 1 ) + if (Count_Args(ParseRec_ptr->item_start, + ParseRec_ptr->item_end - 1, + ParseTbl_ptr) > 1) { /* Yes */ /* Must Add Extra () */ - if ( ( ErrCode = Add_Insertion( &ParseCtx_ptr->InsertTbl, - ParseRec_ptr->item_start, - "(" ) ) != NO_ERR ) + if ((ErrCode = Add_Insertion(&ParseCtx_ptr->InsertTbl, + ParseRec_ptr->item_start, + "(")) != NO_ERR) { goto ret; } - if ( ( ErrCode = Add_Insertion( &ParseCtx_ptr->InsertTbl, - ParseRec_ptr->item_end, - ")" ) ) != NO_ERR ) + if ((ErrCode = Add_Insertion(&ParseCtx_ptr->InsertTbl, + ParseRec_ptr->item_end, + ")")) != NO_ERR) { goto ret; } @@ -8112,7 +8120,9 @@ TOOL_ERROR Include_Header( TOOL_ERROR Instrument( Parse_Context_def *ParseCtx_ptr, - bool instrument_ROM ) + bool instrument_ROM, + bool skip_cmplx_instrum +) { TOOL_ERROR ErrCode = NO_ERR; @@ -8122,6 +8132,7 @@ TOOL_ERROR Instrument( ErrCode = Internal_Error( __FUNCTION__ ); goto ret; } + /* Set State Failure (by default) */ ParseCtx_ptr->State = INS_FAILED; @@ -8149,7 +8160,7 @@ TOOL_ERROR Instrument( /* Erase Function Call Table */ ParseCtx_ptr->FctCallTbl.Size = 0; - if ( ( ErrCode = Instrument_Calls( ParseCtx_ptr ) ) != NO_ERR ) + if ((ErrCode = Instrument_Calls(ParseCtx_ptr)) != NO_ERR) { goto ret; } @@ -8170,7 +8181,7 @@ TOOL_ERROR Instrument( } is_function_present = 0; - if (idx > 0) + if ( idx > 0 ) { is_function_present = 1; } @@ -8263,17 +8274,20 @@ TOOL_ERROR Instrument( /* $(...) inserted on same Line as #pragma message for Skipped Region */ } - if ( ( ErrCode = Instrument_Operators( ParseCtx_ptr ) ) != NO_ERR ) + if (!skip_cmplx_instrum) { - goto ret; + if ((ErrCode = Instrument_Operators(ParseCtx_ptr)) != NO_ERR) + { + goto ret; + } } - if ( ( ErrCode = Instrument_Keywords( ParseCtx_ptr ) ) != NO_ERR ) + if ((ErrCode = Instrument_Keywords(ParseCtx_ptr, skip_cmplx_instrum)) != NO_ERR) { goto ret; } - if ( instrument_ROM && is_cnst_data_present) + if ( instrument_ROM && is_cnst_data_present ) { if ( ( ErrCode = Instrument_ROM( ParseCtx_ptr) ) != NO_ERR ) { diff --git a/src/wmc_tool/c_parser.h b/src/wmc_tool/c_parser.h index fcdf810..4c51e94 100644 --- a/src/wmc_tool/c_parser.h +++ b/src/wmc_tool/c_parser.h @@ -31,7 +31,7 @@ void Free_Pointer_Table_Memory( Pointer_Tbl_def *PointerTable_ptr ); TOOL_ERROR Setup_Regions( Parse_Context_def *ParseContext_ptr, bool verbose ); TOOL_ERROR DesInstrument( Parse_Context_def *ParseContext_ptr, bool keep_manual ); TOOL_ERROR DesInstrument_ROM(Parse_Context_def* ParseCtx_ptr); -TOOL_ERROR Instrument(Parse_Context_def* ParseContext_ptr, bool instr_const); +TOOL_ERROR Instrument(Parse_Context_def* ParseContext_ptr, bool instr_const, bool skip_cmplx_instrum); TOOL_ERROR Instrument_Const_Data_PROM_Table( Parse_Context_def *ParseContext_ptr, T_FILE_BOOK file_book[], int nRecords ); TOOL_ERROR Finalize( Parse_Context_def *ParseContext_ptr ); TOOL_ERROR Include_Header(Parse_Context_def* ParseContext_ptr, char** ptr_end_preproc_block ); diff --git a/src/wmc_tool/wmc_tool.cpp b/src/wmc_tool/wmc_tool.cpp index dac4c48..097d8d4 100644 --- a/src/wmc_tool/wmc_tool.cpp +++ b/src/wmc_tool/wmc_tool.cpp @@ -54,10 +54,11 @@ #define DESINSTRUMENT_ONLY 0x001 #define REMOVE_MANUAL_INSTR 0x002 #define VERBOSE 0x004 +#define SKIP_CMPLX_INSTRUM 0x010 #define NO_BACKUP 0x020 #define INSTR_INFO_ONLY 0x040 -#define OUTPUT_WMOPS_FILES 0x080 #define INSTRUMENT_ROM 0x100 +#define OUTPUT_WMOPS_FILES 0x200 /* Other Constants */ #define BACKUP_SUFFIX ".bak" @@ -77,6 +78,7 @@ static void usage() "Options:\n" " -h [--help]: print help\n" " -v [--verbose]: print warnings and other information messages\n" + " -s [--skip-cmplx-instrumentation]: skip complexity instrumentation\n" " -i [--info-only]: only print instrumentation information\n" " -d [--desinstrument]: desintrument only\n" " -m filename [--rom filename]: add statistics about ROM and RAM consumption\n" @@ -191,6 +193,10 @@ static TOOL_ERROR Parse_Command_Line( { *Operation |= INSTR_INFO_ONLY; } + else if (_stricmp(arg_name, "s") == 0 || _stricmp(arg_name, "skip-cmplx-instrumentation") == 0) + { + *Operation |= SKIP_CMPLX_INSTRUM; + } else if (_stricmp(arg_name, "c") == 0 || _stricmp(arg_name, "generate-wmc-files") == 0) { /* get the next argument - must be an existing direectory */ @@ -993,7 +999,7 @@ static TOOL_ERROR Process_File( if ( !( Operation & DESINSTRUMENT_ONLY ) ) { /* Yes */ /* Instrument */ - if ((ErrCode = Instrument(ParseCtx_ptr, (Operation & INSTRUMENT_ROM) != 0)) != NO_ERR) + if ((ErrCode = Instrument(ParseCtx_ptr, (Operation & INSTRUMENT_ROM) != 0, (Operation & SKIP_CMPLX_INSTRUM) != 0)) != NO_ERR) { fprintf(stdout, "\n"); return ErrCode; @@ -1238,7 +1244,14 @@ int main( int argc, char *argv[] ) if (!(Operation & DESINSTRUMENT_ONLY)) { - fprintf(stdout, "- instrumenting all functions and table (const) data memory\n"); + if (Operation & SKIP_CMPLX_INSTRUM) + { + fprintf(stdout, "- skipping instrumentation of functions\n"); + } + else + { + fprintf(stdout, "- instrumenting all functions and table (const) data memory\n"); + } } if (Operation & OUTPUT_WMOPS_FILES) diff --git a/src/wmc_tool/wmc_tool.h b/src/wmc_tool/wmc_tool.h index 95d961e..ff7fd05 100644 --- a/src/wmc_tool/wmc_tool.h +++ b/src/wmc_tool/wmc_tool.h @@ -19,7 +19,7 @@ * Switches *-------------------------------------------------------------------*/ -#define WMC_TOOL_VERSION_NO "1.5" /* Current version */ +#define WMC_TOOL_VERSION_NO "1.5.1" /* Current version */ /*#define DEBUG_PRINT*/ /* For debugging purposes */ /*-------------------------------------------------------------------* From a0a04f8d40ac49705d812ffe14d6a8c963439061 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Mon, 22 Jul 2024 13:31:21 +0200 Subject: [PATCH 56/67] relax 70% upper char condition checking for local macros --- src/wmc_tool/c_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 95ccf5e..394b877 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -1657,7 +1657,7 @@ static bool Is_Constant( UpperChar = Total = 0; do { - if ( IS_UPPER_CHAR( *ptr ) ) + if ( !IS_LOWER_CHAR( *ptr ) ) UpperChar += 100; Total++; ptr++; From 09daf1ad09c886ad601cd3263a7105b3e37d7e62 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 23 Jul 2024 14:32:54 +0200 Subject: [PATCH 57/67] fix bug when WMC tool does not instrument malloc() calls in IF(...) statements due to INSTRUMENTATION_OFF --- src/wmc_tool/c_parser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 394b877..c76ca96 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -5897,7 +5897,7 @@ static TOOL_ERROR Instrument_Calls( } /* System Allocation Function */ /* !! VM: Added && Find_Region(.) to avoid instrumentation of malloc() calls within WMC_TOOL_SKIP segments */ - if ( (item_type & ITEM_FUNC_SYSTEM) && Find_Region(ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED | ITEM_INSTRUMENTATION_OFF) < 0 ) + if ((item_type & ITEM_FUNC_SYSTEM) && Find_Region(ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED) < 0) { /* Yes */ /* Insert Instrumentation */ if ( ( ErrCode = Add_Insertion( &ParseCtx_ptr->InsertTbl, end, WORD_INSTRUMENT_STRING ) ) != NO_ERR ) From a72aac27d19b4c3163ba8a3b19d72a2a97b40e8b Mon Sep 17 00:00:00 2001 From: malenov Date: Fri, 26 Jul 2024 09:43:31 +0200 Subject: [PATCH 58/67] fixing des-instrumentation of a file that contains print_mem() function plus some instrumented code, e.g. encoder.c --- src/wmc_tool/c_parser.cpp | 158 ++++++++++++++------------------------ src/wmc_tool/wmc_tool.h | 2 +- 2 files changed, 60 insertions(+), 100 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index c76ca96..4f4bb3a 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -7343,7 +7343,6 @@ TOOL_ERROR DesInstrument( } - /*-------------------------------------------------------------------* * DesInstrument_ROM *-------------------------------------------------------------------*/ @@ -7384,121 +7383,82 @@ TOOL_ERROR DesInstrument_ROM( start = ParseRec_ptr->item_start; tmp = ParseRec_ptr->item_end; - /* Instrumentation Code? E.g. 'AddedByWMC_Tool' */ - if (ParseRec_ptr->item_type & ITEM_FUNC_COUNTERS_AUTO && ((ParseRec_ptr->item_type & ITEM_FUNC_COUNTERS_MAN) == 0 || - Find_Region(start, ParseTbl_ptr, ITEM_INSTRUMENTATION_OFF) < 0)) - { /* Yes */ - if (!(ParseRec_ptr->item_type & ITEM_PREPROC_LINE)) - { - /* Delete it */ - Delete(start, tmp); - } - } - - /* 'Const_Data_PROM_Table' Declaration? */ - else if (ParseRec_ptr->item_type & ITEM_DATA_DECL) + /* Data Declaration? */ + if (ParseRec_ptr->item_type & ITEM_DATA_DECL) { /* Yes */ - /* Check if this ROM_Size_Lookup_Table declaration */ + /* Check if this is ROM_Size_Lookup_Table declaration */ if (strnistr(start, "ROM_Size_Lookup_Table", strlen("ROM_Size_Lookup_Table")) != NULL) { - /* Save the pointers - will be used later to check, if it was enclosed in #ifdef WMOPS .. #endif pair */ - start_const_data_prom_table = start; - end_const_data_prom_table = tmp; - } - - /* Delete it */ - Delete(start, tmp); - - } - - /* One of the ROM counting functions, e.g. 'Const_Data_Size_Func(...)'? */ - else if (ParseRec_ptr->item_type & ITEM_FUNC_DEF) - { /* Yes */ - /* Is function prototype or block followed by some blank chars? -> delete them as well */ - if (ParseRec_ptr->item_type & (ITEM_FUNC_PROTO | ITEM_FUNC_BLOCK)) - { - tmp = Skip_Chars(tmp, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_COMMENT, FORWARD); - } + /* Go back to the beginning of the line */ + start = Goto_Chars(start, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + start++; - /* Delete it */ - Delete(start, tmp); - - /* Desintrumenting Function Name? -> Check if it's preceded by 'extern int' or 'static int' return type */ - if (ParseRec_ptr->item_type & ITEM_FUNC_NAME) - { - /* Find the end of the preceding keyword */ - while ((tmp = Skip_Chars(start - 1, SPACE_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_MOVED_OVER, BACKWARDS)) != NULL && IS_IDENTIFIER_CHAR(*tmp)) + /* Check, if line starts with "AddedByWMC_Tool */ + while (strncmp(start, ADDED_TOOL_INFO_STRING, strlen(ADDED_TOOL_INFO_STRING)) == 0) { - /* Find the beginning of the preceding keyword */ - start = Skip_Identifier(tmp, BACKWARDS) + 1; - - /* Check if the found keyword matches one of 'extern', 'static' or 'int' */ - if (memwordcmp(start, STORAGE_STRING) || memwordcmp(start, INT_STRING)) - { /* Yes */ - /* Delete it */ - Delete(start, tmp + 2); + /* check, if line continues with "#ifdef WMOPS" */ + if (strncmp(start + strlen(ADDED_TOOL_INFO_STRING), "#ifdef WMOPS", strlen("#ifdef WMOPS")) == 0) + { + start_const_data_prom_table = start; + break; + } + else + { + /* Go back to the beginning of the previous line */ + start = Skip_Chars(start - 1, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + start = Goto_Chars(start, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + start++; } } - } - - /* Item is no Longer a Function Name/Proto/Block */ - ParseRec_ptr->item_type &= ~ITEM_FUNC_DEF; - } - - /* Item is no Longer Instrumentation */ - ParseRec_ptr->item_type ^= ITEM_INSTRUMENTATION; - } - /* Check, if Const_Data_PROM_Table[] was enclosed in #ifdef WMOPS .. #endif pair */ - if (start_const_data_prom_table != NULL && end_const_data_prom_table != NULL) - { - /* Go back to the first word preceding Const_Data_PROM_Table[] */ - start = Skip_Chars(start_const_data_prom_table - 1, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); - - /* Proceed to the beginning of the line */ - while (!IS_EOL_CHAR(PREV_CHAR(start))) - { - start--; - } + if (!IS_EOL_CHAR(PREV_CHAR(tmp))) + { + /* Go to the beginning of the next line */ + tmp = Goto_Chars(tmp, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, FORWARD); + tmp = Skip_Chars(tmp, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, FORWARD); + } - /* Check if line contains "#ifdef WMOPS" */ - if ( (tmp = stristr(memstr(start, start_const_data_prom_table), "#ifdef")) != NULL) - { - tmp = Skip_Identifier(tmp, FORWARD); - tmp = Skip_Chars(tmp + 1, SPACE_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE); - if (strncmp(tmp, "WMOPS", strlen("WMOPS")) == 0) - { - /* Delete the whole line */ - Delete(start, start_const_data_prom_table); - } - } + /* Check, if line starts with "AddedByWMC_Tool */ + while (strncmp(tmp, ADDED_TOOL_INFO_STRING, strlen(ADDED_TOOL_INFO_STRING)) == 0) + { + /* check, if line continues with "#endif" */ + if (strncmp(tmp + strlen(ADDED_TOOL_INFO_STRING), "#endif", strlen("#endif")) == 0) + { + /* Go to the end this line */ + tmp = Goto_Chars(tmp, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, FORWARD); - /* Go to the first word after Const_Data_PROM_Table[] */ - end = Skip_Chars(end_const_data_prom_table, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE); + /* Go past the EOL */ + if (IS_EOL_SEQ(tmp)) + { + /* One Extra step, if it's CR+LF */ + tmp++; + } + tmp++; - /* Check if line contains "#endif" */ - while (!IS_EOL_CHAR(NEXT_CHAR(end))) - { - if (*end == '#') - { - /* Found '#' */ - if (strncmp(end, "#endif", strlen("#endif")) == 0) - { - /* Go to EOL */ - while (*end != LF_CHAR) + end_const_data_prom_table = tmp; + break; + } + else { - end++; + /* Go to the beginning of the next line */ + tmp = Goto_Chars(tmp, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, FORWARD); + tmp = Skip_Chars(tmp, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, FORWARD); } + } - /* Delete the whole line */ - Delete(end_const_data_prom_table, end); - - break; + if (start_const_data_prom_table != NULL && end_const_data_prom_table != NULL) + { + /* Delete the whole segment */ + Delete(start, tmp); } - } - end++; + /* Item is no Longer a Declaration */ + ParseRec_ptr->item_type ^= ITEM_DATA_DECL; + + /* Item is no Longer Instrumentation */ + ParseRec_ptr->item_type ^= ITEM_INSTRUMENTATION; + } } } diff --git a/src/wmc_tool/wmc_tool.h b/src/wmc_tool/wmc_tool.h index ff7fd05..f081798 100644 --- a/src/wmc_tool/wmc_tool.h +++ b/src/wmc_tool/wmc_tool.h @@ -19,7 +19,7 @@ * Switches *-------------------------------------------------------------------*/ -#define WMC_TOOL_VERSION_NO "1.5.1" /* Current version */ +#define WMC_TOOL_VERSION_NO "1.5.2" /* Current version */ /*#define DEBUG_PRINT*/ /* For debugging purposes */ /*-------------------------------------------------------------------* From 70e8f35c6bcd5d817560af2da2a6c6bcc924aa52 Mon Sep 17 00:00:00 2001 From: malenov Date: Mon, 29 Jul 2024 15:16:01 +0200 Subject: [PATCH 59/67] update to version v1.6 --- src/wmc_tool/wmc_tool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmc_tool/wmc_tool.h b/src/wmc_tool/wmc_tool.h index f081798..891d69b 100644 --- a/src/wmc_tool/wmc_tool.h +++ b/src/wmc_tool/wmc_tool.h @@ -19,7 +19,7 @@ * Switches *-------------------------------------------------------------------*/ -#define WMC_TOOL_VERSION_NO "1.5.2" /* Current version */ +#define WMC_TOOL_VERSION_NO "1.6" /* Current version */ /*#define DEBUG_PRINT*/ /* For debugging purposes */ /*-------------------------------------------------------------------* From 1164cb6b961af55ff8da88f4b4df92b1df3a5e50 Mon Sep 17 00:00:00 2001 From: malenov Date: Mon, 29 Jul 2024 15:17:05 +0200 Subject: [PATCH 60/67] when #undef WMC_TOOL_SKIP is missing, automatically assume end of file but before the last automatically instrumented segment --- src/wmc_tool/c_parser.cpp | 166 +++++++++++++++++++++++++++++++++----- 1 file changed, 147 insertions(+), 19 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 4f4bb3a..0ea8eae 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -3549,6 +3549,46 @@ static TOOL_ERROR Find_Preproc_Instrumentation( } } + /* Mark all lines preceded by AddedByWMC_Tool as Instrumentation */ + + /* Start at Beginning */ + ptr = ParseCtx_ptr->File.Data; + + /* Search for AddedBy_WMC_Tool string which has not been marked as instrumentation yet */ + while ((ptr = Find_Identifier(ptr, ADDED_TOOL_INFO_STRING, ParseTbl_ptr, ITEM_COMMENT, ITEM_INSTRUMENTATION, &idx)) != NULL) + { + /* Get Record */ + ParseRec_ptr = &ParseTbl_ptr->Data[idx]; + + /* Mark as Instrumentation */ + ParseRec_ptr->item_type |= ITEM_INSTRUMENTATION; + + ptr = ParseRec_ptr->item_end; + + /* check, if is followed by #ifdef or #endif statement */ + if ((idx = Find_Region(ptr, ParseTbl_ptr, ITEM_PREPROC_CMD | ITEM_PREPROC_COND)) > 0) + { + /* Get Record */ + ParseRec_ptr = &ParseTbl_ptr->Data[idx]; + + /* Mark as Instrumentation */ + ParseRec_ptr->item_type |= ITEM_INSTRUMENTATION; + + if (memwordcmp(ptr, "#if #ifdef #ifndef #elif") != NULL) + { + /* Get the next record - should be Preprocessor Directive Arguments */ + ParseRec_ptr = &ParseTbl_ptr->Data[idx + 1]; + + /* Mark as Instrumentation */ + ParseRec_ptr->item_type |= ITEM_INSTRUMENTATION; + } + + /* Advance pointer to the end of Preprocessor Arguments (Skip Spaces and Comments Only) */ + ptr = Skip_Chars(ParseRec_ptr->item_end, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_COMMENT); + } + } + + return ErrCode; } @@ -4769,7 +4809,7 @@ static TOOL_ERROR Instrument_Keywords( } } - /* Count Program Memory */ + ///* Count Program Memory */ //if ( item_type == ITEM_KEYWORD_FOR ) // loops++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->loop; //else if ( item_type == ITEM_KEYWORD_WHILE ) @@ -4779,7 +4819,8 @@ static TOOL_ERROR Instrument_Keywords( } /* Count Program Memory */ /* !!! VM: Moved to this place to count PROM size even for non-instrumented keywords */ - if ( Find_Region(ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED) < 0 ) + //if ( Find_Region(ParseRec_ptr->item_start, ParseTbl_ptr, ITEM_SKIPPED) < 0 ) + if (!IS_RESERVED_CHAR(*(ParseRec_ptr->item_start))) { if (item_type == ITEM_KEYWORD_FOR) loops++, ParseCtx_ptr->PROMSize += prom_ops_weights_ptr->loop; @@ -6462,13 +6503,46 @@ TOOL_ERROR Setup_Regions( ITEM_PREPROC_ARGS | ITEM_PREPROC_UNDEF, ITEM_ENCLOSED, &idx ) ) == NULL ) { /* No */ - /* Error - #undef WMC_TOOL_SKIP missing ! */ - ErrCode = ERR_EXPECTED_EOS; - Error("Unable to find matching #undef %s!", ErrCode, WMC_TOOL_SKIP_STRING); - goto ret; + ///* Error - #undef WMC_TOOL_SKIP missing ! */ + //ErrCode = ERR_EXPECTED_EOS; + //Error("Unable to find matching #undef %s!", ErrCode, WMC_TOOL_SKIP_STRING); + //goto ret; + + /* Go to EOF */ + end = file_ptr->Data + file_ptr->Size; + + /* Go back by skipping all lines preceded by AddedByWMC_Tool */ - /* Skipped Region will End at EOF */ - //end = file_ptr->Data + file_ptr->Size; + /* Go back to the beginning of the line */ + end = Skip_Chars(end, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + end = Goto_Chars(end, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + end++; + + /* Check, if line starts with "AddedByWMC_Tool */ + while (strncmp(end, ADDED_TOOL_INFO_STRING, strlen(ADDED_TOOL_INFO_STRING)) == 0) + { + /* Go back to the beginning of the previous line */ + end = Skip_Chars(end - 1, BLANK_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + end = Goto_Chars(end, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, BACKWARDS); + end++; + } + + /* Go to the end of the current line */ + end = Goto_Chars(end, EOL_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_NONE, FORWARD); + + if (end == NULL) + { + /* reached the end of file */ + end = file_ptr->Data + file_ptr->Size; + } + else if (IS_EOL_SEQ(end)) + { + end += 2; + } + else + { + end++; + } } else { /* Yes */ @@ -6483,7 +6557,7 @@ TOOL_ERROR Setup_Regions( } /* Add Non-Instrumented Region */ - if ( ( ErrCode = Add_Region( ParseTbl_ptr, ITEM_INSTRUMENTATION_OFF, ptr, end ) ) != NO_ERR ) + if ( ( ErrCode = Add_Region( ParseTbl_ptr, ITEM_SKIPPED | ITEM_INSTRUMENTATION_OFF, ptr, end ) ) != NO_ERR ) { goto ret; } @@ -7348,7 +7422,8 @@ TOOL_ERROR DesInstrument( *-------------------------------------------------------------------*/ TOOL_ERROR DesInstrument_ROM( - Parse_Context_def* ParseCtx_ptr) + Parse_Context_def* ParseCtx_ptr +) { TOOL_ERROR ErrCode = NO_ERR; @@ -7360,13 +7435,6 @@ TOOL_ERROR DesInstrument_ROM( start_const_data_prom_table = NULL; end_const_data_prom_table = NULL; - /* Check Previous State */ - if (ParseCtx_ptr->State != SETUP_OK) - { - ErrCode = Internal_Error(__FUNCTION__); - goto ret; - } - /* Set State Failure (by default) */ ParseCtx_ptr->State = DI_FAILED; @@ -7383,8 +7451,18 @@ TOOL_ERROR DesInstrument_ROM( start = ParseRec_ptr->item_start; tmp = ParseRec_ptr->item_end; + /* Instrumentation Code? E.g. 'AddedByWMC_Tool' */ + if (ParseRec_ptr->item_type & ITEM_FUNC_COUNTERS_AUTO && ((ParseRec_ptr->item_type & ITEM_FUNC_COUNTERS_MAN) == 0 || + Find_Region(start, ParseTbl_ptr, ITEM_INSTRUMENTATION_OFF) < 0)) + { /* Yes */ + if (!(ParseRec_ptr->item_type & ITEM_PREPROC_LINE)) + { + /* Delete it */ + Delete(start, tmp); + } + } /* Data Declaration? */ - if (ParseRec_ptr->item_type & ITEM_DATA_DECL) + else if (ParseRec_ptr->item_type & ITEM_DATA_DECL) { /* Yes */ /* Check if this is ROM_Size_Lookup_Table declaration */ @@ -7460,6 +7538,56 @@ TOOL_ERROR DesInstrument_ROM( ParseRec_ptr->item_type ^= ITEM_INSTRUMENTATION; } } + /* One of the 'Const_Data_Size_Func(...)' counting functions? */ + else if (ParseRec_ptr->item_type & ITEM_FUNC_DEF) + { /* Yes */ + /* Is function prototype or block followed by some blank chars? -> delete them as well */ + if (ParseRec_ptr->item_type & (ITEM_FUNC_PROTO | ITEM_FUNC_BLOCK)) + { + /* Skip all SPACE chars, if any */ + tmp = Skip_Chars(tmp, SPACE_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_COMMENT, FORWARD); + + /* Go past the EOL, if present */ + if (IS_EOL_SEQ(tmp)) + { + /* Two chars, in case of CR+LF */ + tmp += 2; + } + else if (IS_EOL_CHAR(*tmp)) + { + /* One char, if only LF */ + tmp++; + } + } + + /* Delete it */ + Delete(start, tmp); + + /* Desintrumenting Function Name? -> Check if it's preceded by 'extern int' or 'static int' return type */ + if (ParseRec_ptr->item_type & ITEM_FUNC_NAME) + { + /* Find the end of the preceding keyword */ + while ((tmp = Skip_Chars(start - 1, SPACE_CHARS, ParseTbl_ptr, ITEM_ANY, ITEM_MOVED_OVER, BACKWARDS)) != NULL && IS_IDENTIFIER_CHAR(*tmp)) + { + /* Find the beginning of the preceding keyword */ + start = Skip_Identifier(tmp, BACKWARDS) + 1; + + /* Check if the found keyword matches one of 'extern', 'static' or 'int' */ + if (memwordcmp(start, STORAGE_STRING) || memwordcmp(start, INT_STRING)) + { /* Yes */ + /* Delete it */ + Delete(start, tmp + 2); + } + } + } + + /* Item is no Longer a Function Name/Proto/Block */ + ParseRec_ptr->item_type &= ~ITEM_FUNC_DEF; + + /* Item is no Longer Instrumentation */ + ParseRec_ptr->item_type ^= ITEM_INSTRUMENTATION; + } + } /* Find the print_mem() function */ @@ -7489,7 +7617,7 @@ TOOL_ERROR DesInstrument_ROM( /* Set State Success */ ParseCtx_ptr->State = DESINSTRUMENTED; -ret: +//ret: return ErrCode; } From c6c45955b75bc0efee72701d060286a75145c642 Mon Sep 17 00:00:00 2001 From: malenov Date: Mon, 29 Jul 2024 15:17:19 +0200 Subject: [PATCH 61/67] call DesInstrument_ROM() for regular files as well --- src/wmc_tool/wmc_tool.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/wmc_tool/wmc_tool.cpp b/src/wmc_tool/wmc_tool.cpp index 097d8d4..59ef6fa 100644 --- a/src/wmc_tool/wmc_tool.cpp +++ b/src/wmc_tool/wmc_tool.cpp @@ -995,6 +995,13 @@ static TOOL_ERROR Process_File( return ErrCode; } + /* DesInstrument Const_Data_Size_XXX Functions */ + if ( ( ErrCode = DesInstrument_ROM( ParseCtx_ptr ) ) != NO_ERR ) + { + fprintf(stdout, "\n"); + return ErrCode; + } + /* Instrument */ if ( !( Operation & DESINSTRUMENT_ONLY ) ) { /* Yes */ @@ -1160,6 +1167,7 @@ int main( int argc, char *argv[] ) char Const_Data_PROM_File[MAX_PATH] = ""; char wmops_output_dir[MAX_PATH]; float frames_per_sec; + bool Const_Data_PROM_File_already_reinstrumented = 0; T_FILE_BOOK file_book[MAX_RECORDS]; struct stat s; Parse_Context_def ParseContext; @@ -1434,6 +1442,12 @@ int main( int argc, char *argv[] ) /* Process File */ ErrCode = Process_File(LongFileName, Operation, &ParseContext, MaxFnLength, (Operation & NO_BACKUP) == 0, j * 100.0f / file_book[i].nFiles); + /* Check if the processed file is the same as */ + if (strcmp(LongFileName, Const_Data_PROM_File) == 0) + { + Const_Data_PROM_File_already_reinstrumented = 1; + } + /* Update # of Bytes Processed */ nBytesProcessed += ParseContext.File.Size; @@ -1526,10 +1540,13 @@ int main( int argc, char *argv[] ) goto ret; } - /* DesInstrument Const_Data_Size_XXX Functions */ - if ((ErrCode = DesInstrument_ROM(&ParseContext)) != NO_ERR) + /* DesInstrument Const_Data_PROM_Table[] */ + if (!Const_Data_PROM_File_already_reinstrumented) { - goto ret; + if ((ErrCode = DesInstrument_ROM(&ParseContext)) != NO_ERR) + { + goto ret; + } } /* Check, if "wmc_auto.h" is included */ From 32845f7e92e163d8cfca1648bcb15da15365aa3f Mon Sep 17 00:00:00 2001 From: malenov Date: Mon, 29 Jul 2024 15:30:20 +0200 Subject: [PATCH 62/67] add documentation of changes for v1.6 --- src/wmc_tool/HISTORY.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/wmc_tool/HISTORY.md b/src/wmc_tool/HISTORY.md index 988cc26..f2f43e3 100644 --- a/src/wmc_tool/HISTORY.md +++ b/src/wmc_tool/HISTORY.md @@ -70,4 +70,10 @@ ## v1.5.1 * added the -s (--skip_cmplx_instrumentation) command-line option, which avoids the instrumentation of function bodies. The func_start_ and return_ keywords, along with the remaining functionality, remain unchanged. + +## v1.6 + + * fixed instrumentation issues in encoder.c of the 3GPP EVS codec where malloc() is instrumented and print_mem() is present as well + * when #undef WMC_TOOL_SKIP is missing, automatically assume end of file, but before the last automatically instrumented segment + * the function DesInstrument_ROM() is called in all regular files as well as the file pointed to with the -m command-line argument \ No newline at end of file From 06607ad61d63bd693c1fb53abfacbc79e37dafd4 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 3 Dec 2024 15:53:41 +0100 Subject: [PATCH 63/67] major udate of BASOP operators, corrections to the BASOP complexity counting mechanism --- src/wmc_tool/wmc_auto_c.txt | 4701 +++++++++++++++++++---------------- src/wmc_tool/wmc_auto_h.txt | 2680 +++++++++----------- 2 files changed, 3761 insertions(+), 3620 deletions(-) diff --git a/src/wmc_tool/wmc_auto_c.txt b/src/wmc_tool/wmc_auto_c.txt index 1b3b85e..0f64019 100644 --- a/src/wmc_tool/wmc_auto_c.txt +++ b/src/wmc_tool/wmc_auto_c.txt @@ -1,2172 +1,2529 @@ -"/*\r\n", -" * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved.\r\n", -" *\r\n", -" * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n", -" * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n", -" * or refer to ITU-T Recommendation G.191 on \"SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS\".\r\n", -" *\r\n", -" * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor\r\n", -" * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software\r\n", -" * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE.\r\n", -" *\r\n", -" * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca)\r\n", -" */\r\n", -"\r\n", -"#include \r\n", -"#include \r\n", -"#include \r\n", -"#include \r\n", -"#include \r\n", -"\r\n", -"#ifndef _MSC_VER\r\n", -"#include \r\n", -"#include \r\n", -"#else\r\n", -"#include \r\n", -"#endif\r\n", -"\r\n", -"#include \"options.h\"\r\n", -"#include \"wmc_auto.h\"\r\n", -"\r\n", -"#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */\r\n", -"\r\n", -"#ifdef WMOPS\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * Complexity counting tool\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"#define MAX_FUNCTION_NAME_LENGTH 50 /* Maximum length of the function name */\r\n", -"#define MAX_PARAMS_LENGTH 50 /* Maximum length of the function parameter string */\r\n", -"#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> mightb be increased during runtime, if needed */\r\n", -"#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */\r\n", -"#define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */\r\n", -"#define DOUBLE_MAX 0x80000000\r\n", -"#define FAC ( FRAMES_PER_SECOND / 1e6 )\r\n", -"\r\n", -"\r\n", -"typedef struct \r\n", -"{\r\n", -" char label[MAX_FUNCTION_NAME_LENGTH];\r\n", -" long call_number;\r\n", -" long update_cnt;\r\n", -" int call_tree[MAX_CALL_TREE_DEPTH];\r\n", -" long LastWOper;\r\n", -" double start_selfcnt;\r\n", -" double current_selfcnt;\r\n", -" double max_selfcnt;\r\n", -" double min_selfcnt;\r\n", -" double tot_selfcnt;\r\n", -" double start_cnt; \r\n", -" double current_cnt;\r\n", -" double max_cnt;\r\n", -" double min_cnt;\r\n", -" double tot_cnt;\r\n", -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", -" int32_t current_call_number;\r\n", -" double wc_cnt;\r\n", -" double wc_selfcnt;\r\n", -" int32_t wc_call_number;\r\n", -"#endif\r\n", -"} wmops_record;\r\n", -"\r\n", -"double ops_cnt;\r\n", -"double prom_cnt;\r\n", -"double inst_cnt[NUM_INST];\r\n", -"\r\n", -"static wmops_record *wmops = NULL;\r\n", -"static int num_wmops_records, max_num_wmops_records;\r\n", -"static int current_record;\r\n", -"static long update_cnt;\r\n", -"static double start_cnt;\r\n", -"static double max_cnt;\r\n", -"static double min_cnt;\r\n", -"static double inst_cnt_wc[NUM_INST];\r\n", -"static long fnum_cnt_wc;\r\n", -"static int *wmops_caller_stack = NULL, wmops_caller_stack_index, max_wmops_caller_stack_index = 0;\r\n", -"static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0;\r\n", -"\r\n", -"void reset_wmops( void )\r\n", -"{\r\n", -" int i, j;\r\n", -" unsigned int *ptr;\r\n", -"\r\n", -" num_wmops_records = 0;\r\n", -" max_num_wmops_records = MAX_NUM_RECORDS;\r\n", -" current_record = -1;\r\n", -" update_cnt = 0;\r\n", -"\r\n", -" max_cnt = 0.0;\r\n", -" min_cnt = DOUBLE_MAX;\r\n", -" start_cnt = 0.0;\r\n", -" ops_cnt = 0.0;\r\n", -"\r\n", -" /* allocate the list of wmops records */\r\n", -" if ( wmops == NULL )\r\n", -" {\r\n", -" wmops = (wmops_record *)malloc( max_num_wmops_records * sizeof( wmops_record ) );\r\n", -" }\r\n", -"\r\n", -" if ( wmops == NULL )\r\n", -" {\r\n", -" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Records!\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" /* allocate the BASOP WMOPS counter */\r\n", -" if ( multiCounter == NULL )\r\n", -" {\r\n", -" multiCounter = (BASIC_OP *) malloc( max_num_wmops_records * sizeof( BASIC_OP ) );\r\n", -" }\r\n", -"\r\n", -" if ( multiCounter == NULL )\r\n", -" {\r\n", -" fprintf( stderr, \"Error: Unable to Allocate the BASOP WMOPS counter!\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" /* initilize the list of wmops records */\r\n", -" /* initilize the BASOP WMOPS counters */\r\n", -" for ( i = 0; i < max_num_wmops_records; i++ )\r\n", -" {\r\n", -" strcpy( &wmops[i].label[0], \"\\0\" );\r\n", -" wmops[i].call_number = 0;\r\n", -" wmops[i].update_cnt = 0;\r\n", -" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n", -" {\r\n", -" wmops[i].call_tree[j] = -1;\r\n", -" }\r\n", -" wmops[i].start_selfcnt = 0.0;\r\n", -" wmops[i].current_selfcnt = 0.0;\r\n", -" wmops[i].max_selfcnt = 0.0;\r\n", -" wmops[i].min_selfcnt = DOUBLE_MAX;\r\n", -" wmops[i].tot_selfcnt = 0.0;\r\n", -" wmops[i].start_cnt = 0.0;\r\n", -" wmops[i].current_cnt = 0.0;\r\n", -" wmops[i].max_cnt = 0.0;\r\n", -" wmops[i].min_cnt = DOUBLE_MAX;\r\n", -" wmops[i].tot_cnt = 0.0;\r\n", -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", -" wmops[i].wc_cnt = 0.0;\r\n", -" wmops[i].wc_selfcnt = 0.0;\r\n", -" wmops[i].current_call_number = 0;\r\n", -" wmops[i].wc_call_number = -1;\r\n", -"#endif\r\n", -"\r\n", -" /* clear all BASOP operation counters */\r\n", -" ptr = (unsigned int*) &multiCounter[i];\r\n", -" for ( j = 0; j < (int) ( sizeof(BASIC_OP ) / sizeof( unsigned int ) ); j++ )\r\n", -" {\r\n", -" *ptr++ = 0;\r\n", -" }\r\n", -" wmops[i].LastWOper = 0;\r\n", -" }\r\n", -"\r\n", -" /* allocate the list of wmops callers to track the sequence of function calls */\r\n", -" wmops_caller_stack_index = 0;\r\n", -" max_wmops_caller_stack_index = MAX_NUM_RECORDS;\r\n", -" if ( wmops_caller_stack == NULL )\r\n", -" {\r\n", -" wmops_caller_stack = malloc( max_wmops_caller_stack_index * sizeof( int ) );\r\n", -" }\r\n", -"\r\n", -" if ( wmops_caller_stack == NULL )\r\n", -" {\r\n", -" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Callers!\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" for ( i = 0; i < max_wmops_caller_stack_index; i++ )\r\n", -" {\r\n", -" wmops_caller_stack[i] = -1;\r\n", -" }\r\n", -"\r\n", -" /* initialize auxiliary BASOP WMOPS variables */\r\n", -" call_occurred = 1;\r\n", -" funcId_where_last_call_to_else_occurred = INT_MAX;\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"\r\n", -"void push_wmops( const char *label )\r\n", -"{\r\n", -" int new_flag;\r\n", -" int i, j;\r\n", -"\r\n", -" /* Check, if this is a new function label */\r\n", -" new_flag = 1;\r\n", -" for ( i = 0; i < num_wmops_records; i++ )\r\n", -" {\r\n", -" if ( strcmp( wmops[i].label, label ) == 0 )\r\n", -" {\r\n", -" new_flag = 0;\r\n", -" break;\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* Create a new record in the list */\r\n", -" if ( new_flag )\r\n", -" {\r\n", -" if ( num_wmops_records >= max_num_wmops_records )\r\n", -" {\r\n", -" /* There is no room for a new wmops record -> reallocate the list */\r\n", -" max_num_wmops_records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", -" wmops = realloc( wmops, max_num_wmops_records * sizeof( wmops_record ) );\r\n", -" multiCounter = realloc( multiCounter, max_num_wmops_records * sizeof( BASIC_OP ) );\r\n", -" }\r\n", -"\r\n", -" strcpy( wmops[i].label, label );\r\n", -"\r\n", -" num_wmops_records++;\r\n", -" }\r\n", -"\r\n", -" /* Push the current context info to the new record */\r\n", -" if ( current_record >= 0 )\r\n", -" {\r\n", -" if ( wmops_caller_stack_index >= max_wmops_caller_stack_index )\r\n", -" {\r\n", -" /* There is no room for a new record -> reallocate the list */\r\n", -" max_wmops_caller_stack_index += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", -" wmops_caller_stack = realloc( wmops_caller_stack, max_wmops_caller_stack_index * sizeof( int ) );\r\n", -" }\r\n", -" wmops_caller_stack[wmops_caller_stack_index++] = current_record;\r\n", -"\r\n", -" /* accumulate op counts */\r\n", -" wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n", -"\r\n", -" /* update call tree */\r\n", -" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n", -" {\r\n", -" if ( wmops[i].call_tree[j] == current_record )\r\n", -" {\r\n", -" break;\r\n", -" }\r\n", -" else if ( wmops[i].call_tree[j] == -1 )\r\n", -" {\r\n", -" wmops[i].call_tree[j] = current_record;\r\n", -" break;\r\n", -" }\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* update the current context info */\r\n", -" current_record = i;\r\n", -" wmops[current_record].start_selfcnt = ops_cnt;\r\n", -" wmops[current_record].start_cnt = ops_cnt;\r\n", -" wmops[current_record].call_number++;\r\n", -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", -" wmops[current_record].current_call_number++;\r\n", -"#endif\r\n", -"\r\n", -" /* set the ID of BASOP functions counters */\r\n", -" Set_BASOP_WMOPS_counter( current_record );\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"\r\n", -"void pop_wmops( void )\r\n", -"{\r\n", -" long tot;\r\n", -"\r\n", -" /* Check for underflow */\r\n", -" if ( current_record < 0 )\r\n", -" {\r\n", -" fprintf( stdout, \"\\r pop_wmops(): stack underflow, too many calls to pop_wmops()\\n\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" /* add the BASOP complexity to the counter */\r\n", -" tot = DeltaWeightedOperation();\r\n", -" ops_cnt += tot;\r\n", -"\r\n", -" /* update count of current record */\r\n", -" wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n", -" wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt;\r\n", -"\r\n", -" /* Get back previous context from stack */\r\n", -" if ( wmops_caller_stack_index > 0 )\r\n", -" {\r\n", -" current_record = wmops_caller_stack[--wmops_caller_stack_index];\r\n", -" wmops[current_record].start_selfcnt = ops_cnt;\r\n", -"\r\n", -" /* set the ID of the previous BASOP counter */\r\n", -" Set_BASOP_WMOPS_counter( current_record );\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" current_record = -1;\r\n", -" }\r\n", -"\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"\r\n", -"void update_wmops( void )\r\n", -"{\r\n", -" int i;\r\n", -" double current_cnt;\r\n", -"#ifdef WMOPS_PER_FRAME\r\n", -" static FILE *fid = NULL;\r\n", -" const char filename[] = \"wmops_analysis\";\r\n", -" float tmpF;\r\n", -"#endif\r\n", -"\r\n", -" if ( wmops_caller_stack_index != 0 )\r\n", -" {\r\n", -" fprintf( stdout, \"update_wmops(): WMOPS caller stack corrupted - check that all push_wmops() are matched with pop_wmops()!\\n\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -"#ifdef WMOPS_PER_FRAME\r\n", -" /* Check, if the output file has already been opened */\r\n", -" if ( fid == NULL )\r\n", -" {\r\n", -" fid = fopen( filename, \"wb\" );\r\n", -"\r\n", -" if ( fid == NULL )\r\n", -" {\r\n", -" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", filename );\r\n", -" exit( -1 );\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* Write current complexity to the external file */\r\n", -" tmpF = (float) ( FAC * wmops[0].current_cnt );\r\n", -" fwrite( &tmpF, sizeof( float ), 1, fid );\r\n", -"#endif\r\n", -"\r\n", -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", -" if ( ops_cnt - start_cnt > max_cnt )\r\n", -" {\r\n", -" for ( i = 0; i < num_wmops_records; i++ )\r\n", -" {\r\n", -" wmops[i].wc_cnt = wmops[i].current_cnt;\r\n", -" wmops[i].wc_selfcnt = wmops[i].current_selfcnt;\r\n", -" wmops[i].wc_call_number = wmops[i].current_call_number;\r\n", -" }\r\n", -" }\r\n", -"#endif\r\n", -"\r\n", -" for ( i = 0; i < num_wmops_records; i++ )\r\n", -" {\r\n", -" wmops[i].tot_selfcnt += wmops[i].current_selfcnt;\r\n", -" wmops[i].tot_cnt += wmops[i].current_cnt;\r\n", -"\r\n", -" if ( wmops[i].current_selfcnt > 0 )\r\n", -" {\r\n", -" if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt )\r\n", -" {\r\n", -" wmops[i].max_selfcnt = wmops[i].current_selfcnt;\r\n", -" }\r\n", -"\r\n", -" if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt )\r\n", -" {\r\n", -" wmops[i].min_selfcnt = wmops[i].current_selfcnt;\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" wmops[i].current_selfcnt = 0;\r\n", -"\r\n", -" if ( wmops[i].current_cnt > 0 )\r\n", -" {\r\n", -" if ( wmops[i].current_cnt > wmops[i].max_cnt )\r\n", -" {\r\n", -" wmops[i].max_cnt = wmops[i].current_cnt;\r\n", -" }\r\n", -"\r\n", -"\r\n", -" if ( wmops[i].current_cnt < wmops[i].min_cnt )\r\n", -" {\r\n", -" wmops[i].min_cnt = wmops[i].current_cnt;\r\n", -" }\r\n", -"\r\n", -" wmops[i].update_cnt++;\r\n", -" }\r\n", -"\r\n", -" wmops[i].current_cnt = 0;\r\n", -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", -" wmops[i].current_call_number = 0;\r\n", -"#endif\r\n", -"\r\n", -" /* update the WC of all BASOP counters */\r\n", -" Set_BASOP_WMOPS_counter( i );\r\n", -" Reset_BASOP_WMOPS_counter();\r\n", -" }\r\n", -"\r\n", -" current_cnt = ops_cnt - start_cnt;\r\n", -" if ( current_cnt > max_cnt )\r\n", -" {\r\n", -" max_cnt = current_cnt;\r\n", -"\r\n", -" for ( i = 0; i < NUM_INST; i++ )\r\n", -" {\r\n", -" inst_cnt_wc[i] = inst_cnt[i];\r\n", -" }\r\n", -"\r\n", -" fnum_cnt_wc = update_cnt + 1;\r\n", -" }\r\n", -"\r\n", -" if ( current_cnt < min_cnt )\r\n", -" {\r\n", -" min_cnt = current_cnt;\r\n", -" }\r\n", -"\r\n", -" for ( i = 0; i < NUM_INST; i++ )\r\n", -" {\r\n", -" inst_cnt[i] = 0.0;\r\n", -" }\r\n", -"\r\n", -" start_cnt = ops_cnt;\r\n", -"\r\n", -" /* increment frame counter */\r\n", -" update_cnt++;\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"\r\n", -"void print_wmops( void )\r\n", -"{\r\n", -" int i, label_len, max_label_len;\r\n", -"\r\n", -" char *sfmts = \"%*s %8s %8s %7s %7s\\n\";\r\n", -" char *dfmts = \"%*s %8.2f %8.3f %7.3f %7.3f\\n\";\r\n", -" char *sfmt = \"%*s %8s %8s %7s %7s %7s %7s %7s\\n\";\r\n", -" char *dfmt = \"%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\\n\";\r\n", -"\r\n", -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", -" int j;\r\n", -" char *sfmtt = \"%20s %4s %15s\\n\";\r\n", -" char *dfmtt = \"%20s %4d \";\r\n", -"#endif\r\n", -"\r\n", -" /* calculate maximum label length for compact prinout */\r\n", -" max_label_len = 0;\r\n", -" for ( i = 0; i < num_wmops_records; i++ )\r\n", -" {\r\n", -" label_len = strlen( wmops[i].label );\r\n", -" if ( label_len > max_label_len )\r\n", -" {\r\n", -" max_label_len = label_len;\r\n", -" }\r\n", -" }\r\n", -" max_label_len += 4;\r\n", -"\r\n", -" fprintf( stdout, \"\\n\\n --- Complexity analysis [WMOPS] --- \\n\\n\" );\r\n", -" \r\n", -" fprintf( stdout, \"%*s %33s %23s\\n\", max_label_len, \"\", \"|------ SELF ------|\", \"|--- CUMULATIVE ---|\" );\r\n", -" fprintf( stdout, sfmt, max_label_len, \" routine\", \" calls\", \" min \", \" max \", \" avg \", \" min \", \" max \", \" avg \" );\r\n", -" fprintf( stdout, sfmt, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\" );\r\n", -"\r\n", -" for ( i = 0; i < num_wmops_records; i++ )\r\n", -" {\r\n", -" fprintf( stdout, dfmt, max_label_len, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt,\r\n", -" wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt,\r\n", -" FAC * wmops[i].max_selfcnt,\r\n", -" wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt,\r\n", -" wmops[i].min_cnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_cnt,\r\n", -" FAC * wmops[i].max_cnt,\r\n", -" wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt );\r\n", -" }\r\n", -"\r\n", -" fprintf( stdout, sfmts, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\" );\r\n", -" fprintf( stdout, dfmts, max_label_len, \"total\", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt );\r\n", -" fprintf( stdout, \"\\n\" );\r\n", -"\r\n", -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", -" fprintf( stdout, \"\\nComplexity analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n", -" fprintf( stdout, \"%*s %8s %10s %12s\\n\", max_label_len, \" routine\", \" calls\", \" SELF\", \" CUMULATIVE\" );\r\n", -" fprintf( stdout, \"%*s %8s %10s %10s\\n\", max_label_len, \"---------------\", \"------\", \"------\", \"----------\" );\r\n", -"\r\n", -" for ( i = 0; i < num_wmops_records; i++ )\r\n", -" {\r\n", -" if ( wmops[i].wc_call_number > 0 )\r\n", -" {\r\n", -" fprintf( stdout, \"%*s %8d %10.3f %12.3f\\n\", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt );\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" fprintf( stdout, \"\\nCall tree for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n", -" fprintf( stdout, sfmtt, \" function\", \"num\", \"called by \" );\r\n", -" fprintf( stdout, sfmtt, \"---------------\", \"---\", \"--------------\" );\r\n", -"\r\n", -" for ( i = 0; i < num_wmops_records; i++ )\r\n", -" {\r\n", -" if ( wmops[i].wc_call_number > 0 )\r\n", -" {\r\n", -" fprintf( stdout, dfmtt, wmops[i].label, i );\r\n", -" for ( j = 0; wmops[i].call_tree[j] != -1 && j < MAX_CALL_TREE_DEPTH; j++ )\r\n", -" {\r\n", -" if ( j != 0 )\r\n", -" {\r\n", -" fprintf( stdout, \", \" );\r\n", -" }\r\n", -" fprintf( stdout, \"%d\", wmops[i].call_tree[j] );\r\n", -" }\r\n", -" fprintf( stdout, \"\\n\" );\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" fprintf( stdout, \"\\n\\n\" );\r\n", -"\r\n", -" fprintf( stdout, \"\\nInstruction type analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc ); \r\n", -" for ( i = 0; i < NUM_INST; i++ )\r\n", -" {\r\n", -" switch ( (enum instructions) i )\r\n", -" {\r\n", -" case _ADD:\r\n", -" fprintf( stdout, \"\\tAdds: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _ABS:\r\n", -" fprintf( stdout, \"\\tAbsolutes: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _MULT:\r\n", -" fprintf( stdout, \"\\tMultiplies: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _MAC:\r\n", -" fprintf( stdout, \"\\tMACs: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _MOVE:\r\n", -" fprintf( stdout, \"\\tMoves: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _STORE:\r\n", -" fprintf( stdout, \"\\tStores: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _LOGIC:\r\n", -" fprintf( stdout, \"\\tLogicals: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _SHIFT:\r\n", -" fprintf( stdout, \"\\tShifts: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _BRANCH:\r\n", -" fprintf( stdout, \"\\tBranches: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _DIV:\r\n", -" fprintf( stdout, \"\\tDivisions: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _SQRT:\r\n", -" fprintf( stdout, \"\\tSquare Root: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _TRANS:\r\n", -" fprintf( stdout, \"\\tTrans: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _FUNC:\r\n", -" fprintf( stdout, \"\\tFunc Call: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _LOOP:\r\n", -" fprintf( stdout, \"\\tLoop Init: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _INDIRECT:\r\n", -" fprintf( stdout, \"\\tIndirect Addr: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _PTR_INIT:\r\n", -" fprintf( stdout, \"\\tPointer Init: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _TEST:\r\n", -" fprintf( stdout, \"\\tExtra condit.: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _POWER:\r\n", -" fprintf( stdout, \"\\tExponential: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _LOG:\r\n", -" fprintf( stdout, \"\\tLogarithm: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" case _MISC:\r\n", -" fprintf( stdout, \"\\tAll other op.: %12.1f\\n\", inst_cnt_wc[i] );\r\n", -" break;\r\n", -" default:\r\n", -" fprintf( stdout, \"\\tERROR: Invalid instruction type: %d\\n\\n\", i );\r\n", -" }\r\n", -" }\r\n", -"#endif\r\n", -"\r\n", -" /* De-allocate the list of wmops record */\r\n", -" if ( wmops != NULL )\r\n", -" {\r\n", -" free( wmops );\r\n", -" }\r\n", -"\r\n", -" /* De-allocate the list of wmops caller functions */\r\n", -" if ( wmops_caller_stack != NULL )\r\n", -" {\r\n", -" free( wmops_caller_stack );\r\n", -" }\r\n", -"\r\n", -" /* De-allocate the BASOP WMOPS counter */\r\n", -" if ( multiCounter != NULL )\r\n", -" {\r\n", -" free( multiCounter );\r\n", -" }\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * Memory counting tool measuring RAM usage (stack and heap)\r\n", -" *\r\n", -" * Maximum RAM is measured by monitoring the total allocated memory (stack and heap) in each frame.\r\n", -" *\r\n", -" * Maximum stack is measured by monitoring the difference between the 'top' and 'bottom' of the stack. The 'bottom' of the stack is updated in each function\r\n", -" * with a macro 'func_start_' which is inserted automatically to all functions during the instrumentation process.\r\n", -" *\r\n", -" * Maximum heap is measured by summing the sizes of all memory blocks allocated by malloc() or calloc() and deallocated by free(). The maximum heap size is\r\n", -" * updated each time when the macros malloc_() or calloc_() is invoked. The macros 'malloc_ and calloc_' are inserted automatically during the instrumentation process.\r\n", -" * As part of heap measurements, intra-frame heap and inter-frame heap are measured separately. Intra-frame heap refers to heap memory which is allocated and deallocated\r\n", -" * within a single frame. Inter-frame heap, on the contrary, refers to heap memory which is reserved for more than one frame.\r\n", -" *\r\n", -" * In order to run the memory counting tool the function reset_mem(cnt_size) must be called at the beginning of the encoding/decoding process.\r\n", -" * The unit in which memory consumption is reported is set via the parameter 'cnt_size'. It can be set to 0 (bytes), 1 (32b words) or 2 (64b words).\r\n", -" * At the end of the encoding/decoding process, 'print_mem()' function may be called to print basic information about memory consumption. If the macro 'MEM_COUNT_DETAILS'\r\n", -" * is activated, detailed information is printed\r\n", -" *\r\n", -" * The macro 'WMOPS' needs to be activated to enable memory counting. To avoid the instrumentation of malloc()/calloc()/free() calls, use\r\n", -" * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free().\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using\r\n", -" a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */\r\n", -"#ifdef MEM_ALIGN_64BITS\r\n", -"#define BLOCK_ROUNDING 8 /* Align on 64 Bits */\r\n", -"#else\r\n", -"#define BLOCK_ROUNDING 4 /* Align on 32 Bits */\r\n", -"#endif\r\n", -"\r\n", -"#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) )\r\n", -"#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) )\r\n", -"\r\n", -"#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */\r\n", -"#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */\r\n", -"#define OOB_START 0x1 /* Flag indicating out-of-bounds access before memory block */\r\n", -"#define OOB_END 0x2 /* Flag indicating out-of-bounds access after memory block */\r\n", -"\r\n", -"#ifdef MEM_COUNT_DETAILS\r\n", -"const char *csv_filename = \"mem_analysis.csv\";\r\n", -"static FILE *fid_csv_filename = NULL;\r\n", -"#endif\r\n", -"\r\n", -"typedef struct\r\n", -"{\r\n", -" char function_name[MAX_FUNCTION_NAME_LENGTH + 1];\r\n", -" int16_t *stack_ptr;\r\n", -"} caller_info;\r\n", -"\r\n", -"static caller_info *stack_callers[2] = {NULL, NULL};\r\n", -"\r\n", -"static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */\r\n", -"static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */\r\n", -"static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */\r\n", -"static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */\r\n", -"static int current_calls = 0, max_num_calls = MAX_NUM_RECORDS;\r\n", -"static char location_max_stack[256] = \"undefined\";\r\n", -"\r\n", -"/* Heap-related variables */\r\n", -"typedef struct\r\n", -"{\r\n", -" char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */\r\n", -" char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */\r\n", -" unsigned long hash;\r\n", -" int lineno;\r\n", -" void *block_ptr;\r\n", -" int block_size;\r\n", -" unsigned long total_block_size; /* Cumulative sum of the allocated size in the session */\r\n", -" unsigned long total_used_size; /* Cumulative sum of the used size in the session */\r\n", -" int wc_heap_size_intra_frame; /* Worst-Case Intra-Frame Heap Size */\r\n", -" int wc_heap_size_inter_frame; /* Worst-Case Inter-Frame Heap Size */\r\n", -" int frame_allocated; /* Frame number in which the Memory Block has been allocated (-1 if not allocated at the moment) */\r\n", -" int OOB_Flag;\r\n", -" int noccurances; /* Number of times that the memory block has been allocated in a frame */\r\n", -"} allocator_record;\r\n", -"\r\n", -"allocator_record *allocation_list = NULL;\r\n", -"\r\n", -"static int Num_Records, Max_Num_Records;\r\n", -"static size_t Stat_Cnt_Size = USE_BYTES;\r\n", -"static const char *Count_Unit[] = { \"bytes\", \"words\", \"words\", \"words\" };\r\n", -"\r\n", -"static int32_t wc_ram_size, wc_ram_frame;\r\n", -"static int32_t current_heap_size;\r\n", -"static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap;\r\n", -"static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap;\r\n", -"static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap;\r\n", -"\r\n", -"/* Local Functions */\r\n", -"static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str );\r\n", -"allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record );\r\n", -"static void *mem_alloc_block( size_t size, const char *size_str );\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * reset_mem()\r\n", -" *\r\n", -" * Initialize/reset memory counting tool (stack and heap)\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"void reset_mem( Counting_Size cnt_size )\r\n", -"{\r\n", -" int16_t something;\r\n", -" size_t tmp_size;\r\n", -"\r\n", -" /* initialize list of stack records */\r\n", -" if ( stack_callers[0] == NULL )\r\n", -" {\r\n", -" stack_callers[0] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n", -" stack_callers[1] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n", -" }\r\n", -"\r\n", -" if ( stack_callers[0] == NULL || stack_callers[1] == NULL )\r\n", -" {\r\n", -" fprintf( stderr, \"Error: Unable to Allocate List of Stack Records!\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" current_calls = 0;\r\n", -" max_num_calls = MAX_NUM_RECORDS;\r\n", -"\r\n", -" /* initialize stack pointers */\r\n", -" ptr_base_stack = &something;\r\n", -" ptr_max_stack = ptr_base_stack;\r\n", -" ptr_current_stack = ptr_base_stack;\r\n", -"\r\n", -" /* initialize the unit of memory block size */\r\n", -" Stat_Cnt_Size = cnt_size;\r\n", -"\r\n", -" /* Check, if sizeof(int32_t) is 4 bytes */\r\n", -" tmp_size = sizeof( int32_t );\r\n", -" if ( tmp_size != 4 )\r\n", -" {\r\n", -" fprintf( stderr, \"Error: Expecting 'int32_t' to be a 32 Bits Integer!\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" /* create allocation list for malloc() memory blocks */\r\n", -" if ( allocation_list == NULL )\r\n", -" {\r\n", -" allocation_list = malloc( MAX_NUM_RECORDS * sizeof( allocator_record ) );\r\n", -" }\r\n", -"\r\n", -" if ( allocation_list == NULL )\r\n", -" {\r\n", -" fprintf( stderr, \"Error: Unable to Create List of Memory Blocks!\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" Num_Records = 0;\r\n", -" Max_Num_Records = MAX_NUM_RECORDS;\r\n", -"\r\n", -" wc_ram_size = 0;\r\n", -" wc_ram_frame = -1;\r\n", -" current_heap_size = 0;\r\n", -"\r\n", -" /* heap allocation tree */\r\n", -" heap_allocation_call_tree_max_size = MAX_NUM_RECORDS;\r\n", -" if ( heap_allocation_call_tree == NULL )\r\n", -" {\r\n", -" heap_allocation_call_tree = (int *) malloc( heap_allocation_call_tree_max_size * sizeof( int ) );\r\n", -" memset( heap_allocation_call_tree, -1, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n", -" }\r\n", -" heap_allocation_call_tree_size = 0;\r\n", -"\r\n", -" /* wc intra-frame heap */\r\n", -" max_items_wc_intra_frame_heap = MAX_NUM_RECORDS;\r\n", -" if ( list_wc_intra_frame_heap == NULL )\r\n", -" {\r\n", -" list_wc_intra_frame_heap = (int *) malloc( max_items_wc_intra_frame_heap * sizeof( int ) );\r\n", -" memset( list_wc_intra_frame_heap, -1, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n", -" }\r\n", -" n_items_wc_intra_frame_heap = 0;\r\n", -" size_wc_intra_frame_heap = 0;\r\n", -" location_wc_intra_frame_heap = -1;\r\n", -"\r\n", -" /* current inter-frame heap */\r\n", -" max_items_current_inter_frame_heap = MAX_NUM_RECORDS;\r\n", -" if ( list_current_inter_frame_heap == NULL )\r\n", -" {\r\n", -" list_current_inter_frame_heap = (int *) malloc( max_items_current_inter_frame_heap * sizeof( int ) );\r\n", -" memset( list_current_inter_frame_heap, -1, max_items_current_inter_frame_heap * sizeof( int ) );\r\n", -" }\r\n", -" n_items_current_inter_frame_heap = 0;\r\n", -" size_current_inter_frame_heap = 0;\r\n", -"\r\n", -" /* wc inter-frame heap */\r\n", -" max_items_wc_inter_frame_heap = MAX_NUM_RECORDS;\r\n", -" if ( list_wc_inter_frame_heap == NULL )\r\n", -" {\r\n", -" list_wc_inter_frame_heap = (int *) malloc( max_items_wc_inter_frame_heap * sizeof( int ) );\r\n", -" memset( list_wc_inter_frame_heap, -1, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n", -" }\r\n", -" n_items_wc_inter_frame_heap = 0;\r\n", -" size_wc_inter_frame_heap = 0;\r\n", -" location_wc_inter_frame_heap = -1;\r\n", -"\r\n", -"#ifdef MEM_COUNT_DETAILS\r\n", -" /* Check, if the .csv file has already been opened */\r\n", -" if ( fid_csv_filename == NULL )\r\n", -" {\r\n", -" fid_csv_filename = fopen( csv_filename, \"wb\" );\r\n", -"\r\n", -" if ( fid_csv_filename == NULL )\r\n", -" {\r\n", -" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", csv_filename );\r\n", -" exit( -1 );\r\n", -" }\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" /* reset file */\r\n", -" rewind( fid_csv_filename );\r\n", -" }\r\n", -"#endif\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * reset_stack()\r\n", -" *\r\n", -" * Reset stack pointer\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"void reset_stack( void )\r\n", -"{\r\n", -" int16_t something;\r\n", -"\r\n", -" /* initialize/reset stack pointers */\r\n", -" ptr_base_stack = &something;\r\n", -" ptr_max_stack = ptr_base_stack;\r\n", -" ptr_current_stack = ptr_base_stack;\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * push_stack()\r\n", -" *\r\n", -" * Check the current stack pointer and update the maximum stack pointer, if new maximum found.\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"int push_stack( const char *filename, const char *fctname )\r\n", -"{\r\n", -" int16_t something;\r\n", -" int32_t current_stack_size;\r\n", -"\r\n", -" ptr_current_stack = &something;\r\n", -"\r\n", -" (void) *filename; /* to avoid compilation warning */\r\n", -"\r\n", -" if ( current_calls >= max_num_calls )\r\n", -" {\r\n", -" /* There is no room for a new record -> reallocate the list */\r\n", -" max_num_calls += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", -" stack_callers[0] = realloc( stack_callers[0], max_num_calls * sizeof( caller_info ) );\r\n", -" stack_callers[1] = realloc( stack_callers[1], max_num_calls * sizeof( caller_info ) );\r\n", -" }\r\n", -"\r\n", -" /* Valid Function Name? */\r\n", -" if ( fctname[0] == 0 )\r\n", -" { /* No */\r\n", -" fprintf( stderr, \"Invalid function name for call stack info.\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" /* Save the Name of the Calling Function in the Table */\r\n", -" strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FUNCTION_NAME_LENGTH );\r\n", -" stack_callers[0][current_calls].function_name[MAX_FUNCTION_NAME_LENGTH] = 0; /* Nul Terminate */\r\n", -"\r\n", -" /* Save the Stack Pointer */\r\n", -" stack_callers[0][current_calls].stack_ptr = ptr_current_stack;\r\n", -"\r\n", -" /* Increase the Number of Calls in the List */\r\n", -" current_calls++;\r\n", -"\r\n", -" /* Is this the First Time or the Worst Case? */\r\n", -" if ( ptr_current_stack < ptr_max_stack || ptr_max_stack == NULL )\r\n", -" { /* Yes */\r\n", -" /* Save Info about it */\r\n", -" ptr_max_stack = ptr_current_stack;\r\n", -"\r\n", -" /* save the worst-case frame number */\r\n", -" /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */\r\n", -" wc_stack_frame = update_cnt; \r\n", -" strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 );\r\n", -" location_max_stack[sizeof( location_max_stack ) - 1] = '\\0';\r\n", -"\r\n", -" /* Save Call Tree */\r\n", -" memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls );\r\n", -"\r\n", -" /* Terminate the List with 0 (for printing purposes) */\r\n", -" if ( current_calls < max_num_calls )\r\n", -" {\r\n", -" stack_callers[1][current_calls].function_name[0] = 0;\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* Check, if This is the New Worst-Case RAM (stack + heap) */\r\n", -" current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) );\r\n", -"\r\n", -" if ( current_stack_size < 0 )\r\n", -" {\r\n", -" /* prevent negative stack size */\r\n", -" current_stack_size = 0;\r\n", -" }\r\n", -"\r\n", -" if ( current_stack_size + current_heap_size > wc_ram_size )\r\n", -" {\r\n", -" wc_ram_size = current_stack_size + current_heap_size;\r\n", -" wc_ram_frame = update_cnt;\r\n", -" }\r\n", -"\r\n", -" return 0 /* for Now */;\r\n", -"}\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * pop_stack()\r\n", -" *\r\n", -" * Remove stack caller entry from the list\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"int pop_stack( const char *filename, const char *fctname )\r\n", -"{\r\n", -" caller_info *caller_info_ptr;\r\n", -"\r\n", -" (void) *filename; /* to avoid compilation warning */\r\n", -"\r\n", -" /* Decrease the Number of Records */\r\n", -" current_calls--;\r\n", -"\r\n", -" /* Get Pointer to Caller Information */\r\n", -" caller_info_ptr = &stack_callers[0][current_calls];\r\n", -"\r\n", -" /* Check, if the Function Names Match */\r\n", -" if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 )\r\n", -" {\r\n", -" fprintf( stderr, \"Invalid usage of pop_stack()\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" /* Erase Entry */\r\n", -" caller_info_ptr->function_name[0] = 0;\r\n", -"\r\n", -" /* Retrieve previous stack pointer */\r\n", -" if ( current_calls == 0 )\r\n", -" {\r\n", -" ptr_current_stack = ptr_base_stack;\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" ptr_current_stack = stack_callers[0][current_calls - 1].stack_ptr;\r\n", -" }\r\n", -"\r\n", -" return 0 /* for Now */;\r\n", -"}\r\n", -"\r\n", -"#ifdef MEM_COUNT_DETAILS\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * print_stack_call_tree()\r\n", -" *\r\n", -" * Print detailed information about worst-case stack usage\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"static void print_stack_call_tree( void )\r\n", -"{\r\n", -" caller_info *caller_info_ptr;\r\n", -" int call_level;\r\n", -" char fctname[MAX_FUNCTION_NAME_LENGTH + 1];\r\n", -"\r\n", -" fprintf( stdout, \"\\nList of functions when maximum stack size is reached:\\n\\n\" );\r\n", -"\r\n", -" caller_info_ptr = &stack_callers[1][0];\r\n", -" for ( call_level = 0; call_level < max_num_calls; call_level++ )\r\n", -" {\r\n", -" /* Done? */\r\n", -" if ( caller_info_ptr->function_name[0] == 0 )\r\n", -" {\r\n", -" break;\r\n", -" }\r\n", -"\r\n", -" /* Print Name */\r\n", -" strncpy( fctname, caller_info_ptr->function_name, MAX_FUNCTION_NAME_LENGTH );\r\n", -" strcat( fctname, \"()\" );\r\n", -" fprintf( stdout, \"%-42s\", fctname );\r\n", -"\r\n", -" /* Print Stack Usage (Based on Difference) */\r\n", -" if ( call_level != 0 )\r\n", -" {\r\n", -" fprintf( stdout, \"%lu %s\\n\", ( ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" fprintf( stdout, \"%lu %s\\n\", ( ( ptr_base_stack - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n", -" }\r\n", -"\r\n", -" /* Advance */\r\n", -" caller_info_ptr++;\r\n", -" }\r\n", -"\r\n", -" fprintf( stdout, \"\\n\" );\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"#endif\r\n", -"\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * mem_alloc()\r\n", -" *\r\n", -" * Creates new record, stores auxiliary information about which function allocated the memory, line number, parameters, etc.\r\n", -" * Finally, it allocates physical memory using malloc()\r\n", -" * The function also updates worst-case heap size and worst-case RAM size\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"void *mem_alloc(\r\n", -" const char *func_name,\r\n", -" int func_lineno,\r\n", -" size_t size,\r\n", -" char *size_str /* the first char indicates m-alloc or c-alloc */ )\r\n", -"{\r\n", -" int index_record;\r\n", -" int32_t current_stack_size;\r\n", -" unsigned long hash;\r\n", -" allocator_record *ptr_record;\r\n", -"\r\n", -" if ( size == 0 )\r\n", -" {\r\n", -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Size of Zero not Supported\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" /* Search for an existing record (that has been de-allocated before) */\r\n", -" index_record = 0;\r\n", -" while ( ( ptr_record = get_mem_record( &hash, func_name, func_lineno, size_str, &index_record ) ) != NULL )\r\n", -" {\r\n", -" if ( ptr_record->frame_allocated == -1 )\r\n", -" {\r\n", -" break;\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" index_record++;\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* Create new record */\r\n", -" if ( ptr_record == NULL )\r\n", -" {\r\n", -" if ( Num_Records >= Max_Num_Records )\r\n", -" {\r\n", -" /* There is no room for a new record -> reallocate memory */\r\n", -" Max_Num_Records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", -" allocation_list = realloc( allocation_list, Max_Num_Records * sizeof( allocator_record ) );\r\n", -" }\r\n", -"\r\n", -" ptr_record = &( allocation_list[Num_Records] );\r\n", -"\r\n", -" /* Initialize new record */\r\n", -" ptr_record->hash = hash;\r\n", -" ptr_record->noccurances = 0;\r\n", -" ptr_record->total_block_size = 0;\r\n", -" ptr_record->total_used_size = 0;\r\n", -" ptr_record->frame_allocated = -1;\r\n", -" ptr_record->OOB_Flag = 0;\r\n", -" ptr_record->wc_heap_size_intra_frame = -1;\r\n", -" ptr_record->wc_heap_size_inter_frame = -1;\r\n", -"\r\n", -" index_record = Num_Records;\r\n", -" Num_Records++;\r\n", -" }\r\n", -"\r\n", -" /* Allocate memory block for the new record, add signature before the beginning and after the memory block and fill it with magic value */\r\n", -" ptr_record->block_ptr = mem_alloc_block( size, size_str );\r\n", -"\r\n", -" if ( ptr_record->block_ptr == NULL )\r\n", -" {\r\n", -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Cannot Allocate Memory!\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" /* Save all auxiliary information about the memory block */\r\n", -" strncpy( ptr_record->name, func_name, MAX_FUNCTION_NAME_LENGTH );\r\n", -" ptr_record->name[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n", -" strncpy( ptr_record->params, size_str, MAX_PARAMS_LENGTH ); /* Note: The size string starts with either 'm' or 'c' to indicate 'm'alloc or 'c'alloc */\r\n", -" ptr_record->params[MAX_PARAMS_LENGTH] = '\\0';\r\n", -" ptr_record->lineno = func_lineno;\r\n", -" ptr_record->block_size = size;\r\n", -" ptr_record->total_block_size += size;\r\n", -"\r\n", -"#ifdef MEM_COUNT_DETAILS\r\n", -" /* Export heap memory allocation record to the .csv file */\r\n", -" fprintf( fid_csv_filename, \"A,%d,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n", -"#endif\r\n", -"\r\n", -" if ( ptr_record->frame_allocated != -1 )\r\n", -" {\r\n", -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Attempt to Allocate the Same Memory Block with Freeing it First!\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" ptr_record->frame_allocated = update_cnt; /* Store the current frame number -> later it will be used to determine the total duration */\r\n", -"\r\n", -" /* Update Heap Size in the current frame */\r\n", -" current_heap_size += ptr_record->block_size;\r\n", -"\r\n", -" /* Check, if this is the new Worst-Case RAM (stack + heap) */\r\n", -" current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) );\r\n", -" if ( current_stack_size + current_heap_size > wc_ram_size )\r\n", -" {\r\n", -" wc_ram_size = current_stack_size + current_heap_size;\r\n", -" wc_ram_frame = update_cnt;\r\n", -" }\r\n", -"\r\n", -" /* Add new entry to the heap allocation call tree */\r\n", -" if ( heap_allocation_call_tree == NULL )\r\n", -" {\r\n", -" fprintf( stderr, \"Error: Heap allocation call tree not created!\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" /* check, if the maximum size of the call tree has been reached -> resize if so */\r\n", -" if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size )\r\n", -" {\r\n", -" heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", -" heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n", -" }\r\n", -"\r\n", -" /* push new entry (positive number means push op, neagtive number means pop op; zero index must be converted to 0.01 :-) */\r\n", -" heap_allocation_call_tree[heap_allocation_call_tree_size++] = index_record;\r\n", -"\r\n", -" return ptr_record->block_ptr;\r\n", -"}\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * mem_alloc_block()\r\n", -" *\r\n", -" * Physical allocation of memory using malloc(). Appends 'signature' before and after the block,\r\n", -" * pre-fills memory block with magic value\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"static void *mem_alloc_block( size_t size, const char *size_str )\r\n", -"{\r\n", -" size_t rounded_size;\r\n", -" void *block_ptr;\r\n", -" char *tmp_ptr;\r\n", -" size_t n, f;\r\n", -" int32_t fill_value;\r\n", -" int32_t *ptr32;\r\n", -" int32_t mask, temp;\r\n", -"\r\n", -" /* Round Up Block Size */\r\n", -" rounded_size = ROUND_BLOCK_SIZE( size );\r\n", -"\r\n", -" /* Allocate memory using the standard malloc() by adding room for Signature Values */\r\n", -" block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 );\r\n", -"\r\n", -" if ( block_ptr == NULL )\r\n", -" {\r\n", -" return NULL;\r\n", -" }\r\n", -"\r\n", -" /* Add Signature Before the Start of the Block */\r\n", -" ptr32 = (int32_t *) block_ptr;\r\n", -" n = N_32BITS_BLOCKS;\r\n", -" do\r\n", -" {\r\n", -" *ptr32++ = MAGIC_VALUE_OOB;\r\n", -" } while ( --n );\r\n", -"\r\n", -" /* Fill Memory Block with Magic Value or 0 */\r\n", -" fill_value = MAGIC_VALUE_USED;\r\n", -" if ( size_str[0] == 'c' )\r\n", -" {\r\n", -" fill_value = 0x00000000;\r\n", -" }\r\n", -" n = size / sizeof( int32_t );\r\n", -" while ( n-- )\r\n", -" {\r\n", -" *ptr32++ = fill_value;\r\n", -" }\r\n", -"\r\n", -" /* Fill the Reminder of the Memory Block - After Rounding */\r\n", -" n = rounded_size - size;\r\n", -" f = n % sizeof( int32_t );\r\n", -" if ( f != 0 )\r\n", -" {\r\n", -" /* when filling with '0' need to adapt the magic value */\r\n", -" /* shift by [1->24, 2->16, 3->8] */\r\n", -" mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */\r\n", -" temp = MAGIC_VALUE_OOB & mask;\r\n", -" if ( fill_value != 0x0 )\r\n", -" { /* for malloc merge fill value */\r\n", -" temp += ( ~mask ) & MAGIC_VALUE_USED;\r\n", -" } /* for calloc the code in (1) above already introduces zeros */\r\n", -" *ptr32++ = temp;\r\n", -" }\r\n", -" n /= sizeof( int32_t );\r\n", -" n += N_32BITS_BLOCKS;\r\n", -"\r\n", -" /* Add Signature After the End of Block */\r\n", -" do\r\n", -" {\r\n", -" *ptr32++ = MAGIC_VALUE_OOB;\r\n", -" } while ( --n );\r\n", -"\r\n", -" /* Adjust the Memory Block Pointer (Magic Value Before and After the Memory Block Requested) */\r\n", -" tmp_ptr = (char *) block_ptr;\r\n", -" tmp_ptr += BLOCK_ROUNDING;\r\n", -" block_ptr = (void *) tmp_ptr;\r\n", -"\r\n", -" return block_ptr;\r\n", -"}\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * mem_set_usage()\r\n", -" *\r\n", -" * Calculates actual usage of memory block by checking the magic value that was used to pre-fill\r\n", -" * each memory block during its allocation\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"static int mem_set_usage( allocator_record *record_ptr )\r\n", -"{\r\n", -" int total_bytes_used;\r\n", -"\r\n", -" size_t n;\r\n", -" int32_t *ptr32;\r\n", -" char *ptr8;\r\n", -" size_t total_bytes;\r\n", -" int32_t fill_value;\r\n", -"\r\n", -" fill_value = MAGIC_VALUE_USED;\r\n", -" if ( ( record_ptr->params[0] ) == 'c' )\r\n", -" {\r\n", -" fill_value = 0x00000000;\r\n", -" }\r\n", -"\r\n", -" total_bytes = record_ptr->block_size;\r\n", -"\r\n", -" /* Check 4 bytes at a time */\r\n", -" ptr32 = (int32_t *) record_ptr->block_ptr;\r\n", -" total_bytes_used = 0;\r\n", -" for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- )\r\n", -" {\r\n", -" if ( *ptr32++ != fill_value )\r\n", -" {\r\n", -" total_bytes_used += sizeof( int32_t );\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* Check remaining bytes (If Applicable) 1 byte at a time */\r\n", -" ptr8 = (char *) ptr32;\r\n", -" for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- )\r\n", -" {\r\n", -" if ( *ptr8++ != (char) fill_value )\r\n", -" {\r\n", -" total_bytes_used++;\r\n", -" }\r\n", -"\r\n", -" /* Update Value */\r\n", -" fill_value >>= 8;\r\n", -" }\r\n", -"\r\n", -" return total_bytes_used;\r\n", -"}\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * mem_check_OOB()\r\n", -" *\r\n", -" * Checks, if out-of-bounds access has occured. This is done by inspecting the 'signature' value\r\n", -" * taht has been added before and after the memory block during its allocation\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"static unsigned int mem_check_OOB( allocator_record *record_ptr )\r\n", -"{\r\n", -" int32_t *ptr32;\r\n", -" unsigned int OOB_Flag = 0x0;\r\n", -" int32_t mask;\r\n", -" size_t i;\r\n", -" int f;\r\n", -"\r\n", -" ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS;\r\n", -"\r\n", -" /* Check the Signature at the Beginning of Memory Block */\r\n", -" i = N_32BITS_BLOCKS;\r\n", -" do\r\n", -" {\r\n", -" if ( *ptr32++ ^ MAGIC_VALUE_OOB )\r\n", -" {\r\n", -" OOB_Flag |= OOB_START;\r\n", -" }\r\n", -" } while ( --i );\r\n", -"\r\n", -" /* Advance to End (Snap to lowest 32 Bits) */\r\n", -" ptr32 += record_ptr->block_size / sizeof( int32_t );\r\n", -"\r\n", -" /* Calculate Unused Space That has been added to get to the rounded Block Size */\r\n", -" i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size;\r\n", -"\r\n", -" /* Partial Check of Signature at the End of Memory Block (for block size that has been rounded) */\r\n", -" f = i % sizeof( int32_t );\r\n", -" if ( f != 0 )\r\n", -" {\r\n", -" mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 );\r\n", -" if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask )\r\n", -" {\r\n", -" OOB_Flag |= OOB_END;\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* Full Check of Signature at the End of Memory Block, i.e. all 32 Bits (for the remainder after rounding) */\r\n", -" i /= sizeof( int32_t );\r\n", -" i += N_32BITS_BLOCKS;\r\n", -" do\r\n", -" {\r\n", -" if ( *ptr32++ ^ MAGIC_VALUE_OOB )\r\n", -" {\r\n", -" OOB_Flag |= OOB_END;\r\n", -" }\r\n", -" } while ( --i );\r\n", -"\r\n", -" return OOB_Flag;\r\n", -"}\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * malloc_hash()\r\n", -" *\r\n", -" * Calculate hash from function name, line number and malloc size\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str )\r\n", -"{\r\n", -" unsigned long hash = 5381;\r\n", -" const char *ptr_str;\r\n", -"\r\n", -" ptr_str = func_name;\r\n", -" while ( ptr_str != NULL && *ptr_str != '\\0' )\r\n", -" {\r\n", -" hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */\r\n", -" }\r\n", -"\r\n", -" hash = ( ( hash << 5 ) + hash ) + func_lineno; /* hash * 33 + func_lineno */\r\n", -"\r\n", -" ptr_str = size_str;\r\n", -" while ( ptr_str != NULL && *ptr_str != '\\0' )\r\n", -" {\r\n", -" hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */\r\n", -" }\r\n", -"\r\n", -" return hash;\r\n", -"}\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * get_mem_record()\r\n", -" *\r\n", -" * Search for memory record in the internal list, return NULL if not found\r\n", -" * Start from index_record\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record )\r\n", -"{\r\n", -" int i;\r\n", -"\r\n", -" if ( *index_record < 0 || *index_record > Num_Records )\r\n", -" {\r\n", -" return NULL;\r\n", -" }\r\n", -"\r\n", -" /* calculate hash */\r\n", -" *hash = malloc_hash( func_name, func_lineno, size_str );\r\n", -"\r\n", -" for ( i = *index_record; i < Num_Records; i++ )\r\n", -" {\r\n", -" /* check, if memory block is not allocated at the moment and the hash matches */\r\n", -" if ( allocation_list[i].block_ptr == NULL && *hash == allocation_list[i].hash )\r\n", -" {\r\n", -" *index_record = i;\r\n", -" return &( allocation_list[i] );\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* not found */\r\n", -" *index_record = -1;\r\n", -" return NULL;\r\n", -"}\r\n", -"\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * mem_free()\r\n", -" *\r\n", -" * This function de-allocatesd the memory block and frees the mphysical memory with free().\r\n", -" * It also updates actual and average usage of the memory block.\r\n", -" *\r\n", -" * Note: The record is not removed from the list and may be reused later on in mem_alloc()!\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"void mem_free( const char *func_name, int func_lineno, void *ptr )\r\n", -"{\r\n", -" int i, index_record;\r\n", -" char *tmp_ptr;\r\n", -" allocator_record *ptr_record;\r\n", -"\r\n", -" /* Search for the Block Pointer in the List */\r\n", -" ptr_record = NULL;\r\n", -" index_record = -1;\r\n", -" for ( i = 0; i < Num_Records; i++ )\r\n", -" {\r\n", -" if ( ptr == allocation_list[i].block_ptr )\r\n", -" { /* Yes, Found it */\r\n", -" ptr_record = &( allocation_list[i] );\r\n", -" index_record = i;\r\n", -" break;\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" if ( ptr_record == NULL )\r\n", -" {\r\n", -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Unable to Find Record Corresponding to the Allocated Memory Block!\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" /* Update the Heap Size */\r\n", -" current_heap_size -= ptr_record->block_size;\r\n", -"\r\n", -" /* Calculate the Actual Usage of the Memory Block (Look for Signature) */\r\n", -" ptr_record->total_used_size += mem_set_usage( ptr_record );\r\n", -"\r\n", -" /* Check, if Out-Of-Bounds Access has been Detected */\r\n", -" ptr_record->OOB_Flag = mem_check_OOB( ptr_record );\r\n", -"\r\n", -"#ifdef MEM_COUNT_DETAILS\r\n", -" /* Export heap memory de-allocation record to the .csv file */\r\n", -" fprintf( fid_csv_filename, \"D,%d,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n", -"#endif\r\n", -"\r\n", -" /* De-Allocate Memory Block */\r\n", -" tmp_ptr = (char *) ptr;\r\n", -" tmp_ptr -= BLOCK_ROUNDING;\r\n", -" ptr = (void *) tmp_ptr;\r\n", -" free( ptr );\r\n", -"\r\n", -" /* Add new entry to the heap allocation call tree */\r\n", -" if ( heap_allocation_call_tree == NULL )\r\n", -" {\r\n", -" fprintf( stderr, \"Error: Heap allocation call tree not created!\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -"\r\n", -" /* check, if the maximum size of the call tree has been reached -> resize if so */\r\n", -" if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size )\r\n", -" {\r\n", -" heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", -" heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n", -" }\r\n", -"\r\n", -" heap_allocation_call_tree[heap_allocation_call_tree_size++] = -index_record;\r\n", -"\r\n", -" /* Reset memory block pointer (this is checked when updating wc intra-frame and inter-frame memory) */\r\n", -" ptr_record->block_ptr = NULL;\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * update_mem()\r\n", -" *\r\n", -" * This function updates the worst-case intra-frame memory and the worst-case inter-frame memory.\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"void update_mem( void )\r\n", -"{\r\n", -" int i, j, flag_alloc = -1, i_record;\r\n", -" int size_current_intra_frame_heap;\r\n", -" int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap;\r\n", -" allocator_record *ptr_record;\r\n", -"\r\n", -" /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */\r\n", -" n_items_current_intra_frame_heap = 0;\r\n", -" size_current_intra_frame_heap = 0;\r\n", -" for ( i = 0; i < heap_allocation_call_tree_size; i++ )\r\n", -" {\r\n", -" /* get the record */\r\n", -" i_record = heap_allocation_call_tree[i];\r\n", -"\r\n", -" if ( i_record > 0 )\r\n", -" {\r\n", -" flag_alloc = 1;\r\n", -" }\r\n", -" else if ( i_record < 0 )\r\n", -" {\r\n", -" flag_alloc = 0;\r\n", -" i_record = -i_record;\r\n", -" }\r\n", -" ptr_record = &( allocation_list[i_record] );\r\n", -"\r\n", -" if ( ptr_record->frame_allocated == update_cnt && ptr_record->block_ptr == NULL )\r\n", -" {\r\n", -" /* intra-frame heap memory */\r\n", -" if ( list_current_intra_frame_heap == NULL )\r\n", -" {\r\n", -" list_current_intra_frame_heap = (int *) malloc( heap_allocation_call_tree_size * sizeof( int ) );\r\n", -" memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) );\r\n", -" }\r\n", -"\r\n", -" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n", -" if ( i_record == 0 )\r\n", -" {\r\n", -" flag_alloc = 1;\r\n", -" for ( j = 0; j < n_items_current_intra_frame_heap; j++ )\r\n", -" {\r\n", -" if ( list_current_intra_frame_heap[j] == i_record )\r\n", -" {\r\n", -" flag_alloc = 0;\r\n", -" break;\r\n", -" }\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" if ( flag_alloc )\r\n", -" {\r\n", -" /* add to list */\r\n", -" list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record;\r\n", -" size_current_intra_frame_heap += ptr_record->block_size;\r\n", -"\r\n", -" /* no need to re-size the list -> the initially allocated size should be large enough */\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" /* remove from list */\r\n", -" for ( j = 0; j < n_items_current_intra_frame_heap; j++ )\r\n", -" {\r\n", -" if ( list_current_intra_frame_heap[j] == i_record )\r\n", -" {\r\n", -" break;\r\n", -" }\r\n", -" }\r\n", -" memmove( &list_current_intra_frame_heap[j], &list_current_intra_frame_heap[j + 1], ( n_items_current_intra_frame_heap - j ) * sizeof( int ) );\r\n", -" n_items_current_intra_frame_heap--;\r\n", -" size_current_intra_frame_heap -= ptr_record->block_size;\r\n", -"\r\n", -" /* reset block size */\r\n", -" ptr_record->frame_allocated = -1;\r\n", -" ptr_record->block_size = 0;\r\n", -" }\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" /* inter-frame heap memory */\r\n", -"\r\n", -" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n", -" if ( i_record == 0 )\r\n", -" {\r\n", -" flag_alloc = 1;\r\n", -" for ( j = 0; j < n_items_current_inter_frame_heap; j++ )\r\n", -" {\r\n", -" if ( list_current_inter_frame_heap[j] == i_record )\r\n", -" {\r\n", -" flag_alloc = 0;\r\n", -" break;\r\n", -" }\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" if ( flag_alloc )\r\n", -" {\r\n", -" /* add to list */\r\n", -" if ( n_items_current_inter_frame_heap >= max_items_current_inter_frame_heap )\r\n", -" {\r\n", -" /* resize list, if needed */\r\n", -" max_items_current_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n", -" list_current_inter_frame_heap = realloc( list_current_inter_frame_heap, max_items_current_inter_frame_heap * sizeof( int ) );\r\n", -" }\r\n", -"\r\n", -" list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record;\r\n", -" size_current_inter_frame_heap += ptr_record->block_size;\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" /* remove from list */\r\n", -" for ( j = 0; j < n_items_current_inter_frame_heap; j++ )\r\n", -" {\r\n", -" if ( list_current_inter_frame_heap[j] == i_record )\r\n", -" {\r\n", -" break;\r\n", -" }\r\n", -" }\r\n", -" memmove( &list_current_inter_frame_heap[j], &list_current_inter_frame_heap[j + 1], ( n_items_current_inter_frame_heap - j ) * sizeof( int ) );\r\n", -" n_items_current_inter_frame_heap--;\r\n", -" size_current_inter_frame_heap -= ptr_record->block_size;\r\n", -"\r\n", -" /* reset block size */\r\n", -" ptr_record->frame_allocated = -1;\r\n", -" ptr_record->block_size = 0;\r\n", -" }\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* check, if this is the new worst-case for intra-frame heap memory */\r\n", -" if ( size_current_intra_frame_heap > size_wc_intra_frame_heap )\r\n", -" {\r\n", -" if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap )\r\n", -" {\r\n", -" /* resize the list, if needed */\r\n", -" max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n", -" list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n", -" }\r\n", -"\r\n", -" /* copy current-frame list to worst-case list */\r\n", -" memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) );\r\n", -" n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap;\r\n", -" size_wc_intra_frame_heap = size_current_intra_frame_heap;\r\n", -" location_wc_intra_frame_heap = update_cnt;\r\n", -"\r\n", -" /* update the wc numbers in all individual records */\r\n", -" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n", -" {\r\n", -" i_record = list_wc_intra_frame_heap[i];\r\n", -" ptr_record = &( allocation_list[i_record] );\r\n", -" ptr_record->wc_heap_size_intra_frame = ptr_record->block_size;\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* check, if this is the new worst-case for inter-frame heap memory */\r\n", -" if ( size_current_inter_frame_heap > size_wc_inter_frame_heap )\r\n", -" {\r\n", -" if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap )\r\n", -" {\r\n", -" /* resize list, if needed */\r\n", -" max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n", -" list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n", -" }\r\n", -"\r\n", -" /* copy current-frame list to worst-case list */\r\n", -" memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) );\r\n", -" n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap;\r\n", -" size_wc_inter_frame_heap = size_current_inter_frame_heap;\r\n", -" location_wc_inter_frame_heap = update_cnt;\r\n", -"\r\n", -" /* update the wc numbers in all individual records */\r\n", -" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n", -" {\r\n", -" i_record = list_wc_inter_frame_heap[i];\r\n", -" ptr_record = &( allocation_list[i_record] );\r\n", -" ptr_record->wc_heap_size_inter_frame = ptr_record->block_size;\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* reset heap allocation call tree */\r\n", -" heap_allocation_call_tree_size = 0;\r\n", -"\r\n", -" /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */\r\n", -" if ( list_current_intra_frame_heap )\r\n", -" {\r\n", -" free( list_current_intra_frame_heap );\r\n", -" }\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"#ifdef MEM_COUNT_DETAILS\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * subst()\r\n", -" *\r\n", -" * Substitute character in string\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"static void subst( char *s, char from, char to )\r\n", -"{\r\n", -" while ( *s == from )\r\n", -" {\r\n", -" *s++ = to;\r\n", -" }\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * mem_count_summary()\r\n", -" *\r\n", -" * Print detailed (per-item) information about heap memory usage\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"static void mem_count_summary( void )\r\n", -"{\r\n", -" int i, j, index, index_record;\r\n", -" size_t length;\r\n", -" char buf[300], format_str[50], name_str[MAX_FUNCTION_NAME_LENGTH + 3], parms_str[MAX_PARAMS_LENGTH + 1], type_str[10], usage_str[20], size_str[20], line_str[10];\r\n", -" allocator_record *ptr_record, *ptr;\r\n", -"\r\n", -" /* Prepare format string */\r\n", -" sprintf( format_str, \"%%-%ds %%5s %%6s %%-%ds %%20s %%6s \", MAX_FUNCTION_NAME_LENGTH, MAX_PARAMS_LENGTH );\r\n", -"\r\n", -" if ( n_items_wc_intra_frame_heap > 0 )\r\n", -" {\r\n", -" /* Intra-Frame Heap Size */\r\n", -" fprintf( stdout, \"\\nList of memory blocks when maximum intra-frame heap size is reached:\\n\\n\" );\r\n", -"\r\n", -" /* Find duplicate records (same hash and worst-case heap size) */\r\n", -" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n", -" {\r\n", -" index_record = list_wc_intra_frame_heap[i];\r\n", -" if ( index_record == -1 )\r\n", -" {\r\n", -" continue;\r\n", -" }\r\n", -"\r\n", -" ptr_record = &( allocation_list[index_record] );\r\n", -" for ( j = i + 1; j < n_items_wc_intra_frame_heap; j++ )\r\n", -" {\r\n", -" index = list_wc_intra_frame_heap[j];\r\n", -" if ( index == -1 )\r\n", -" {\r\n", -" continue;\r\n", -" }\r\n", -" ptr = &( allocation_list[index] );\r\n", -"\r\n", -" if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_intra_frame == ptr_record->wc_heap_size_intra_frame )\r\n", -" {\r\n", -" ptr_record->noccurances++;\r\n", -" list_wc_intra_frame_heap[j] = -1;\r\n", -" }\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* Print Header */\r\n", -" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Maximum Size\", \"Usage\" );\r\n", -" puts( buf );\r\n", -" length = strlen( buf );\r\n", -" sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n", -" subst( buf, '0', '-' );\r\n", -" puts( buf );\r\n", -"\r\n", -" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n", -" {\r\n", -" index_record = list_wc_intra_frame_heap[i];\r\n", -"\r\n", -" if ( index_record != -1 )\r\n", -" {\r\n", -" /* get the record */\r\n", -" ptr_record = &( allocation_list[index_record] );\r\n", -"\r\n", -" /* prepare information strings */\r\n", -" strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH );\r\n", -" strcat( name_str, \"()\" );\r\n", -" name_str[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n", -" strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH );\r\n", -" parms_str[MAX_PARAMS_LENGTH] = '\\0';\r\n", -"\r\n", -" if ( ptr_record->params[0] == 'm' )\r\n", -" {\r\n", -" strcpy( type_str, \"malloc\" );\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" strcpy( type_str, \"calloc\" );\r\n", -" }\r\n", -"\r\n", -" sprintf( line_str, \"%d\", ptr_record->lineno );\r\n", -"\r\n", -" /* prepare average usage & memory size strings */\r\n", -" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) );\r\n", -"\r\n", -" if ( ptr_record->noccurances > 1 )\r\n", -" {\r\n", -" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" sprintf( size_str, \"%d %s\", (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n", -" }\r\n", -"\r\n", -" sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str );\r\n", -" puts( buf );\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" fprintf( stdout, \"\\n\" );\r\n", -" }\r\n", -"\r\n", -" if ( n_items_wc_inter_frame_heap > 0 )\r\n", -" {\r\n", -" /* Inter-Frame Heap Size */\r\n", -" fprintf( stdout, \"\\nList of memory blocks when maximum inter-frame heap size is reached:\\n\\n\" );\r\n", -"\r\n", -" /* Find duplicate records (same hash and worst-case heap size) */\r\n", -" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n", -" {\r\n", -" index_record = list_wc_inter_frame_heap[i];\r\n", -" if ( index_record == -1 )\r\n", -" {\r\n", -" continue;\r\n", -" }\r\n", -" ptr_record = &( allocation_list[index_record] );\r\n", -" ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */\r\n", -" for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ )\r\n", -" {\r\n", -" index = list_wc_inter_frame_heap[j];\r\n", -" if ( index == -1 )\r\n", -" {\r\n", -" continue;\r\n", -" }\r\n", -" ptr = &( allocation_list[index] );\r\n", -"\r\n", -" if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_inter_frame == ptr_record->wc_heap_size_inter_frame )\r\n", -" {\r\n", -" ptr_record->noccurances++;\r\n", -" list_wc_inter_frame_heap[j] = -1;\r\n", -" }\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" /* Print Header */\r\n", -" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Memory Size\", \"Usage\" );\r\n", -" puts( buf );\r\n", -" length = strlen( buf );\r\n", -" sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n", -" subst( buf, '0', '-' );\r\n", -" puts( buf );\r\n", -"\r\n", -" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n", -" {\r\n", -" index_record = list_wc_inter_frame_heap[i];\r\n", -"\r\n", -" if ( index_record != -1 )\r\n", -" {\r\n", -" /* get the record */\r\n", -" ptr_record = &( allocation_list[index_record] );\r\n", -"\r\n", -" /* prepare information strings */\r\n", -" strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH );\r\n", -" strcat( name_str, \"()\" );\r\n", -" name_str[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n", -" strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH );\r\n", -" parms_str[MAX_PARAMS_LENGTH] = '\\0';\r\n", -"\r\n", -" if ( ptr_record->params[0] == 'm' )\r\n", -" {\r\n", -" strcpy( type_str, \"malloc\" );\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" strcpy( type_str, \"calloc\" );\r\n", -" }\r\n", -"\r\n", -" sprintf( line_str, \"%d\", ptr_record->lineno );\r\n", -"\r\n", -" /* prepare average usage & memory size strings */\r\n", -" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) );\r\n", -"\r\n", -" if ( ptr_record->noccurances > 1 )\r\n", -" {\r\n", -" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" sprintf( size_str, \"%d %s\", (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n", -" }\r\n", -"\r\n", -" sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str );\r\n", -" puts( buf );\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" fprintf( stdout, \"\\n\" );\r\n", -" }\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"#endif\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * print_mem()\r\n", -" *\r\n", -" * Print information about ROM and RAM memory usage\r\n", -" *--------------------------------------------------------------------*/\r\n", -"\r\n", -"void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] )\r\n", -"{\r\n", -" int i, nElem;\r\n", -"\r\n", -" fprintf( stdout, \"\\n\\n --- Memory usage --- \\n\\n\" );\r\n", -"\r\n", -" if ( Const_Data_PROM_Table != NULL )\r\n", -" {\r\n", -" nElem = 0;\r\n", -" while ( strcmp( Const_Data_PROM_Table[nElem].file_spec, \"\" ) != 0 )\r\n", -" nElem++;\r\n", -"\r\n", -" for ( i = 0; i < nElem; i++ )\r\n", -" {\r\n", -" if ( Stat_Cnt_Size > 0 )\r\n", -" {\r\n", -" /* words */\r\n", -" fprintf( stdout, \"Program ROM size (%s): %d words\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size );\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" /* bytes (here, we assume that each instruction takes PROM_INST_SIZE bits of the PROM memory) */\r\n", -" fprintf( stdout, \"Program ROM size (%s): %d bytes\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size * ( PROM_INST_SIZE / 8 ) );\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" for ( i = 0; i < nElem; i++ )\r\n", -" {\r\n", -" if ( Const_Data_PROM_Table[i].Get_Const_Data_Size_Func == NULL )\r\n", -" {\r\n", -" fprintf( stdout, \"Error: Cannot retrieve or calculate Table ROM size of (%s)!\\n\", Const_Data_PROM_Table[i].file_spec );\r\n", -" }\r\n", -"\r\n", -" fprintf( stdout, \"Table ROM (const data) size (%s): %d %s\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].Get_Const_Data_Size_Func() >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n", -" }\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" fprintf( stdout, \"Program ROM size: not available\\n\" );\r\n", -" fprintf( stdout, \"Table ROM (const data) size: not available\\n\" );\r\n", -" }\r\n", -"\r\n", -" if ( wc_ram_size > 0 )\r\n", -" {\r\n", -" fprintf( stdout, \"Maximum RAM (stack + heap) size: %d %s in frame %d\\n\", wc_ram_size >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], wc_ram_frame );\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" fprintf( stdout, \"Maximum RAM (stack + heap) size: not available\\n\" );\r\n", -" }\r\n", -"\r\n", -" /* check, if the stack is empty */\r\n", -" if ( ptr_current_stack != ptr_base_stack )\r\n", -" {\r\n", -" fprintf( stderr, \"Warning: Stack is not empty.\\n\" );\r\n", -" }\r\n", -"\r\n", -" if ( ptr_base_stack - ptr_max_stack > 0 )\r\n", -" {\r\n", -" fprintf( stdout, \"Maximum stack size: %lu %s in frame %d\\n\", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size],\r\n", -" wc_stack_frame );\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" fprintf( stdout, \"Maximum stack size: not available\\n\" );\r\n", -" }\r\n", -"\r\n", -" /* last update of intra-frame memory and inter-frame memory, if needed */\r\n", -" if ( heap_allocation_call_tree_size > 0 )\r\n", -" {\r\n", -" update_mem();\r\n", -" }\r\n", -"\r\n", -" /* check, if all memory blocks have been deallocated (freed) */\r\n", -" for ( i = 0; i < Num_Records; i++ )\r\n", -" {\r\n", -" if ( allocation_list[i].block_ptr != NULL )\r\n", -" {\r\n", -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", allocation_list[i].name, allocation_list[i].lineno, \"Error: Memory Block has not been De-Allocated with free()!\" );\r\n", -" exit( -1 );\r\n", -" }\r\n", -" }\r\n", -"\r\n", -" if ( n_items_wc_intra_frame_heap > 0 )\r\n", -" {\r\n", -" fprintf( stdout, \"Maximum intra-frame heap size: %d %s in frame %d\\n\", size_wc_intra_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_intra_frame_heap );\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" fprintf( stdout, \"Maximum intra-frame heap size: 0\\n\" );\r\n", -" }\r\n", -"\r\n", -" if ( n_items_wc_inter_frame_heap > 0 )\r\n", -" {\r\n", -" fprintf( stdout, \"Maximum inter-frame heap size: %d %s in frame %d\\n\", size_wc_inter_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_inter_frame_heap );\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" fprintf( stdout, \"Maximum inter-frame heap size: 0\\n\" );\r\n", -" }\r\n", -"\r\n", -"#ifdef MEM_COUNT_DETAILS\r\n", -" /* Print detailed information about worst-case stack usage */\r\n", -" if ( ptr_base_stack - ptr_max_stack > 0 )\r\n", -" {\r\n", -" print_stack_call_tree();\r\n", -" }\r\n", -"\r\n", -" /* Print detailed information about worst-case heap usage */\r\n", -" mem_count_summary();\r\n", -"#endif\r\n", -"\r\n", -" if ( Stat_Cnt_Size > 0 )\r\n", -" {\r\n", -" /* words */\r\n", -" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", 8 << Stat_Cnt_Size );\r\n", -" }\r\n", -" else\r\n", -" {\r\n", -" /* bytes */\r\n", -" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", PROM_INST_SIZE );\r\n", -" }\r\n", -" fprintf( stdout, \"Note: The Data ROM size is calculated using the sizeof(type) built-in function\\n\" );\r\n", -"\r\n", -" if ( n_items_wc_intra_frame_heap > 0 )\r\n", -" {\r\n", -" fprintf( stdout, \"Intra-frame heap memory is allocated and de-allocated in the same frame\\n\" );\r\n", -" }\r\n", -"\r\n", -" /* De-allocate list of heap memory blocks */\r\n", -" if ( allocation_list != NULL )\r\n", -" {\r\n", -" free( allocation_list );\r\n", -" }\r\n", -"\r\n", -" /* De-allocate list of stack records */\r\n", -" if ( stack_callers[0] != NULL )\r\n", -" {\r\n", -" free( stack_callers[0] );\r\n", -" }\r\n", -"\r\n", -" if ( stack_callers[1] != NULL )\r\n", -" {\r\n", -" free( stack_callers[1] );\r\n", -" }\r\n", -"\r\n", -" /* De-allocate heap allocation call tree */\r\n", -" if ( heap_allocation_call_tree != NULL )\r\n", -" {\r\n", -" free( heap_allocation_call_tree );\r\n", -" }\r\n", -"\r\n", -" /* De-allocate intra-frame and inter-frame heap lists */\r\n", -" if ( list_wc_intra_frame_heap != NULL )\r\n", -" {\r\n", -" free( list_wc_intra_frame_heap );\r\n", -" }\r\n", -"\r\n", -" if ( list_current_inter_frame_heap != NULL )\r\n", -" {\r\n", -" free( list_current_inter_frame_heap );\r\n", -" }\r\n", -"\r\n", -" if ( list_wc_inter_frame_heap != NULL )\r\n", -" {\r\n", -" free( list_wc_inter_frame_heap );\r\n", -" }\r\n", -"\r\n", -"#ifdef MEM_COUNT_DETAILS\r\n", -" if ( fid_csv_filename != NULL )\r\n", -" {\r\n", -" fclose( fid_csv_filename );\r\n", -" }\r\n", -"#endif\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"#endif /* WMOPS */\r\n", -"\r\n", -"#ifndef WMOPS\r\n", -"int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */\r\n", -"#endif\r\n", -"\r\n", -"#ifdef WMOPS\r\n", -"/* Global counter for the calculation of BASOP complexity */\r\n", -"BASIC_OP *multiCounter = NULL;\r\n", -"int currCounter = 0;\r\n", -"int funcId_where_last_call_to_else_occurred;\r\n", -"long funcid_total_wmops_at_last_call_to_else;\r\n", -"int call_occurred = 1;\r\n", -"\r\n", -"BASIC_OP op_weight = {\r\n", -" 1, 1, 1, 1, 1,\r\n", -" 1, 1, 1, 1, 1,\r\n", -" 1, 1, 1, 1, 1,\r\n", -" 1, 1, 2, 2, 1,\r\n", -" 1, 1, 1, 3, 1,\r\n", -"\r\n", -" 1, 1, 1, 3, 1,\r\n", -" 4, 1, 18, 1, 1,\r\n", -" 2, 1, 2, 2, 1,\r\n", -" 1, 1, 1, 1, 1,\r\n", -" 3, 3, 3, 3, 1,\r\n", -"\r\n", -" 1, 1, 1, 1, 1,\r\n", -" 1, 1, 1, 2,\r\n", -" 1, 2, 2, 4, 1,\r\n", -" 1, 1, 1, 1, 1,\r\n", -" 1, 1, 1, 1, 1,\r\n", -"\r\n", -" 1, 1, 1, 1, 3,\r\n", -" 3, 3, 3, 3, 1,\r\n", -" 1, 1, 1, 1, 1,\r\n", -" 1, 1, 1, 4, 4,\r\n", -" 4, 8, 3, 4, 4,\r\n", -"\r\n", -" 5, 32, 3\r\n", -"};\r\n", -"\r\n", -"/* Set the counter group to use, default is zero */\r\n", -"void Set_BASOP_WMOPS_counter( int counterId )\r\n", -"{\r\n", -" if ( ( counterId > num_wmops_records ) || ( counterId < 0 ) )\r\n", -" {\r\n", -" currCounter = 0;\r\n", -" return;\r\n", -" }\r\n", -" currCounter = counterId;\r\n", -" call_occurred = 1;\r\n", -"}\r\n", -"\r\n", -"extern int32_t frame;\r\n", -"\r\n", -"long TotalWeightedOperation()\r\n", -"{\r\n", -" int i;\r\n", -" unsigned int *ptr, *ptr2;\r\n", -" long tot; \r\n", -"\r\n", -" tot = 0;\r\n", -" ptr = (unsigned int *) &multiCounter[currCounter];\r\n", -" ptr2 = (unsigned int *) &op_weight;\r\n", -"\r\n", -" for ( i = 0; i < ( int )( sizeof( multiCounter[currCounter] ) / sizeof( unsigned int ) ); i++ )\r\n", -" {\r\n", -" tot += ( ( *ptr++ ) * ( *ptr2++ ) );\r\n", -" }\r\n", -"\r\n", -" return ( tot );\r\n", -"}\r\n", -"\r\n", -"long DeltaWeightedOperation( void )\r\n", -"{\r\n", -" long NewWOper, delta;\r\n", -"\r\n", -" NewWOper = TotalWeightedOperation();\r\n", -"\r\n", -" delta = NewWOper - wmops[currCounter].LastWOper;\r\n", -" wmops[currCounter].LastWOper = NewWOper;\r\n", -"\r\n", -" return ( delta );\r\n", -"}\r\n", -"\r\n", -"/* Resets the current BASOP WMOPS counter */\r\n", -"void Reset_BASOP_WMOPS_counter( void )\r\n", -"{\r\n", -" int i;\r\n", -" long *ptr;\r\n", -"\r\n", -" /* clear the current BASOP operation counter before new frame begins */\r\n", -" ptr = (long *) &multiCounter[currCounter];\r\n", -" for ( i = 0; i < (int) ( sizeof( multiCounter[currCounter] ) / sizeof( long ) ); i++ )\r\n", -" {\r\n", -" *ptr++ = 0;\r\n", -" }\r\n", -"\r\n", -" wmops[currCounter].LastWOper = 0;\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"#endif\r\n", -"\r\n", -"\r\n", -"\r\n", \ No newline at end of file +"/*\r\n" +" * (C) 2024 copyright VoiceAge Corporation. All Rights Reserved.\r\n" +" *\r\n" +" * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n" +" * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n" +" * or refer to ITU-T Recommendation G.191 on \"SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS\".\r\n" +" *\r\n" +" * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor\r\n" +" * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software\r\n" +" * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE.\r\n" +" *\r\n" +" * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca)\r\n" +" */\r\n" +"\r\n" +"#include \r\n" +"#include \r\n" +"#include \r\n" +"#include \r\n" +"#include \r\n" +"#include \r\n" +"#include \r\n" +"\r\n" +"#ifndef _MSC_VER\r\n" +"#include \r\n" +"#include \r\n" +"#else\r\n" +"#include \r\n" +"#endif\r\n" +"\r\n" +"#include \"wmc_auto.h\"\r\n" +"\r\n" +"#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */\r\n" +"\r\n" +"#ifndef WMOPS\r\n" +"int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */\r\n" +"#endif\r\n" +"\r\n" +"#ifdef WMOPS\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * Complexity counting tool\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"\r\n" +"#define MAX_FUNCTION_NAME_LENGTH 200 /* Maximum length of the function name */\r\n" +"#define MAX_PARAMS_LENGTH 200 /* Maximum length of the function parameter string */\r\n" +"#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> might be increased during runtime, if needed */\r\n" +"#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */\r\n" +"#define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */\r\n" +"#define DOUBLE_MAX 0x80000000\r\n" +"#define FAC ( FRAMES_PER_SECOND / 1e6 )\r\n" +"\r\n" +"#define FRAMES_PER_SECOND 50.0\r\n" +"#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */\r\n" +"\r\n" +"typedef struct\r\n" +"{\r\n" +" char label[MAX_FUNCTION_NAME_LENGTH];\r\n" +" long call_number;\r\n" +" long update_cnt;\r\n" +" int call_tree[MAX_CALL_TREE_DEPTH];\r\n" +" long LastWOper;\r\n" +" double start_selfcnt;\r\n" +" double current_selfcnt;\r\n" +" double max_selfcnt;\r\n" +" double min_selfcnt;\r\n" +" double tot_selfcnt;\r\n" +" double start_cnt; /* The following take into account the decendants */\r\n" +" double current_cnt;\r\n" +" double max_cnt;\r\n" +" double min_cnt;\r\n" +" double tot_cnt;\r\n" +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" +" int32_t current_call_number;\r\n" +" double wc_cnt;\r\n" +" double wc_selfcnt;\r\n" +" int32_t wc_call_number;\r\n" +"#endif\r\n" +"} wmops_record;\r\n" +"\r\n" +"double ops_cnt;\r\n" +"double inst_cnt[NUM_INST];\r\n" +"\r\n" +"static wmops_record *wmops = NULL;\r\n" +"static int num_wmops_records, max_num_wmops_records;\r\n" +"static int current_record;\r\n" +"static long update_cnt;\r\n" +"static double start_cnt;\r\n" +"static double max_cnt;\r\n" +"static double min_cnt;\r\n" +"static double inst_cnt_wc[NUM_INST];\r\n" +"static long fnum_cnt_wc;\r\n" +"static int *wmops_caller_stack = NULL, wmops_caller_stack_index, max_wmops_caller_stack_index = 0;\r\n" +"static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0;\r\n" +"\r\n" +"static BASIC_OP op_weight = {\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 2, 2, 1,\r\n" +" 1, 1, 1, 2, 1,\r\n" +"\r\n" +" 1, 1, 1, 2, 1,\r\n" +" 1, 1, 18, 1, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 2, 2, 2, 2, 1,\r\n" +"\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 1, 2,\r\n" +" 1, 2, 2, 2, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +"\r\n" +" 1, 1, 1, 1, 3,\r\n" +" 3, 3, 3, 1, 1,\r\n" +" 1, 1, 1, 1, 1,\r\n" +" 1, 1, 1, 3, 2,\r\n" +" 2, 6, 3, 3, 2,\r\n" +"\r\n" +" 1, 32, 1\r\n" +"\r\n" +"/* New complex basops */\r\n" +"#ifdef COMPLEX_OPERATOR\r\n" +" ,\r\n" +" 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1\r\n" +"\r\n" +" ,\r\n" +" 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1\r\n" +"\r\n" +"#endif /* #ifdef COMPLEX_OPERATOR */\r\n" +"\r\n" +"#ifdef ENH_64_BIT_OPERATOR\r\n" +" /* Weights of new 64 bit basops */\r\n" +" ,\r\n" +" 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\r\n" +"#endif /* #ifdef ENH_64_BIT_OPERATOR */\r\n" +"\r\n" +"#ifdef ENH_32_BIT_OPERATOR\r\n" +" ,\r\n" +" 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\r\n" +"#endif /* #ifdef ENH_32_BIT_OPERATOR */\r\n" +"\r\n" +"#ifdef ENH_U_32_BIT_OPERATOR\r\n" +" ,\r\n" +" 1, 1, 1, 2, 2, 1, 1\r\n" +"#endif /* #ifdef ENH_U_32_BIT_OPERATOR */\r\n" +"\r\n" +"#ifdef CONTROL_CODE_OPS\r\n" +" ,\r\n" +" 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\r\n" +"#endif /* #ifdef CONTROL_CODE_OPS */\r\n" +"};\r\n" +"\r\n" +"BASIC_OP *multiCounter = NULL;\r\n" +"unsigned int currCounter = 0;\r\n" +"int funcId_where_last_call_to_else_occurred;\r\n" +"long funcid_total_wmops_at_last_call_to_else;\r\n" +"int call_occurred = 1;\r\n" +"char func_name_where_last_call_to_else_occurred[MAX_FUNCTION_NAME_LENGTH + 1];\r\n" +"\r\n" +"void reset_wmops( void )\r\n" +"{\r\n" +" int i, j;\r\n" +"\r\n" +" num_wmops_records = 0;\r\n" +" max_num_wmops_records = MAX_NUM_RECORDS;\r\n" +" current_record = -1;\r\n" +" update_cnt = 0;\r\n" +"\r\n" +" max_cnt = 0.0;\r\n" +" min_cnt = DOUBLE_MAX;\r\n" +" start_cnt = 0.0;\r\n" +" ops_cnt = 0.0;\r\n" +"\r\n" +" /* allocate the list of WMOPS records */\r\n" +" if ( wmops == NULL )\r\n" +" {\r\n" +" wmops = (wmops_record *) malloc( max_num_wmops_records * sizeof( wmops_record ) );\r\n" +" }\r\n" +"\r\n" +" if ( wmops == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Records!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" /* allocate the list of BASOP WMOPS records */\r\n" +" if ( multiCounter == NULL )\r\n" +" {\r\n" +" multiCounter = (BASIC_OP *) malloc( max_num_wmops_records * sizeof( BASIC_OP ) );\r\n" +" }\r\n" +"\r\n" +" if ( multiCounter == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Error: Unable to Allocate the BASOP WMOPS counter!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" /* initilize the list of WMOPS records */\r\n" +" /* initilize BASOP operation counters */\r\n" +" for ( i = 0; i < max_num_wmops_records; i++ )\r\n" +" {\r\n" +" strcpy( &wmops[i].label[0], \"\\0\" );\r\n" +" wmops[i].call_number = 0;\r\n" +" wmops[i].update_cnt = 0;\r\n" +" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n" +" {\r\n" +" wmops[i].call_tree[j] = -1;\r\n" +" }\r\n" +" wmops[i].start_selfcnt = 0.0;\r\n" +" wmops[i].current_selfcnt = 0.0;\r\n" +" wmops[i].max_selfcnt = 0.0;\r\n" +" wmops[i].min_selfcnt = DOUBLE_MAX;\r\n" +" wmops[i].tot_selfcnt = 0.0;\r\n" +" wmops[i].start_cnt = 0.0;\r\n" +" wmops[i].current_cnt = 0.0;\r\n" +" wmops[i].max_cnt = 0.0;\r\n" +" wmops[i].min_cnt = DOUBLE_MAX;\r\n" +" wmops[i].tot_cnt = 0.0;\r\n" +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" +" wmops[i].wc_cnt = 0.0;\r\n" +" wmops[i].wc_selfcnt = 0.0;\r\n" +" wmops[i].current_call_number = 0;\r\n" +" wmops[i].wc_call_number = -1;\r\n" +"#endif\r\n" +"\r\n" +" /* Reset BASOP operation counter */\r\n" +" Reset_BASOP_WMOPS_counter( i );\r\n" +" }\r\n" +"\r\n" +" /* allocate the list of wmops callers to track the sequence of function calls */\r\n" +" wmops_caller_stack_index = 0;\r\n" +" max_wmops_caller_stack_index = MAX_NUM_RECORDS;\r\n" +" if ( wmops_caller_stack == NULL )\r\n" +" {\r\n" +" wmops_caller_stack = malloc( max_wmops_caller_stack_index * sizeof( int ) );\r\n" +" }\r\n" +"\r\n" +" if ( wmops_caller_stack == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Callers!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" for ( i = 0; i < max_wmops_caller_stack_index; i++ )\r\n" +" {\r\n" +" wmops_caller_stack[i] = -1;\r\n" +" }\r\n" +"\r\n" +" /* initialize auxiliary BASOP counter variables */\r\n" +" currCounter = 0; /* Note: currCounter cannot be set to -1 because it's defined as unsigned int ! */\r\n" +" call_occurred = 1;\r\n" +" funcId_where_last_call_to_else_occurred = -100;\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"void push_wmops_fct( const char *label, ... )\r\n" +"{\r\n" +" int new_flag;\r\n" +" int i, j, index_record;\r\n" +" long tot;\r\n" +" va_list arg;\r\n" +" char func_name[MAX_FUNCTION_NAME_LENGTH] = \"\";\r\n" +"\r\n" +" /* concatenate all function name labels into a single string */\r\n" +" va_start( arg, label );\r\n" +" while ( label )\r\n" +" {\r\n" +" strcat( func_name, label );\r\n" +" label = va_arg( arg, const char * );\r\n" +" }\r\n" +" va_end( arg );\r\n" +"\r\n" +" /* Check, if this is a new function label */\r\n" +" new_flag = 1;\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" +" {\r\n" +" if ( strcmp( wmops[i].label, func_name ) == 0 )\r\n" +" {\r\n" +" new_flag = 0;\r\n" +" break;\r\n" +" }\r\n" +" }\r\n" +" index_record = i;\r\n" +"\r\n" +" /* Create a new WMOPS record in the list */\r\n" +" if ( new_flag )\r\n" +" {\r\n" +" if ( num_wmops_records >= max_num_wmops_records )\r\n" +" {\r\n" +" /* There is no room for a new WMOPS record -> reallocate the list */\r\n" +" max_num_wmops_records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" wmops = realloc( wmops, max_num_wmops_records * sizeof( wmops_record ) );\r\n" +" multiCounter = realloc( multiCounter, max_num_wmops_records * sizeof( BASIC_OP ) );\r\n" +" }\r\n" +"\r\n" +" /* initilize the new WMOPS record */\r\n" +" strcpy( &wmops[index_record].label[0], \"\\0\" );\r\n" +" wmops[index_record].call_number = 0;\r\n" +" wmops[index_record].update_cnt = 0;\r\n" +" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n" +" {\r\n" +" wmops[index_record].call_tree[j] = -1;\r\n" +" }\r\n" +" wmops[index_record].start_selfcnt = 0.0;\r\n" +" wmops[index_record].current_selfcnt = 0.0;\r\n" +" wmops[index_record].max_selfcnt = 0.0;\r\n" +" wmops[index_record].min_selfcnt = DOUBLE_MAX;\r\n" +" wmops[index_record].tot_selfcnt = 0.0;\r\n" +" wmops[index_record].start_cnt = 0.0;\r\n" +" wmops[index_record].current_cnt = 0.0;\r\n" +" wmops[index_record].max_cnt = 0.0;\r\n" +" wmops[index_record].min_cnt = DOUBLE_MAX;\r\n" +" wmops[index_record].tot_cnt = 0.0;\r\n" +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" +" wmops[index_record].wc_cnt = 0.0;\r\n" +" wmops[index_record].wc_selfcnt = 0.0;\r\n" +" wmops[index_record].current_call_number = 0;\r\n" +" wmops[index_record].wc_call_number = -1;\r\n" +"#endif\r\n" +"\r\n" +" /* Reset BASOP operation counter */\r\n" +" Reset_BASOP_WMOPS_counter( index_record );\r\n" +"\r\n" +" strcpy( wmops[index_record].label, func_name );\r\n" +"\r\n" +" num_wmops_records++;\r\n" +" }\r\n" +"\r\n" +" /* Update the WMOPS context info of the old record before switching to the new one */\r\n" +" if ( current_record >= 0 )\r\n" +" {\r\n" +" if ( wmops_caller_stack_index >= max_wmops_caller_stack_index )\r\n" +" {\r\n" +" /* There is no room for a new record -> reallocate the list */\r\n" +" max_wmops_caller_stack_index += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" wmops_caller_stack = realloc( wmops_caller_stack, max_wmops_caller_stack_index * sizeof( int ) );\r\n" +" }\r\n" +" wmops_caller_stack[wmops_caller_stack_index++] = current_record;\r\n" +"\r\n" +" /* add the BASOP complexity to the counter and update the old WMOPS counter */\r\n" +" tot = DeltaWeightedOperation( current_record );\r\n" +" ops_cnt += tot;\r\n" +" wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n" +"\r\n" +" /* update call tree */\r\n" +" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n" +" {\r\n" +" if ( wmops[index_record].call_tree[j] == current_record )\r\n" +" {\r\n" +" break;\r\n" +" }\r\n" +" else if ( wmops[index_record].call_tree[j] == -1 )\r\n" +" {\r\n" +" wmops[index_record].call_tree[j] = current_record;\r\n" +" break;\r\n" +" }\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* Need to reset the BASOP operation counter of the 0th record in every push_wmops() */\r\n" +" /* because currCounter can never be -1 */\r\n" +" if ( current_record == -1 && index_record == 0 )\r\n" +" {\r\n" +" wmops[index_record].LastWOper = TotalWeightedOperation( index_record );\r\n" +" }\r\n" +"\r\n" +" /* switch to the new record */\r\n" +" current_record = index_record;\r\n" +" wmops[index_record].start_selfcnt = ops_cnt;\r\n" +" wmops[index_record].start_cnt = ops_cnt;\r\n" +" wmops[index_record].call_number++;\r\n" +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" +" wmops[index_record].current_call_number++;\r\n" +"#endif\r\n" +"\r\n" +" /* set the ID of the current BASOP operations counter */\r\n" +" currCounter = index_record;\r\n" +" call_occurred = 1;\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"void pop_wmops( void )\r\n" +"{\r\n" +" long tot;\r\n" +"\r\n" +" /* Check for underflow */\r\n" +" if ( current_record < 0 )\r\n" +" {\r\n" +" fprintf( stdout, \"\\r pop_wmops(): stack underflow, too many calls to pop_wmops()\\n\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" /* add the BASOP complexity to the counter */\r\n" +" tot = DeltaWeightedOperation( currCounter );\r\n" +" ops_cnt += tot;\r\n" +"\r\n" +" /* update count of current record */\r\n" +" wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n" +" wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt;\r\n" +"\r\n" +" /* Get back previous context from stack */\r\n" +" if ( wmops_caller_stack_index > 0 )\r\n" +" {\r\n" +" current_record = wmops_caller_stack[--wmops_caller_stack_index];\r\n" +" wmops[current_record].start_selfcnt = ops_cnt;\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" current_record = -1;\r\n" +" }\r\n" +"\r\n" +" /* set the ID of the previous BASOP operations counter */\r\n" +" if ( current_record == -1 )\r\n" +" {\r\n" +" currCounter = 0; /* Note: currCounter cannot be set to -1 because it's defined as unsigned int ! */\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" currCounter = current_record;\r\n" +" }\r\n" +" call_occurred = 1;\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"\r\n" +"void update_wmops( void )\r\n" +"{\r\n" +" int i;\r\n" +" double current_cnt;\r\n" +"#ifdef WMOPS_PER_FRAME\r\n" +" static FILE *fid = NULL;\r\n" +" const char filename[] = \"wmops_analysis\";\r\n" +" float tmpF;\r\n" +"#endif\r\n" +"\r\n" +" if ( wmops_caller_stack_index != 0 )\r\n" +" {\r\n" +" fprintf( stdout, \"update_wmops(): WMOPS caller stack corrupted - check that all push_wmops() are matched with pop_wmops()!\\n\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +"#ifdef WMOPS_PER_FRAME\r\n" +" /* Check, if the output file has already been opened */\r\n" +" if ( fid == NULL )\r\n" +" {\r\n" +" fid = fopen( filename, \"wb\" );\r\n" +"\r\n" +" if ( fid == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", filename );\r\n" +" exit( -1 );\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* Write current complexity to the external file */\r\n" +" tmpF = (float) ( FAC * wmops[0].current_cnt );\r\n" +" fwrite( &tmpF, sizeof( float ), 1, fid );\r\n" +"#endif\r\n" +"\r\n" +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" +" if ( ops_cnt - start_cnt > max_cnt )\r\n" +" {\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" +" {\r\n" +" wmops[i].wc_cnt = wmops[i].current_cnt;\r\n" +" wmops[i].wc_selfcnt = wmops[i].current_selfcnt;\r\n" +" wmops[i].wc_call_number = wmops[i].current_call_number;\r\n" +" }\r\n" +" }\r\n" +"#endif\r\n" +"\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" +" {\r\n" +" wmops[i].tot_selfcnt += wmops[i].current_selfcnt;\r\n" +" wmops[i].tot_cnt += wmops[i].current_cnt;\r\n" +"\r\n" +" if ( wmops[i].current_selfcnt > 0 )\r\n" +" {\r\n" +" if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt )\r\n" +" {\r\n" +" wmops[i].max_selfcnt = wmops[i].current_selfcnt;\r\n" +" }\r\n" +"\r\n" +" if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt )\r\n" +" {\r\n" +" wmops[i].min_selfcnt = wmops[i].current_selfcnt;\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" wmops[i].current_selfcnt = 0;\r\n" +"\r\n" +" if ( wmops[i].current_cnt > 0 )\r\n" +" {\r\n" +" if ( wmops[i].current_cnt > wmops[i].max_cnt )\r\n" +" {\r\n" +" wmops[i].max_cnt = wmops[i].current_cnt;\r\n" +" }\r\n" +"\r\n" +"\r\n" +" if ( wmops[i].current_cnt < wmops[i].min_cnt )\r\n" +" {\r\n" +" wmops[i].min_cnt = wmops[i].current_cnt;\r\n" +" }\r\n" +"\r\n" +" wmops[i].update_cnt++;\r\n" +" }\r\n" +"\r\n" +" wmops[i].current_cnt = 0;\r\n" +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" +" wmops[i].current_call_number = 0;\r\n" +"#endif\r\n" +"\r\n" +" /* reset the BASOP operations counter */\r\n" +" call_occurred = 1;\r\n" +" Reset_BASOP_WMOPS_counter( i );\r\n" +" }\r\n" +"\r\n" +" current_cnt = ops_cnt - start_cnt;\r\n" +" if ( current_cnt > max_cnt )\r\n" +" {\r\n" +" max_cnt = current_cnt;\r\n" +"\r\n" +" for ( i = 0; i < NUM_INST; i++ )\r\n" +" {\r\n" +" inst_cnt_wc[i] = inst_cnt[i];\r\n" +" }\r\n" +"\r\n" +" fnum_cnt_wc = update_cnt + 1;\r\n" +" }\r\n" +"\r\n" +" if ( current_cnt < min_cnt )\r\n" +" {\r\n" +" min_cnt = current_cnt;\r\n" +" }\r\n" +"\r\n" +" for ( i = 0; i < NUM_INST; i++ )\r\n" +" {\r\n" +" inst_cnt[i] = 0.0;\r\n" +" }\r\n" +"\r\n" +" start_cnt = ops_cnt;\r\n" +"\r\n" +" /* increment frame counter */\r\n" +" update_cnt++;\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"void print_wmops( void )\r\n" +"{\r\n" +" int i, label_len, max_label_len;\r\n" +"\r\n" +" char *sfmts = \"%*s %8s %8s %7s %7s\\n\";\r\n" +" char *dfmts = \"%*s %8.2f %8.3f %7.3f %7.3f\\n\";\r\n" +" char *sfmt = \"%*s %8s %8s %7s %7s %7s %7s %7s\\n\";\r\n" +" char *dfmt = \"%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\\n\";\r\n" +"\r\n" +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" +" int j;\r\n" +" char *sfmtt = \"%20s %4s %15s\\n\";\r\n" +" char *dfmtt = \"%20s %4d \";\r\n" +"#endif\r\n" +"\r\n" +" /* calculate maximum label length for compact prinout */\r\n" +" max_label_len = 0;\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" +" {\r\n" +" label_len = strlen( wmops[i].label );\r\n" +" if ( label_len > max_label_len )\r\n" +" {\r\n" +" max_label_len = label_len;\r\n" +" }\r\n" +" }\r\n" +" max_label_len += 4;\r\n" +"\r\n" +" fprintf( stdout, \"\\n\\n --- Complexity analysis [WMOPS] --- \\n\\n\" );\r\n" +"\r\n" +" fprintf( stdout, \"%*s %33s %23s\\n\", max_label_len, \"\", \"|------ SELF ------|\", \"|--- CUMULATIVE ---|\" );\r\n" +" fprintf( stdout, sfmt, max_label_len, \" routine\", \" calls\", \" min \", \" max \", \" avg \", \" min \", \" max \", \" avg \" );\r\n" +" fprintf( stdout, sfmt, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\" );\r\n" +"\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" +" {\r\n" +" fprintf( stdout, dfmt, max_label_len, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt,\r\n" +" wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt,\r\n" +" FAC * wmops[i].max_selfcnt,\r\n" +" wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt,\r\n" +" wmops[i].min_cnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_cnt,\r\n" +" FAC * wmops[i].max_cnt,\r\n" +" wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt );\r\n" +" }\r\n" +"\r\n" +" fprintf( stdout, sfmts, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\" );\r\n" +" fprintf( stdout, dfmts, max_label_len, \"total\", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt );\r\n" +" fprintf( stdout, \"\\n\" );\r\n" +"\r\n" +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" +" fprintf( stdout, \"\\nComplexity analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n" +" fprintf( stdout, \"%*s %8s %10s %12s\\n\", max_label_len, \" routine\", \" calls\", \" SELF\", \" CUMULATIVE\" );\r\n" +" fprintf( stdout, \"%*s %8s %10s %10s\\n\", max_label_len, \"---------------\", \"------\", \"------\", \"----------\" );\r\n" +"\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" +" {\r\n" +" if ( wmops[i].wc_call_number > 0 )\r\n" +" {\r\n" +" fprintf( stdout, \"%*s %8d %10.3f %12.3f\\n\", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt );\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" fprintf( stdout, \"\\nCall tree for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n" +" fprintf( stdout, sfmtt, \" function\", \"num\", \"called by \" );\r\n" +" fprintf( stdout, sfmtt, \"---------------\", \"---\", \"--------------\" );\r\n" +"\r\n" +" for ( i = 0; i < num_wmops_records; i++ )\r\n" +" {\r\n" +" if ( wmops[i].wc_call_number > 0 )\r\n" +" {\r\n" +" fprintf( stdout, dfmtt, wmops[i].label, i );\r\n" +" for ( j = 0; wmops[i].call_tree[j] != -1 && j < MAX_CALL_TREE_DEPTH; j++ )\r\n" +" {\r\n" +" if ( j != 0 )\r\n" +" {\r\n" +" fprintf( stdout, \", \" );\r\n" +" }\r\n" +" fprintf( stdout, \"%d\", wmops[i].call_tree[j] );\r\n" +" }\r\n" +" fprintf( stdout, \"\\n\" );\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" fprintf( stdout, \"\\n\\n\" );\r\n" +"\r\n" +" fprintf( stdout, \"\\nInstruction type analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n" +" for ( i = 0; i < NUM_INST; i++ )\r\n" +" {\r\n" +" switch ( (enum instructions) i )\r\n" +" {\r\n" +" case _ADD:\r\n" +" fprintf( stdout, \"\\tAdds: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _ABS:\r\n" +" fprintf( stdout, \"\\tAbsolutes: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _MULT:\r\n" +" fprintf( stdout, \"\\tMultiplies: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _MAC:\r\n" +" fprintf( stdout, \"\\tMACs: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _MOVE:\r\n" +" fprintf( stdout, \"\\tMoves: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _STORE:\r\n" +" fprintf( stdout, \"\\tStores: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _LOGIC:\r\n" +" fprintf( stdout, \"\\tLogicals: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _SHIFT:\r\n" +" fprintf( stdout, \"\\tShifts: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _BRANCH:\r\n" +" fprintf( stdout, \"\\tBranches: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _DIV:\r\n" +" fprintf( stdout, \"\\tDivisions: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _SQRT:\r\n" +" fprintf( stdout, \"\\tSquare Root: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _TRANS:\r\n" +" fprintf( stdout, \"\\tTrans: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _FUNC:\r\n" +" fprintf( stdout, \"\\tFunc Call: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _LOOP:\r\n" +" fprintf( stdout, \"\\tLoop Init: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _INDIRECT:\r\n" +" fprintf( stdout, \"\\tIndirect Addr: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _PTR_INIT:\r\n" +" fprintf( stdout, \"\\tPointer Init: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _TEST:\r\n" +" fprintf( stdout, \"\\tExtra condit.: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _POWER:\r\n" +" fprintf( stdout, \"\\tExponential: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _LOG:\r\n" +" fprintf( stdout, \"\\tLogarithm: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" case _MISC:\r\n" +" fprintf( stdout, \"\\tAll other op.: %12.1f\\n\", inst_cnt_wc[i] );\r\n" +" break;\r\n" +" default:\r\n" +" fprintf( stdout, \"\\tERROR: Invalid instruction type: %d\\n\\n\", i );\r\n" +" }\r\n" +" }\r\n" +"#endif\r\n" +"\r\n" +" /* De-allocate the list of wmops record */\r\n" +" if ( wmops != NULL )\r\n" +" {\r\n" +" free( wmops );\r\n" +" }\r\n" +"\r\n" +" /* De-allocate the list of wmops caller functions */\r\n" +" if ( wmops_caller_stack != NULL )\r\n" +" {\r\n" +" free( wmops_caller_stack );\r\n" +" }\r\n" +"\r\n" +" /* De-allocate the BASOP WMOPS counter */\r\n" +" if ( multiCounter != NULL )\r\n" +" {\r\n" +" free( multiCounter );\r\n" +" }\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * Memory counting tool measuring RAM usage (stack and heap)\r\n" +" *\r\n" +" * Maximum RAM is measured by monitoring the total allocated memory (stack and heap) in each frame.\r\n" +" *\r\n" +" * Maximum stack is measured by monitoring the difference between the 'top' and 'bottom' of the stack. The 'bottom' of the stack is updated in each function\r\n" +" * with a macro 'func_start_' which is inserted automatically to all functions during the instrumentation process.\r\n" +" *\r\n" +" * Maximum heap is measured by summing the sizes of all memory blocks allocated by malloc() or calloc() and deallocated by free(). The maximum heap size is\r\n" +" * updated each time when the macros malloc_() or calloc_() is invoked. The macros 'malloc_ and calloc_' are inserted automatically during the instrumentation process.\r\n" +" * As part of heap measurements, intra-frame heap and inter-frame heap are measured separately. Intra-frame heap refers to heap memory which is allocated and deallocated\r\n" +" * within a single frame. Inter-frame heap, on the contrary, refers to heap memory which is reserved for more than one frame.\r\n" +" *\r\n" +" * In order to run the memory counting tool the function reset_mem(cnt_size) must be called at the beginning of the encoding/decoding process.\r\n" +" * The unit in which memory consumption is reported is set via the parameter 'cnt_size'. It can be set to 0 (bytes), 1 (32b words) or 2 (64b words).\r\n" +" * At the end of the encoding/decoding process, 'print_mem()' function may be called to print basic information about memory consumption. If the macro 'MEM_COUNT_DETAILS'\r\n" +" * is activated, detailed information is printed\r\n" +" *\r\n" +" * The macro 'WMOPS' needs to be activated to enable memory counting. To avoid the instrumentation of malloc()/calloc()/free() calls, use\r\n" +" * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free().\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"\r\n" +"/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using\r\n" +" a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */\r\n" +"#ifdef MEM_ALIGN_64BITS\r\n" +"#define BLOCK_ROUNDING 8 /* Align on 64 Bits */\r\n" +"#else\r\n" +"#define BLOCK_ROUNDING 4 /* Align on 32 Bits */\r\n" +"#endif\r\n" +"\r\n" +"#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) )\r\n" +"\r\n" +"#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */\r\n" +"#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */\r\n" +"#define OOB_START 0x1 /* int indicating out-of-bounds access before memory block */\r\n" +"#define OOB_END 0x2 /* int indicating out-of-bounds access after memory block */\r\n" +"\r\n" +"#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) )\r\n" +"#define IS_CALLOC( str ) ( str[0] == 'c' )\r\n" +"\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +"const char *csv_filename = \"mem_analysis.csv\";\r\n" +"static FILE *fid_csv_filename = NULL;\r\n" +"#endif\r\n" +"\r\n" +"typedef struct\r\n" +"{\r\n" +" char function_name[MAX_FUNCTION_NAME_LENGTH + 1];\r\n" +" int16_t *stack_ptr;\r\n" +"} caller_info;\r\n" +"\r\n" +"static caller_info *stack_callers[2] = { NULL, NULL };\r\n" +"\r\n" +"static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */\r\n" +"static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */\r\n" +"static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */\r\n" +"static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */\r\n" +"static int current_calls = 0, max_num_calls = MAX_NUM_RECORDS;\r\n" +"static char location_max_stack[256] = \"undefined\";\r\n" +"\r\n" +"typedef struct\r\n" +"{\r\n" +" char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */\r\n" +" char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */\r\n" +" unsigned long hash;\r\n" +" int lineno;\r\n" +" void *block_ptr;\r\n" +" int block_size;\r\n" +" unsigned long total_block_size; /* Cumulative sum of the allocated size in the session */\r\n" +" unsigned long total_used_size; /* Cumulative sum of the used size in the session */\r\n" +" int wc_heap_size_intra_frame; /* Worst-Case Intra-Frame Heap Size */\r\n" +" int wc_heap_size_inter_frame; /* Worst-Case Inter-Frame Heap Size */\r\n" +" int frame_allocated; /* Frame number in which the Memory Block has been allocated (-1 if not allocated at the moment) */\r\n" +" int OOB_Flag;\r\n" +" int noccurances; /* Number of times that the memory block has been allocated in a frame */\r\n" +"} allocator_record;\r\n" +"\r\n" +"allocator_record *allocation_list = NULL;\r\n" +"\r\n" +"static int Num_Records, Max_Num_Records;\r\n" +"static size_t Stat_Cnt_Size = USE_BYTES;\r\n" +"static const char *Count_Unit[] = { \"bytes\", \"words\", \"words\", \"words\" };\r\n" +"\r\n" +"static int32_t wc_ram_size, wc_ram_frame;\r\n" +"static int32_t current_heap_size;\r\n" +"static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap;\r\n" +"static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap;\r\n" +"static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap;\r\n" +"\r\n" +"/* Local Functions */\r\n" +"static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str );\r\n" +"allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record );\r\n" +"static void *mem_alloc_block( size_t size, const char *size_str );\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * reset_mem()\r\n" +" *\r\n" +" * Initialize/reset memory counting tool (stack and heap)\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"void reset_mem( Counting_Size cnt_size )\r\n" +"{\r\n" +" int16_t something;\r\n" +" size_t tmp_size;\r\n" +"\r\n" +" /* initialize list of stack records */\r\n" +" if ( stack_callers[0] == NULL )\r\n" +" {\r\n" +" stack_callers[0] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n" +" stack_callers[1] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n" +" }\r\n" +"\r\n" +" if ( stack_callers[0] == NULL || stack_callers[1] == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Error: Unable to Allocate List of Stack Records!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" current_calls = 0;\r\n" +" max_num_calls = MAX_NUM_RECORDS;\r\n" +"\r\n" +" /* initialize stack pointers */\r\n" +" ptr_base_stack = &something;\r\n" +" ptr_max_stack = ptr_base_stack;\r\n" +" ptr_current_stack = ptr_base_stack;\r\n" +"\r\n" +" /* initialize the unit of memory block size */\r\n" +" Stat_Cnt_Size = cnt_size;\r\n" +"\r\n" +" /* Check, if sizeof(int32_t) is 4 bytes */\r\n" +" tmp_size = sizeof( int32_t );\r\n" +" if ( tmp_size != 4 )\r\n" +" {\r\n" +" fprintf( stderr, \"Error: Expecting 'int32_t' to be a 32 Bits Integer!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" /* create allocation list for malloc() memory blocks */\r\n" +" if ( allocation_list == NULL )\r\n" +" {\r\n" +" allocation_list = malloc( MAX_NUM_RECORDS * sizeof( allocator_record ) );\r\n" +" }\r\n" +"\r\n" +" if ( allocation_list == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Error: Unable to Create List of Memory Blocks!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" Num_Records = 0;\r\n" +" Max_Num_Records = MAX_NUM_RECORDS;\r\n" +"\r\n" +" wc_ram_size = 0;\r\n" +" wc_ram_frame = -1;\r\n" +" current_heap_size = 0;\r\n" +"\r\n" +" /* heap allocation tree */\r\n" +" heap_allocation_call_tree_max_size = MAX_NUM_RECORDS;\r\n" +" if ( heap_allocation_call_tree == NULL )\r\n" +" {\r\n" +" heap_allocation_call_tree = (int *) malloc( heap_allocation_call_tree_max_size * sizeof( int ) );\r\n" +" memset( heap_allocation_call_tree, -1, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n" +" }\r\n" +" heap_allocation_call_tree_size = 0;\r\n" +"\r\n" +" /* wc intra-frame heap */\r\n" +" max_items_wc_intra_frame_heap = MAX_NUM_RECORDS;\r\n" +" if ( list_wc_intra_frame_heap == NULL )\r\n" +" {\r\n" +" list_wc_intra_frame_heap = (int *) malloc( max_items_wc_intra_frame_heap * sizeof( int ) );\r\n" +" memset( list_wc_intra_frame_heap, -1, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n" +" }\r\n" +" n_items_wc_intra_frame_heap = 0;\r\n" +" size_wc_intra_frame_heap = 0;\r\n" +" location_wc_intra_frame_heap = -1;\r\n" +"\r\n" +" /* current inter-frame heap */\r\n" +" max_items_current_inter_frame_heap = MAX_NUM_RECORDS;\r\n" +" if ( list_current_inter_frame_heap == NULL )\r\n" +" {\r\n" +" list_current_inter_frame_heap = (int *) malloc( max_items_current_inter_frame_heap * sizeof( int ) );\r\n" +" memset( list_current_inter_frame_heap, -1, max_items_current_inter_frame_heap * sizeof( int ) );\r\n" +" }\r\n" +" n_items_current_inter_frame_heap = 0;\r\n" +" size_current_inter_frame_heap = 0;\r\n" +"\r\n" +" /* wc inter-frame heap */\r\n" +" max_items_wc_inter_frame_heap = MAX_NUM_RECORDS;\r\n" +" if ( list_wc_inter_frame_heap == NULL )\r\n" +" {\r\n" +" list_wc_inter_frame_heap = (int *) malloc( max_items_wc_inter_frame_heap * sizeof( int ) );\r\n" +" memset( list_wc_inter_frame_heap, -1, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n" +" }\r\n" +" n_items_wc_inter_frame_heap = 0;\r\n" +" size_wc_inter_frame_heap = 0;\r\n" +" location_wc_inter_frame_heap = -1;\r\n" +"\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +" /* Check, if the .csv file has already been opened */\r\n" +" if ( fid_csv_filename == NULL )\r\n" +" {\r\n" +" fid_csv_filename = fopen( csv_filename, \"wb\" );\r\n" +"\r\n" +" if ( fid_csv_filename == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", csv_filename );\r\n" +" exit( -1 );\r\n" +" }\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" /* reset file */\r\n" +" rewind( fid_csv_filename );\r\n" +" }\r\n" +"#endif\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * reset_stack()\r\n" +" *\r\n" +" * Reset stack pointer\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"void reset_stack( void )\r\n" +"{\r\n" +" int16_t something;\r\n" +"\r\n" +" /* initialize/reset stack pointers */\r\n" +" ptr_base_stack = &something;\r\n" +" ptr_max_stack = ptr_base_stack;\r\n" +" ptr_current_stack = ptr_base_stack;\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * push_stack()\r\n" +" *\r\n" +" * Check the current stack pointer and update the maximum stack pointer, if new maximum found.\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"int push_stack( const char *filename, const char *fctname )\r\n" +"{\r\n" +" int16_t something;\r\n" +" int32_t current_stack_size;\r\n" +"\r\n" +" ptr_current_stack = &something;\r\n" +"\r\n" +" (void) *filename; /* to avoid compilation warning */\r\n" +"\r\n" +" if ( current_calls >= max_num_calls )\r\n" +" {\r\n" +" /* There is no room for a new record -> reallocate the list */\r\n" +" max_num_calls += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" stack_callers[0] = realloc( stack_callers[0], max_num_calls * sizeof( caller_info ) );\r\n" +" stack_callers[1] = realloc( stack_callers[1], max_num_calls * sizeof( caller_info ) );\r\n" +" }\r\n" +"\r\n" +" /* Valid Function Name? */\r\n" +" if ( fctname[0] == 0 )\r\n" +" { /* No */\r\n" +" fprintf( stderr, \"Invalid function name for call stack info.\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" /* Save the Name of the Calling Function in the Table */\r\n" +" strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FUNCTION_NAME_LENGTH );\r\n" +" stack_callers[0][current_calls].function_name[MAX_FUNCTION_NAME_LENGTH] = 0; /* Nul Terminate */\r\n" +"\r\n" +" /* Save the Stack Pointer */\r\n" +" stack_callers[0][current_calls].stack_ptr = ptr_current_stack;\r\n" +"\r\n" +" /* Increase the Number of Calls in the List */\r\n" +" current_calls++;\r\n" +"\r\n" +" /* Is this the First Time or the Worst Case? */\r\n" +" if ( ptr_current_stack < ptr_max_stack || ptr_max_stack == NULL )\r\n" +" { /* Yes */\r\n" +" /* Save Info about it */\r\n" +" ptr_max_stack = ptr_current_stack;\r\n" +"\r\n" +" /* save the worst-case frame number */\r\n" +" /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */\r\n" +" wc_stack_frame = update_cnt;\r\n" +" strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 );\r\n" +" location_max_stack[sizeof( location_max_stack ) - 1] = '\\0';\r\n" +"\r\n" +" /* Save Call Tree */\r\n" +" memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls );\r\n" +"\r\n" +" /* Terminate the List with 0 (for printing purposes) */\r\n" +" if ( current_calls < max_num_calls )\r\n" +" {\r\n" +" stack_callers[1][current_calls].function_name[0] = 0;\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* Check, if This is the New Worst-Case RAM (stack + heap) */\r\n" +" current_stack_size = ( int32_t )( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) );\r\n" +"\r\n" +" if ( current_stack_size < 0 )\r\n" +" {\r\n" +" /* prevent negative stack size */\r\n" +" current_stack_size = 0;\r\n" +" }\r\n" +"\r\n" +" if ( current_stack_size + current_heap_size > wc_ram_size )\r\n" +" {\r\n" +" wc_ram_size = current_stack_size + current_heap_size;\r\n" +" wc_ram_frame = update_cnt;\r\n" +" }\r\n" +"\r\n" +" return 0 /* for Now */;\r\n" +"}\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * pop_stack()\r\n" +" *\r\n" +" * Remove stack caller entry from the list\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"int pop_stack( const char *filename, const char *fctname )\r\n" +"{\r\n" +" caller_info *caller_info_ptr;\r\n" +"\r\n" +" (void) *filename; /* to avoid compilation warning */\r\n" +"\r\n" +" /* Decrease the Number of Records */\r\n" +" current_calls--;\r\n" +"\r\n" +" /* Get Pointer to Caller Information */\r\n" +" caller_info_ptr = &stack_callers[0][current_calls];\r\n" +"\r\n" +" /* Check, if the Function Names Match */\r\n" +" if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 )\r\n" +" {\r\n" +" fprintf( stderr, \"Invalid usage of pop_stack()\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" /* Erase Entry */\r\n" +" caller_info_ptr->function_name[0] = 0;\r\n" +"\r\n" +" /* Retrieve previous stack pointer */\r\n" +" if ( current_calls == 0 )\r\n" +" {\r\n" +" ptr_current_stack = ptr_base_stack;\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" ptr_current_stack = stack_callers[0][current_calls - 1].stack_ptr;\r\n" +" }\r\n" +"\r\n" +" return 0 /* for Now */;\r\n" +"}\r\n" +"\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * print_stack_call_tree()\r\n" +" *\r\n" +" * Print detailed information about worst-case stack usage\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"static void print_stack_call_tree( void )\r\n" +"{\r\n" +" caller_info *caller_info_ptr;\r\n" +" int call_level;\r\n" +" char fctname[MAX_FUNCTION_NAME_LENGTH + 1];\r\n" +"\r\n" +" fprintf( stdout, \"\\nList of functions when maximum stack size is reached:\\n\\n\" );\r\n" +"\r\n" +" caller_info_ptr = &stack_callers[1][0];\r\n" +" for ( call_level = 0; call_level < max_num_calls; call_level++ )\r\n" +" {\r\n" +" /* Done? */\r\n" +" if ( caller_info_ptr->function_name[0] == 0 )\r\n" +" {\r\n" +" break;\r\n" +" }\r\n" +"\r\n" +" /* Print Name */\r\n" +" strncpy( fctname, caller_info_ptr->function_name, MAX_FUNCTION_NAME_LENGTH );\r\n" +" strcat( fctname, \"()\" );\r\n" +" fprintf( stdout, \"%-42s\", fctname );\r\n" +"\r\n" +" /* Print Stack Usage (Based on Difference) */\r\n" +" if ( call_level != 0 )\r\n" +" {\r\n" +" fprintf( stdout, \"%lu %s\\n\", ( ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" fprintf( stdout, \"%lu %s\\n\", ( ( ptr_base_stack - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n" +" }\r\n" +"\r\n" +" /* Advance */\r\n" +" caller_info_ptr++;\r\n" +" }\r\n" +"\r\n" +" fprintf( stdout, \"\\n\" );\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"#endif\r\n" +"\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * mem_alloc()\r\n" +" *\r\n" +" * Creates new record, stores auxiliary information about which function allocated the memory, line number, parameters, etc.\r\n" +" * Finally, it allocates physical memory using malloc()\r\n" +" * The function also updates worst-case heap size and worst-case RAM size\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"void *mem_alloc(\r\n" +" const char *func_name,\r\n" +" int func_lineno,\r\n" +" size_t size,\r\n" +" char *size_str /* the first char indicates m-alloc or c-alloc */ )\r\n" +"{\r\n" +" int index_record;\r\n" +" int32_t current_stack_size;\r\n" +" unsigned long hash;\r\n" +" allocator_record *ptr_record;\r\n" +"\r\n" +" if ( size == 0 )\r\n" +" {\r\n" +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Size of Zero not Supported\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" /* Search for an existing record (that has been de-allocated before) */\r\n" +" index_record = 0;\r\n" +" while ( ( ptr_record = get_mem_record( &hash, func_name, func_lineno, size_str, &index_record ) ) != NULL )\r\n" +" {\r\n" +" if ( ptr_record->frame_allocated == -1 )\r\n" +" {\r\n" +" break;\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" index_record++;\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* Create new record */\r\n" +" if ( ptr_record == NULL )\r\n" +" {\r\n" +" if ( Num_Records >= Max_Num_Records )\r\n" +" {\r\n" +" /* There is no room for a new record -> reallocate memory */\r\n" +" Max_Num_Records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" allocation_list = realloc( allocation_list, Max_Num_Records * sizeof( allocator_record ) );\r\n" +" }\r\n" +"\r\n" +" ptr_record = &( allocation_list[Num_Records] );\r\n" +"\r\n" +" /* Initialize new record */\r\n" +" ptr_record->hash = hash;\r\n" +" ptr_record->noccurances = 0;\r\n" +" ptr_record->total_block_size = 0;\r\n" +" ptr_record->total_used_size = 0;\r\n" +" ptr_record->frame_allocated = -1;\r\n" +" ptr_record->OOB_Flag = 0;\r\n" +" ptr_record->wc_heap_size_intra_frame = -1;\r\n" +" ptr_record->wc_heap_size_inter_frame = -1;\r\n" +"\r\n" +" index_record = Num_Records;\r\n" +" Num_Records++;\r\n" +" }\r\n" +"\r\n" +" /* Allocate memory block for the new record, add signature before the beginning and after the memory block and fill it with magic value */\r\n" +" ptr_record->block_ptr = mem_alloc_block( size, size_str );\r\n" +"\r\n" +" if ( ptr_record->block_ptr == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Cannot Allocate Memory!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" /* Save all auxiliary information about the memory block */\r\n" +" strncpy( ptr_record->name, func_name, MAX_FUNCTION_NAME_LENGTH );\r\n" +" ptr_record->name[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n" +" strncpy( ptr_record->params, size_str, MAX_PARAMS_LENGTH ); /* Note: The size string starts with either 'm' or 'c' to indicate 'm'alloc or 'c'alloc */\r\n" +" ptr_record->params[MAX_PARAMS_LENGTH] = '\\0';\r\n" +" ptr_record->lineno = func_lineno;\r\n" +" ptr_record->block_size = size;\r\n" +" ptr_record->total_block_size += size;\r\n" +"\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +" /* Export heap memory allocation record to the .csv file */\r\n" +" fprintf( fid_csv_filename, \"A,%ld,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n" +"#endif\r\n" +"\r\n" +" if ( ptr_record->frame_allocated != -1 )\r\n" +" {\r\n" +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Attempt to Allocate the Same Memory Block with Freeing it First!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" ptr_record->frame_allocated = update_cnt; /* Store the current frame number -> later it will be used to determine the total duration */\r\n" +"\r\n" +" /* Update Heap Size in the current frame */\r\n" +" current_heap_size += ptr_record->block_size;\r\n" +"\r\n" +" /* Check, if this is the new Worst-Case RAM (stack + heap) */\r\n" +" current_stack_size = ( int32_t )( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) );\r\n" +" if ( current_stack_size + current_heap_size > wc_ram_size )\r\n" +" {\r\n" +" wc_ram_size = current_stack_size + current_heap_size;\r\n" +" wc_ram_frame = update_cnt;\r\n" +" }\r\n" +"\r\n" +" /* Add new entry to the heap allocation call tree */\r\n" +" if ( heap_allocation_call_tree == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Error: Heap allocation call tree not created!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" /* check, if the maximum size of the call tree has been reached -> resize if so */\r\n" +" if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size )\r\n" +" {\r\n" +" heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n" +" }\r\n" +"\r\n" +" /* push new entry (positive number means push op, neagtive number means pop op; zero index must be converted to 0.01 :-) */\r\n" +" heap_allocation_call_tree[heap_allocation_call_tree_size++] = index_record;\r\n" +"\r\n" +" return ptr_record->block_ptr;\r\n" +"}\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * mem_alloc_block()\r\n" +" *\r\n" +" * Physical allocation of memory using malloc(). Appends 'signature' before and after the block,\r\n" +" * pre-fills memory block with magic value\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"static void *mem_alloc_block( size_t size, const char *size_str )\r\n" +"{\r\n" +" size_t rounded_size;\r\n" +" void *block_ptr;\r\n" +" char *tmp_ptr;\r\n" +" size_t n, f;\r\n" +" int32_t fill_value;\r\n" +" int32_t *ptr32;\r\n" +" int32_t mask, temp;\r\n" +"\r\n" +" /* Round Up Block Size */\r\n" +" rounded_size = ROUND_BLOCK_SIZE( size );\r\n" +"\r\n" +" /* Allocate memory using the standard malloc() by adding room for Signature Values */\r\n" +" block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 );\r\n" +"\r\n" +" if ( block_ptr == NULL )\r\n" +" {\r\n" +" return NULL;\r\n" +" }\r\n" +"\r\n" +" /* Add Signature Before the Start of the Block */\r\n" +" ptr32 = (int32_t *) block_ptr;\r\n" +" n = N_32BITS_BLOCKS;\r\n" +" do\r\n" +" {\r\n" +" *ptr32++ = MAGIC_VALUE_OOB;\r\n" +" } while ( --n );\r\n" +"\r\n" +" /* Fill Memory Block with Magic Value or 0 */\r\n" +" fill_value = MAGIC_VALUE_USED;\r\n" +" if ( size_str[0] == 'c' )\r\n" +" {\r\n" +" fill_value = 0x00000000;\r\n" +" }\r\n" +" n = size / sizeof( int32_t );\r\n" +" while ( n-- )\r\n" +" {\r\n" +" *ptr32++ = fill_value;\r\n" +" }\r\n" +"\r\n" +" /* Fill the Reminder of the Memory Block - After Rounding */\r\n" +" n = rounded_size - size;\r\n" +" f = n % sizeof( int32_t );\r\n" +" if ( f != 0 )\r\n" +" {\r\n" +" /* when filling with '0' need to adapt the magic value */\r\n" +" /* shift by [1->24, 2->16, 3->8] */\r\n" +" mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */\r\n" +" temp = MAGIC_VALUE_OOB & mask;\r\n" +" if ( fill_value != 0x0 )\r\n" +" { /* for malloc merge fill value */\r\n" +" temp += ( ~mask ) & MAGIC_VALUE_USED;\r\n" +" } /* for calloc the code in (1) above already introduces zeros */\r\n" +" *ptr32++ = temp;\r\n" +" }\r\n" +" n /= sizeof( int32_t );\r\n" +" n += N_32BITS_BLOCKS;\r\n" +"\r\n" +" /* Add Signature After the End of Block */\r\n" +" do\r\n" +" {\r\n" +" *ptr32++ = MAGIC_VALUE_OOB;\r\n" +" } while ( --n );\r\n" +"\r\n" +" /* Adjust the Memory Block Pointer (Magic Value Before and After the Memory Block Requested) */\r\n" +" tmp_ptr = (char *) block_ptr;\r\n" +" tmp_ptr += BLOCK_ROUNDING;\r\n" +" block_ptr = (void *) tmp_ptr;\r\n" +"\r\n" +" return block_ptr;\r\n" +"}\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * mem_set_usage()\r\n" +" *\r\n" +" * Calculates actual usage of memory block by checking the magic value that was used to pre-fill\r\n" +" * each memory block during its allocation\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"static int mem_set_usage( allocator_record *record_ptr )\r\n" +"{\r\n" +" int total_bytes_used;\r\n" +"\r\n" +" size_t n;\r\n" +" int32_t *ptr32;\r\n" +" char *ptr8;\r\n" +" size_t total_bytes;\r\n" +" int32_t fill_value;\r\n" +"\r\n" +" fill_value = MAGIC_VALUE_USED;\r\n" +" if ( ( record_ptr->params[0] ) == 'c' )\r\n" +" {\r\n" +" fill_value = 0x00000000;\r\n" +" }\r\n" +"\r\n" +" total_bytes = record_ptr->block_size;\r\n" +"\r\n" +" /* Check 4 bytes at a time */\r\n" +" ptr32 = (int32_t *) record_ptr->block_ptr;\r\n" +" total_bytes_used = 0;\r\n" +" for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- )\r\n" +" {\r\n" +" if ( *ptr32++ != fill_value )\r\n" +" {\r\n" +" total_bytes_used += sizeof( int32_t );\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* Check remaining bytes (If Applicable) 1 byte at a time */\r\n" +" ptr8 = (char *) ptr32;\r\n" +" for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- )\r\n" +" {\r\n" +" if ( *ptr8++ != (char) fill_value )\r\n" +" {\r\n" +" total_bytes_used++;\r\n" +" }\r\n" +"\r\n" +" /* Update Value */\r\n" +" fill_value >>= 8;\r\n" +" }\r\n" +"\r\n" +" return total_bytes_used;\r\n" +"}\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * mem_check_OOB()\r\n" +" *\r\n" +" * Checks, if out-of-bounds access has occured. This is done by inspecting the 'signature' value\r\n" +" * taht has been added before and after the memory block during its allocation\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"static unsigned int mem_check_OOB( allocator_record *record_ptr )\r\n" +"{\r\n" +" int32_t *ptr32;\r\n" +" unsigned int OOB_Flag = 0x0;\r\n" +" int32_t mask;\r\n" +" size_t i;\r\n" +" int f;\r\n" +"\r\n" +" ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS;\r\n" +"\r\n" +" /* Check the Signature at the Beginning of Memory Block */\r\n" +" i = N_32BITS_BLOCKS;\r\n" +" do\r\n" +" {\r\n" +" if ( *ptr32++ ^ MAGIC_VALUE_OOB )\r\n" +" {\r\n" +" OOB_Flag |= OOB_START;\r\n" +" }\r\n" +" } while ( --i );\r\n" +"\r\n" +" /* Advance to End (Snap to lowest 32 Bits) */\r\n" +" ptr32 += record_ptr->block_size / sizeof( int32_t );\r\n" +"\r\n" +" /* Calculate Unused Space That has been added to get to the rounded Block Size */\r\n" +" i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size;\r\n" +"\r\n" +" /* Partial Check of Signature at the End of Memory Block (for block size that has been rounded) */\r\n" +" f = i % sizeof( int32_t );\r\n" +" if ( f != 0 )\r\n" +" {\r\n" +" mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 );\r\n" +" if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask )\r\n" +" {\r\n" +" OOB_Flag |= OOB_END;\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* Full Check of Signature at the End of Memory Block, i.e. all 32 Bits (for the remainder after rounding) */\r\n" +" i /= sizeof( int32_t );\r\n" +" i += N_32BITS_BLOCKS;\r\n" +" do\r\n" +" {\r\n" +" if ( *ptr32++ ^ MAGIC_VALUE_OOB )\r\n" +" {\r\n" +" OOB_Flag |= OOB_END;\r\n" +" }\r\n" +" } while ( --i );\r\n" +"\r\n" +" return OOB_Flag;\r\n" +"}\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * malloc_hash()\r\n" +" *\r\n" +" * Calculate hash from function name, line number and malloc size\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str )\r\n" +"{\r\n" +" unsigned long hash = 5381;\r\n" +" const char *ptr_str;\r\n" +"\r\n" +" ptr_str = func_name;\r\n" +" while ( ptr_str != NULL && *ptr_str != '\\0' )\r\n" +" {\r\n" +" hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */\r\n" +" }\r\n" +"\r\n" +" hash = ( ( hash << 5 ) + hash ) + func_lineno; /* hash * 33 + func_lineno */\r\n" +"\r\n" +" ptr_str = size_str;\r\n" +" while ( ptr_str != NULL && *ptr_str != '\\0' )\r\n" +" {\r\n" +" hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */\r\n" +" }\r\n" +"\r\n" +" return hash;\r\n" +"}\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * get_mem_record()\r\n" +" *\r\n" +" * Search for memory record in the internal list, return NULL if not found\r\n" +" * Start from index_record\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record )\r\n" +"{\r\n" +" int i;\r\n" +"\r\n" +" if ( *index_record < 0 || *index_record > Num_Records )\r\n" +" {\r\n" +" return NULL;\r\n" +" }\r\n" +"\r\n" +" /* calculate hash */\r\n" +" *hash = malloc_hash( func_name, func_lineno, size_str );\r\n" +"\r\n" +" for ( i = *index_record; i < Num_Records; i++ )\r\n" +" {\r\n" +" /* check, if memory block is not allocated at the moment and the hash matches */\r\n" +" if ( allocation_list[i].block_ptr == NULL && *hash == allocation_list[i].hash )\r\n" +" {\r\n" +" *index_record = i;\r\n" +" return &( allocation_list[i] );\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* not found */\r\n" +" *index_record = -1;\r\n" +" return NULL;\r\n" +"}\r\n" +"\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * mem_free()\r\n" +" *\r\n" +" * This function de-allocates memory blocks and frees physical memory with free().\r\n" +" * It also updates the actual and average usage of memory blocks.\r\n" +" *\r\n" +" * Note: The record is not removed from the list and may be reused later on in mem_alloc()!\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"void mem_free( const char *func_name, int func_lineno, void *ptr )\r\n" +"{\r\n" +" int i, index_record;\r\n" +" char *tmp_ptr;\r\n" +" allocator_record *ptr_record;\r\n" +"\r\n" +" /* Search for the Block Pointer in the List */\r\n" +" ptr_record = NULL;\r\n" +" index_record = -1;\r\n" +" for ( i = 0; i < Num_Records; i++ )\r\n" +" {\r\n" +" if ( ptr == allocation_list[i].block_ptr )\r\n" +" { /* Yes, Found it */\r\n" +" ptr_record = &( allocation_list[i] );\r\n" +" index_record = i;\r\n" +" break;\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" if ( ptr_record == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Unable to Find Record Corresponding to the Allocated Memory Block!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" /* Update the Heap Size */\r\n" +" current_heap_size -= ptr_record->block_size;\r\n" +"\r\n" +" /* Calculate the Actual Usage of the Memory Block (Look for Signature) */\r\n" +" ptr_record->total_used_size += mem_set_usage( ptr_record );\r\n" +"\r\n" +" /* Check, if Out-Of-Bounds Access has been Detected */\r\n" +" ptr_record->OOB_Flag = mem_check_OOB( ptr_record );\r\n" +"\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +" /* Export heap memory de-allocation record to the .csv file */\r\n" +" fprintf( fid_csv_filename, \"D,%ld,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n" +"#endif\r\n" +"\r\n" +" /* De-Allocate Memory Block */\r\n" +" tmp_ptr = (char *) ptr;\r\n" +" tmp_ptr -= BLOCK_ROUNDING;\r\n" +" ptr = (void *) tmp_ptr;\r\n" +" free( ptr );\r\n" +"\r\n" +" /* Add new entry to the heap allocation call tree */\r\n" +" if ( heap_allocation_call_tree == NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Error: Heap allocation call tree not created!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" /* check, if the maximum size of the call tree has been reached -> resize if so */\r\n" +" if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size )\r\n" +" {\r\n" +" heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n" +" }\r\n" +"\r\n" +" heap_allocation_call_tree[heap_allocation_call_tree_size++] = -index_record;\r\n" +"\r\n" +" /* Reset memory block pointer (this is checked when updating wc intra-frame and inter-frame memory) */\r\n" +" ptr_record->block_ptr = NULL;\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * update_mem()\r\n" +" *\r\n" +" * This function updates the worst-case intra-frame memory and the worst-case inter-frame memory.\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"void update_mem( void )\r\n" +"{\r\n" +" int i, j, flag_alloc = -1, i_record;\r\n" +" int size_current_intra_frame_heap;\r\n" +" int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap;\r\n" +" allocator_record *ptr_record;\r\n" +"\r\n" +" /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */\r\n" +" n_items_current_intra_frame_heap = 0;\r\n" +" size_current_intra_frame_heap = 0;\r\n" +" for ( i = 0; i < heap_allocation_call_tree_size; i++ )\r\n" +" {\r\n" +" /* get the record */\r\n" +" i_record = heap_allocation_call_tree[i];\r\n" +"\r\n" +" if ( i_record > 0 )\r\n" +" {\r\n" +" flag_alloc = 1;\r\n" +" }\r\n" +" else if ( i_record < 0 )\r\n" +" {\r\n" +" flag_alloc = 0;\r\n" +" i_record = -i_record;\r\n" +" }\r\n" +" ptr_record = &( allocation_list[i_record] );\r\n" +"\r\n" +" if ( ptr_record->frame_allocated == update_cnt && ptr_record->block_ptr == NULL )\r\n" +" {\r\n" +" /* intra-frame heap memory */\r\n" +" if ( list_current_intra_frame_heap == NULL )\r\n" +" {\r\n" +" list_current_intra_frame_heap = (int *) malloc( heap_allocation_call_tree_size * sizeof( int ) );\r\n" +" memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) );\r\n" +" }\r\n" +"\r\n" +" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n" +" if ( i_record == 0 )\r\n" +" {\r\n" +" flag_alloc = 1;\r\n" +" for ( j = 0; j < n_items_current_intra_frame_heap; j++ )\r\n" +" {\r\n" +" if ( list_current_intra_frame_heap[j] == i_record )\r\n" +" {\r\n" +" flag_alloc = 0;\r\n" +" break;\r\n" +" }\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" if ( flag_alloc )\r\n" +" {\r\n" +" /* add to list */\r\n" +" list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record;\r\n" +" size_current_intra_frame_heap += ptr_record->block_size;\r\n" +"\r\n" +" /* no need to re-size the list -> the initially allocated size should be large enough */\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" /* remove from list */\r\n" +" for ( j = 0; j < n_items_current_intra_frame_heap; j++ )\r\n" +" {\r\n" +" if ( list_current_intra_frame_heap[j] == i_record )\r\n" +" {\r\n" +" break;\r\n" +" }\r\n" +" }\r\n" +" memmove( &list_current_intra_frame_heap[j], &list_current_intra_frame_heap[j + 1], ( n_items_current_intra_frame_heap - j ) * sizeof( int ) );\r\n" +" n_items_current_intra_frame_heap--;\r\n" +" size_current_intra_frame_heap -= ptr_record->block_size;\r\n" +"\r\n" +" /* reset block size */\r\n" +" ptr_record->frame_allocated = -1;\r\n" +" ptr_record->block_size = 0;\r\n" +" }\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" /* inter-frame heap memory */\r\n" +"\r\n" +" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n" +" if ( i_record == 0 )\r\n" +" {\r\n" +" flag_alloc = 1;\r\n" +" for ( j = 0; j < n_items_current_inter_frame_heap; j++ )\r\n" +" {\r\n" +" if ( list_current_inter_frame_heap[j] == i_record )\r\n" +" {\r\n" +" flag_alloc = 0;\r\n" +" break;\r\n" +" }\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" if ( flag_alloc )\r\n" +" {\r\n" +" /* add to list */\r\n" +" if ( n_items_current_inter_frame_heap >= max_items_current_inter_frame_heap )\r\n" +" {\r\n" +" /* resize list, if needed */\r\n" +" max_items_current_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" list_current_inter_frame_heap = realloc( list_current_inter_frame_heap, max_items_current_inter_frame_heap * sizeof( int ) );\r\n" +" }\r\n" +"\r\n" +" list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record;\r\n" +" size_current_inter_frame_heap += ptr_record->block_size;\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" /* remove from list */\r\n" +" for ( j = 0; j < n_items_current_inter_frame_heap; j++ )\r\n" +" {\r\n" +" if ( list_current_inter_frame_heap[j] == i_record )\r\n" +" {\r\n" +" break;\r\n" +" }\r\n" +" }\r\n" +" memmove( &list_current_inter_frame_heap[j], &list_current_inter_frame_heap[j + 1], ( n_items_current_inter_frame_heap - j ) * sizeof( int ) );\r\n" +" n_items_current_inter_frame_heap--;\r\n" +" size_current_inter_frame_heap -= ptr_record->block_size;\r\n" +"\r\n" +" /* reset block size */\r\n" +" ptr_record->frame_allocated = -1;\r\n" +" ptr_record->block_size = 0;\r\n" +" }\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* check, if this is the new worst-case for intra-frame heap memory */\r\n" +" if ( size_current_intra_frame_heap > size_wc_intra_frame_heap )\r\n" +" {\r\n" +" if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap )\r\n" +" {\r\n" +" /* resize the list, if needed */\r\n" +" max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n" +" }\r\n" +"\r\n" +" /* copy current-frame list to worst-case list */\r\n" +" memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) );\r\n" +" n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap;\r\n" +" size_wc_intra_frame_heap = size_current_intra_frame_heap;\r\n" +" location_wc_intra_frame_heap = update_cnt;\r\n" +"\r\n" +" /* update the wc numbers in all individual records */\r\n" +" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n" +" {\r\n" +" i_record = list_wc_intra_frame_heap[i];\r\n" +" ptr_record = &( allocation_list[i_record] );\r\n" +" ptr_record->wc_heap_size_intra_frame = ptr_record->block_size;\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* check, if this is the new worst-case for inter-frame heap memory */\r\n" +" if ( size_current_inter_frame_heap > size_wc_inter_frame_heap )\r\n" +" {\r\n" +" if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap )\r\n" +" {\r\n" +" /* resize list, if needed */\r\n" +" max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" +" list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n" +" }\r\n" +"\r\n" +" /* copy current-frame list to worst-case list */\r\n" +" memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) );\r\n" +" n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap;\r\n" +" size_wc_inter_frame_heap = size_current_inter_frame_heap;\r\n" +" location_wc_inter_frame_heap = update_cnt;\r\n" +"\r\n" +" /* update the wc numbers in all individual records */\r\n" +" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n" +" {\r\n" +" i_record = list_wc_inter_frame_heap[i];\r\n" +" ptr_record = &( allocation_list[i_record] );\r\n" +" ptr_record->wc_heap_size_inter_frame = ptr_record->block_size;\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* reset heap allocation call tree */\r\n" +" heap_allocation_call_tree_size = 0;\r\n" +"\r\n" +" /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */\r\n" +" if ( list_current_intra_frame_heap )\r\n" +" {\r\n" +" free( list_current_intra_frame_heap );\r\n" +" }\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * subst()\r\n" +" *\r\n" +" * Substitute character in string\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"static void subst( char *s, char from, char to )\r\n" +"{\r\n" +" while ( *s == from )\r\n" +" {\r\n" +" *s++ = to;\r\n" +" }\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * mem_count_summary()\r\n" +" *\r\n" +" * Print detailed (per-item) information about heap memory usage\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"static void mem_count_summary( void )\r\n" +"{\r\n" +" int i, j, index, index_record;\r\n" +" size_t length;\r\n" +" char buf[300], format_str[50], name_str[MAX_FUNCTION_NAME_LENGTH + 3], parms_str[MAX_PARAMS_LENGTH + 1], type_str[10], usage_str[20], size_str[20], line_str[10];\r\n" +" allocator_record *ptr_record, *ptr;\r\n" +"\r\n" +" /* Prepare format string */\r\n" +" sprintf( format_str, \"%%-%d.%ds %%5.5s %%6.6s %%-%d.%ds %%20.20s %%6.6s \", 50, 50, 50, 50 );\r\n" +"\r\n" +" if ( n_items_wc_intra_frame_heap > 0 )\r\n" +" {\r\n" +" /* Intra-Frame Heap Size */\r\n" +" fprintf( stdout, \"\\nList of memory blocks when maximum intra-frame heap size is reached:\\n\\n\" );\r\n" +"\r\n" +" /* Find duplicate records (same hash and worst-case heap size) */\r\n" +" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n" +" {\r\n" +" index_record = list_wc_intra_frame_heap[i];\r\n" +" if ( index_record == -1 )\r\n" +" {\r\n" +" continue;\r\n" +" }\r\n" +"\r\n" +" ptr_record = &( allocation_list[index_record] );\r\n" +" for ( j = i + 1; j < n_items_wc_intra_frame_heap; j++ )\r\n" +" {\r\n" +" index = list_wc_intra_frame_heap[j];\r\n" +" if ( index == -1 )\r\n" +" {\r\n" +" continue;\r\n" +" }\r\n" +" ptr = &( allocation_list[index] );\r\n" +"\r\n" +" if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_intra_frame == ptr_record->wc_heap_size_intra_frame )\r\n" +" {\r\n" +" ptr_record->noccurances++;\r\n" +" list_wc_intra_frame_heap[j] = -1;\r\n" +" }\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* Print Header */\r\n" +" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Maximum Size\", \"Usage\" );\r\n" +" puts( buf );\r\n" +" length = strlen( buf );\r\n" +" sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n" +" subst( buf, '0', '-' );\r\n" +" puts( buf );\r\n" +"\r\n" +" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n" +" {\r\n" +" index_record = list_wc_intra_frame_heap[i];\r\n" +"\r\n" +" if ( index_record != -1 )\r\n" +" {\r\n" +" /* get the record */\r\n" +" ptr_record = &( allocation_list[index_record] );\r\n" +"\r\n" +" /* prepare information strings */\r\n" +" strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH );\r\n" +" strcat( name_str, \"()\" );\r\n" +" name_str[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n" +" strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH );\r\n" +" parms_str[MAX_PARAMS_LENGTH] = '\\0';\r\n" +"\r\n" +" if ( ptr_record->params[0] == 'm' )\r\n" +" {\r\n" +" strcpy( type_str, \"malloc\" );\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" strcpy( type_str, \"calloc\" );\r\n" +" }\r\n" +"\r\n" +" sprintf( line_str, \"%d\", ptr_record->lineno );\r\n" +"\r\n" +" /* prepare average usage & memory size strings */\r\n" +" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) );\r\n" +"\r\n" +" if ( ptr_record->noccurances > 1 )\r\n" +" {\r\n" +" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" sprintf( size_str, \"%d %s\", (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" +" }\r\n" +"\r\n" +" sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str );\r\n" +" puts( buf );\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" fprintf( stdout, \"\\n\" );\r\n" +" }\r\n" +"\r\n" +" if ( n_items_wc_inter_frame_heap > 0 )\r\n" +" {\r\n" +" /* Inter-Frame Heap Size */\r\n" +" fprintf( stdout, \"\\nList of memory blocks when maximum inter-frame heap size is reached:\\n\\n\" );\r\n" +"\r\n" +" /* Find duplicate records (same hash and worst-case heap size) */\r\n" +" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n" +" {\r\n" +" index_record = list_wc_inter_frame_heap[i];\r\n" +" if ( index_record == -1 )\r\n" +" {\r\n" +" continue;\r\n" +" }\r\n" +" ptr_record = &( allocation_list[index_record] );\r\n" +" ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */\r\n" +" for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ )\r\n" +" {\r\n" +" index = list_wc_inter_frame_heap[j];\r\n" +" if ( index == -1 )\r\n" +" {\r\n" +" continue;\r\n" +" }\r\n" +" ptr = &( allocation_list[index] );\r\n" +"\r\n" +" if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_inter_frame == ptr_record->wc_heap_size_inter_frame )\r\n" +" {\r\n" +" ptr_record->noccurances++;\r\n" +" list_wc_inter_frame_heap[j] = -1;\r\n" +" }\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" /* Print Header */\r\n" +" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Memory Size\", \"Usage\" );\r\n" +" puts( buf );\r\n" +" length = strlen( buf );\r\n" +" sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n" +" subst( buf, '0', '-' );\r\n" +" puts( buf );\r\n" +"\r\n" +" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n" +" {\r\n" +" index_record = list_wc_inter_frame_heap[i];\r\n" +"\r\n" +" if ( index_record != -1 )\r\n" +" {\r\n" +" /* get the record */\r\n" +" ptr_record = &( allocation_list[index_record] );\r\n" +"\r\n" +" /* prepare information strings */\r\n" +" strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH );\r\n" +" strcat( name_str, \"()\" );\r\n" +" name_str[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n" +" strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH );\r\n" +" parms_str[MAX_PARAMS_LENGTH] = '\\0';\r\n" +"\r\n" +" if ( ptr_record->params[0] == 'm' )\r\n" +" {\r\n" +" strcpy( type_str, \"malloc\" );\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" strcpy( type_str, \"calloc\" );\r\n" +" }\r\n" +"\r\n" +" sprintf( line_str, \"%d\", ptr_record->lineno );\r\n" +"\r\n" +" /* prepare average usage & memory size strings */\r\n" +" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) );\r\n" +"\r\n" +" if ( ptr_record->noccurances > 1 )\r\n" +" {\r\n" +" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" sprintf( size_str, \"%d %s\", (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" +" }\r\n" +"\r\n" +" sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str );\r\n" +" puts( buf );\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" fprintf( stdout, \"\\n\" );\r\n" +" }\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"#endif\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * print_mem()\r\n" +" *\r\n" +" * Print information about ROM and RAM memory usage\r\n" +" *--------------------------------------------------------------------*/\r\n" +"\r\n" +"void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] )\r\n" +"{\r\n" +" int i, nElem;\r\n" +"\r\n" +" fprintf( stdout, \"\\n\\n --- Memory usage --- \\n\\n\" );\r\n" +"\r\n" +" if ( Const_Data_PROM_Table != NULL )\r\n" +" {\r\n" +" nElem = 0;\r\n" +" while ( strcmp( Const_Data_PROM_Table[nElem].file_spec, \"\" ) != 0 )\r\n" +" nElem++;\r\n" +"\r\n" +" for ( i = 0; i < nElem; i++ )\r\n" +" {\r\n" +" if ( Stat_Cnt_Size > 0 )\r\n" +" {\r\n" +" /* words */\r\n" +" fprintf( stdout, \"Program ROM size (%s): %d words\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size );\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" /* bytes (here, we assume that each instruction takes PROM_INST_SIZE bits of the PROM memory) */\r\n" +" fprintf( stdout, \"Program ROM size (%s): %d bytes\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size * ( PROM_INST_SIZE / 8 ) );\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" for ( i = 0; i < nElem; i++ )\r\n" +" {\r\n" +" if ( Const_Data_PROM_Table[i].Get_Const_Data_Size_Func == NULL )\r\n" +" {\r\n" +" fprintf( stdout, \"Error: Cannot retrieve or calculate Table ROM size of (%s)!\\n\", Const_Data_PROM_Table[i].file_spec );\r\n" +" }\r\n" +"\r\n" +" fprintf( stdout, \"Table ROM (const data) size (%s): %d %s\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].Get_Const_Data_Size_Func() >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n" +" }\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" fprintf( stdout, \"Program ROM size: not available\\n\" );\r\n" +" fprintf( stdout, \"Table ROM (const data) size: not available\\n\" );\r\n" +" }\r\n" +"\r\n" +" if ( wc_ram_size > 0 )\r\n" +" {\r\n" +" fprintf( stdout, \"Maximum RAM (stack + heap) size: %d %s in frame %d\\n\", wc_ram_size >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], wc_ram_frame );\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" fprintf( stdout, \"Maximum RAM (stack + heap) size: not available\\n\" );\r\n" +" }\r\n" +"\r\n" +" /* check, if the stack is empty */\r\n" +" if ( ptr_current_stack != ptr_base_stack )\r\n" +" {\r\n" +" fprintf( stderr, \"Warning: Stack is not empty.\\n\" );\r\n" +" }\r\n" +"\r\n" +" if ( ptr_base_stack - ptr_max_stack > 0 )\r\n" +" {\r\n" +" fprintf( stdout, \"Maximum stack size: %lu %s in frame %d\\n\", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size],\r\n" +" wc_stack_frame );\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" fprintf( stdout, \"Maximum stack size: not available\\n\" );\r\n" +" }\r\n" +"\r\n" +" /* last update of intra-frame memory and inter-frame memory, if needed */\r\n" +" if ( heap_allocation_call_tree_size > 0 )\r\n" +" {\r\n" +" update_mem();\r\n" +" }\r\n" +"\r\n" +" /* check, if all memory blocks have been deallocated (freed) */\r\n" +" for ( i = 0; i < Num_Records; i++ )\r\n" +" {\r\n" +" if ( allocation_list[i].block_ptr != NULL )\r\n" +" {\r\n" +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", allocation_list[i].name, allocation_list[i].lineno, \"Error: Memory Block has not been De-Allocated with free()!\" );\r\n" +" exit( -1 );\r\n" +" }\r\n" +" }\r\n" +"\r\n" +" if ( n_items_wc_intra_frame_heap > 0 )\r\n" +" {\r\n" +" fprintf( stdout, \"Maximum intra-frame heap size: %d %s in frame %d\\n\", size_wc_intra_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_intra_frame_heap );\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" fprintf( stdout, \"Maximum intra-frame heap size: 0\\n\" );\r\n" +" }\r\n" +"\r\n" +" if ( n_items_wc_inter_frame_heap > 0 )\r\n" +" {\r\n" +" fprintf( stdout, \"Maximum inter-frame heap size: %d %s in frame %d\\n\", size_wc_inter_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_inter_frame_heap );\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" fprintf( stdout, \"Maximum inter-frame heap size: 0\\n\" );\r\n" +" }\r\n" +"\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +" /* Print detailed information about worst-case stack usage */\r\n" +" if ( ptr_base_stack - ptr_max_stack > 0 )\r\n" +" {\r\n" +" print_stack_call_tree();\r\n" +" }\r\n" +"\r\n" +" /* Print detailed information about worst-case heap usage */\r\n" +" mem_count_summary();\r\n" +"#endif\r\n" +"\r\n" +" if ( Stat_Cnt_Size > 0 )\r\n" +" {\r\n" +" /* words */\r\n" +" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", 8 << Stat_Cnt_Size );\r\n" +" }\r\n" +" else\r\n" +" {\r\n" +" /* bytes */\r\n" +" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", PROM_INST_SIZE );\r\n" +" }\r\n" +" fprintf( stdout, \"Note: The Data ROM size is calculated using the sizeof(type) built-in function\\n\" );\r\n" +"\r\n" +" if ( n_items_wc_intra_frame_heap > 0 )\r\n" +" {\r\n" +" fprintf( stdout, \"Intra-frame heap memory is allocated and de-allocated in the same frame\\n\" );\r\n" +" }\r\n" +"\r\n" +" /* De-allocate list of heap memory blocks */\r\n" +" if ( allocation_list != NULL )\r\n" +" {\r\n" +" free( allocation_list );\r\n" +" }\r\n" +"\r\n" +" /* De-allocate list of stack records */\r\n" +" if ( stack_callers[0] != NULL )\r\n" +" {\r\n" +" free( stack_callers[0] );\r\n" +" }\r\n" +"\r\n" +" if ( stack_callers[1] != NULL )\r\n" +" {\r\n" +" free( stack_callers[1] );\r\n" +" }\r\n" +"\r\n" +" /* De-allocate heap allocation call tree */\r\n" +" if ( heap_allocation_call_tree != NULL )\r\n" +" {\r\n" +" free( heap_allocation_call_tree );\r\n" +" }\r\n" +"\r\n" +" /* De-allocate intra-frame and inter-frame heap lists */\r\n" +" if ( list_wc_intra_frame_heap != NULL )\r\n" +" {\r\n" +" free( list_wc_intra_frame_heap );\r\n" +" }\r\n" +"\r\n" +" if ( list_current_inter_frame_heap != NULL )\r\n" +" {\r\n" +" free( list_current_inter_frame_heap );\r\n" +" }\r\n" +"\r\n" +" if ( list_wc_inter_frame_heap != NULL )\r\n" +" {\r\n" +" free( list_wc_inter_frame_heap );\r\n" +" }\r\n" +"\r\n" +"#ifdef MEM_COUNT_DETAILS\r\n" +" if ( fid_csv_filename != NULL )\r\n" +" {\r\n" +" fclose( fid_csv_filename );\r\n" +" }\r\n" +"#endif\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"#endif /* WMOPS */\r\n" +"\r\n" +"#ifdef CONTROL_CODE_OPS\r\n" +"\r\n" +"int LT_16( short var1, short var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( var1 < var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].LT_16++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int GT_16( short var1, short var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( var1 > var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].GT_16++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int LE_16( short var1, short var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( var1 <= var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].LE_16++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int GE_16( short var1, short var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( var1 >= var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].GE_16++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int EQ_16( short var1, short var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( var1 == var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].EQ_16++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int NE_16( short var1, short var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( var1 != var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].NE_16++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int LT_32( int L_var1, int L_var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( L_var1 < L_var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].LT_32++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int GT_32( int L_var1, int L_var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( L_var1 > L_var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].GT_32++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int LE_32( int L_var1, int L_var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( L_var1 <= L_var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].LE_32++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int GE_32( int L_var1, int L_var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( L_var1 >= L_var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].GE_32++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int EQ_32( int L_var1, int L_var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( L_var1 == L_var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].EQ_32++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int NE_32( int L_var1, int L_var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( L_var1 != L_var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].NE_32++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int LT_64( long long int L64_var1, long long int L64_var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( L64_var1 < L64_var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].LT_64++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int GT_64( long long int L64_var1, long long int L64_var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( L64_var1 > L64_var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].GT_64++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int LE_64( long long int L64_var1, long long int L64_var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( L64_var1 <= L64_var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].LE_64++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"int GE_64( long long int L64_var1, long long int L64_var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( L64_var1 >= L64_var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].GE_64++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"int EQ_64( long long int L64_var1, long long int L64_var2 )\r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( L64_var1 == L64_var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].EQ_64++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"int NE_64( long long int L64_var1, long long int L64_var2 ) \r\n" +"{\r\n" +" int F_ret = 0;\r\n" +"\r\n" +" if ( L64_var1 != L64_var2 )\r\n" +" {\r\n" +" F_ret = 1;\r\n" +" }\r\n" +"#ifdef WMOPS\r\n" +" multiCounter[currCounter].NE_64++;\r\n" +"#endif\r\n" +" return F_ret;\r\n" +"}\r\n" +"\r\n" +"#endif /* #ifdef CONTROL_CODE_OPS */\r\n" +"\r\n" +"#ifdef WMOPS\r\n" +"\r\n" +"void incrIf( const char *func_name )\r\n" +"{\r\n" +" /* Technical note: If the \"IF\" operator comes just after an \"ELSE\", its counter must not be incremented */\r\n" +" /* The following auxiliary variables are used to check if the \"IF\" operator doesn't immediately follow an \"ELSE\" operator */\r\n" +" if ( ( (int) currCounter != funcId_where_last_call_to_else_occurred ) || ( strncmp( func_name, func_name_where_last_call_to_else_occurred, MAX_FUNCTION_NAME_LENGTH ) != 0 ) || ( TotalWeightedOperation( currCounter) != funcid_total_wmops_at_last_call_to_else ) || ( call_occurred == 1 ) )\r\n" +" multiCounter[currCounter].If++;\r\n" +"\r\n" +" call_occurred = 0;\r\n" +" funcId_where_last_call_to_else_occurred = -100;\r\n" +"}\r\n" +"\r\n" +"void incrElse( const char *func_name )\r\n" +"{\r\n" +" multiCounter[currCounter].If++;\r\n" +"\r\n" +" /* Save the BASOP counter Id in the last function in which ELSE() has been called */\r\n" +" funcId_where_last_call_to_else_occurred = currCounter;\r\n" +"\r\n" +" /* Save the BASOP comeplxity in the last call of the ELSE() statement */\r\n" +" funcid_total_wmops_at_last_call_to_else = TotalWeightedOperation( currCounter );\r\n" +"\r\n" +" /* Save the function name in the last call of the ELSE() statement */\r\n" +" strncpy( func_name_where_last_call_to_else_occurred, func_name, MAX_FUNCTION_NAME_LENGTH );\r\n" +" func_name_where_last_call_to_else_occurred[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n" +"\r\n" +" /* Set call_occurred to 0 to prevent counting of complexity of the next \"immediate\" IF statement */\r\n" +" call_occurred = 0;\r\n" +"}\r\n" +"\r\n" +"long TotalWeightedOperation( unsigned int CounterId )\r\n" +"{\r\n" +" int i;\r\n" +" unsigned int *ptr, *ptr2;\r\n" +" long tot;\r\n" +"\r\n" +" tot = 0;\r\n" +" ptr = (unsigned int *) &multiCounter[CounterId];\r\n" +" ptr2 = (unsigned int *) &op_weight;\r\n" +"\r\n" +" for ( i = 0; i < (int) ( sizeof( multiCounter[CounterId] ) / sizeof( unsigned int ) ); i++ )\r\n" +" {\r\n" +" if ( *ptr == UINT_MAX )\r\n" +" {\r\n" +" printf( \"\\nError in BASOP complexity counters: multiCounter[%d][%d] = %d !!!\\n\", CounterId, i, *ptr );\r\n" +" exit( -1 );\r\n" +" }\r\n" +"\r\n" +" tot += ( ( *ptr++ ) * ( *ptr2++ ) );\r\n" +" }\r\n" +"\r\n" +" return ( tot );\r\n" +"}\r\n" +"\r\n" +"long DeltaWeightedOperation( unsigned int CounterId )\r\n" +"{\r\n" +" long NewWOper, delta;\r\n" +"\r\n" +" NewWOper = TotalWeightedOperation( CounterId );\r\n" +"\r\n" +" delta = NewWOper - wmops[CounterId].LastWOper;\r\n" +" wmops[CounterId].LastWOper = NewWOper;\r\n" +"\r\n" +" return ( delta );\r\n" +"}\r\n" +"\r\n" +"/* Resets BASOP operation counter */\r\n" +"void Reset_BASOP_WMOPS_counter( unsigned int counterId )\r\n" +"{\r\n" +" int i;\r\n" +" long *ptr;\r\n" +"\r\n" +" /* reset the current BASOP operation counter */\r\n" +" ptr = (long *) &multiCounter[counterId];\r\n" +" for ( i = 0; i < (int) ( sizeof( multiCounter[counterId] ) / sizeof( long ) ); i++ )\r\n" +" {\r\n" +" *ptr++ = 0;\r\n" +" }\r\n" +"\r\n" +" wmops[counterId].LastWOper = 0;\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"#endif\r\n" \ No newline at end of file diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index caed270..0313dce 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -1,1448 +1,1232 @@ -"/*\r\n", -" * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved.\r\n", -" *\r\n", -" * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n", -" * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n", -" * or refer to ITU-T Recommendation G.191 on \"SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS\".\r\n", -" *\r\n", -" * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor\r\n", -" * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software\r\n", -" * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE.\r\n", -" *\r\n", -" * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca)\r\n", -" */\r\n", -"\r\n", -"#ifndef WMOPS_H\r\n", -"#define WMOPS_H\r\n", -"\r\n", -"#ifndef EXIT_FAILURE\r\n", -"#include /* stdlib is needed for exit() */\r\n", -"#endif\r\n", -"\r\n", -"#ifndef EOF\r\n", -"#include /* stdio is needed for fprintf() */\r\n", -"#endif\r\n", -"\r\n", -"\r\n", -"/* To Prevent \"warning: '$' in identifier or number\" message under GCC */\r\n", -"#ifdef __GNUC__\r\n", -"#pragma GCC system_header\r\n", -"#endif\r\n", -"\r\n", -"#ifndef INT_MAX\r\n", -"#define INT_MAX 32767\r\n", -"#endif\r\n", -"\r\n", -"#define FRAMES_PER_SECOND 50.0 \r\n", -"#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */\r\n", -"\r\n", -"#ifdef WMOPS\r\n", -"enum instructions\r\n", -"{\r\n", -" _ADD,\r\n", -" _ABS,\r\n", -" _MULT,\r\n", -" _MAC,\r\n", -" _MOVE,\r\n", -" _STORE,\r\n", -" _LOGIC,\r\n", -" _SHIFT,\r\n", -" _BRANCH,\r\n", -" _DIV,\r\n", -" _SQRT,\r\n", -" _TRANS,\r\n", -" _FUNC,\r\n", -" _LOOP,\r\n", -" _INDIRECT,\r\n", -" _PTR_INIT,\r\n", -" _TEST,\r\n", -" _POWER,\r\n", -" _LOG,\r\n", -" _MISC,\r\n", -" NUM_INST\r\n", -"};\r\n", -"\r\n", -"#define _ADD_C 1\r\n", -"#define _ABS_C 1\r\n", -"#define _MULT_C 1\r\n", -"#define _MAC_C 1\r\n", -"#define _MOVE_C 1\r\n", -"#define _STORE_C 1\r\n", -"#define _LOGIC_C 1\r\n", -"#define _SHIFT_C 1\r\n", -"#define _BRANCH_C 4\r\n", -"#define _DIV_C 18\r\n", -"#define _SQRT_C 10\r\n", -"#define _TRANS_C 25\r\n", -"#define _FUNC_C 2 /* need to add number of arguments */\r\n", -"#define _LOOP_C 3\r\n", -"#define _INDIRECT_C 2\r\n", -"#define _PTR_INIT_C 1\r\n", -"#define _TEST_C 2\r\n", -"#define _POWER_C 25\r\n", -"#define _LOG_C 25\r\n", -"#define _MISC_C 1\r\n", -"\r\n", -"#define _ADD_P 1\r\n", -"#define _ABS_P 1\r\n", -"#define _MULT_P 1\r\n", -"#define _MAC_P 1\r\n", -"#define _MOVE_P 1\r\n", -"#define _STORE_P 0\r\n", -"#define _LOGIC_P 1\r\n", -"#define _SHIFT_P 1\r\n", -"#define _BRANCH_P 2\r\n", -"#define _DIV_P 2\r\n", -"#define _SQRT_P 2\r\n", -"#define _TRANS_P 2\r\n", -"#define _FUNC_P 2 /* need to add number of arguments */\r\n", -"#define _LOOP_P 1\r\n", -"#define _INDIRECT_P 2\r\n", -"#define _PTR_INIT_P 1\r\n", -"#define _TEST_P 1\r\n", -"#define _POWER_P 2\r\n", -"#define _LOG_P 2\r\n", -"#define _MISC_P 1\r\n", -"\r\n", -"#define ADD( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _ADD_C * ( x ) ); \\\r\n", -" inst_cnt[_ADD] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _ADD_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define ABS( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _ABS_C * ( x ) ); \\\r\n", -" inst_cnt[_ABS] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _ABS_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define MULT( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _MULT_C * ( x ) ); \\\r\n", -" inst_cnt[_MULT] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _MULT_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define MAC( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _MAC_C * ( x ) ); \\\r\n", -" inst_cnt[_MAC] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _MAC_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define MOVE( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _MOVE_C * ( x ) ); \\\r\n", -" inst_cnt[_MOVE] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _MOVE_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define STORE( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _STORE_C * ( x ) ); \\\r\n", -" inst_cnt[_STORE] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _STORE_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define LOGIC( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _LOGIC_C * ( x ) ); \\\r\n", -" inst_cnt[_LOGIC] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _LOGIC_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define SHIFT( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _SHIFT_C * ( x ) ); \\\r\n", -" inst_cnt[_SHIFT] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _SHIFT_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define BRANCH( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _BRANCH_C * ( x ) ); \\\r\n", -" inst_cnt[_BRANCH] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _BRANCH_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define DIV( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _DIV_C * ( x ) ); \\\r\n", -" inst_cnt[_DIV] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _DIV_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define SQRT( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _SQRT_C * ( x ) ); \\\r\n", -" inst_cnt[_SQRT] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _SQRT_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define TRANS( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _TRANS_C * ( x ) ); \\\r\n", -" inst_cnt[_TRANS] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _TRANS_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define LOOP( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _LOOP_C * ( x ) ); \\\r\n", -" inst_cnt[_LOOP] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _LOOP_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define INDIRECT( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _INDIRECT_C * ( x ) ); \\\r\n", -" inst_cnt[_INDIRECT] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _INDIRECT_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define PTR_INIT( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _PTR_INIT_C * ( x ) ); \\\r\n", -" inst_cnt[_PTR_INIT] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _PTR_INIT_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define TEST( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _TEST_C * ( x ) ); \\\r\n", -" inst_cnt[_TEST] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _TEST_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define POWER( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _POWER_C * ( x ) ); \\\r\n", -" inst_cnt[_POWER] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _POWER_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define LOG( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _LOG_C * ( x ) ); \\\r\n", -" inst_cnt[_LOG] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _LOG_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define MISC( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _MISC_C * ( x ) ); \\\r\n", -" inst_cnt[_MISC] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _MISC_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"\r\n", -"#define FUNC( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( _FUNC_C + _MOVE_C * ( x ) ); \\\r\n", -" inst_cnt[_FUNC]++; \\\r\n", -" inst_cnt[_MOVE] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _FUNC_P + _MOVE_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"\r\n", -"#define DADD( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( 2 * _ADD_C * ( x ) ); \\\r\n", -" inst_cnt[_ADD] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _ADD_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define DMULT( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( 2 * _MULT_C * ( x ) ); \\\r\n", -" inst_cnt[_MULT] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _MULT_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define DMAC( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( 2 * _MAC_C * ( x ) ); \\\r\n", -" inst_cnt[_MAC] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _MAC_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define DMOVE( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( 2 * _MOVE_C * ( x ) ); \\\r\n", -" inst_cnt[_MOVE] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _MOVE_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define DSTORE( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( 2 * _STORE_C * ( x ) ); \\\r\n", -" inst_cnt[_STORE] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _STORE_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define DLOGIC( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( 2 * _LOGIC_C * ( x ) ); \\\r\n", -" inst_cnt[_LOGIC] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _LOGIC_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define DSHIFT( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( 2 * _SHIFT_C * ( x ) ); \\\r\n", -" inst_cnt[_SHIFT] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _SHIFT_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define DDIV( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( 2 * _DIV_C * ( x ) ); \\\r\n", -" inst_cnt[_DIV] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _DIV_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define DSQRT( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( 2 * _SQRT_C * ( x ) ); \\\r\n", -" inst_cnt[_SQRT] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _SQRT_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"#define DTRANS( x ) \\\r\n", -" { \\\r\n", -" { \\\r\n", -" ops_cnt += ( 2 * _TRANS_C * ( x ) ); \\\r\n", -" inst_cnt[_TRANS] += ( x ); \\\r\n", -" { \\\r\n", -" static int pcnt; \\\r\n", -" if ( !pcnt ) \\\r\n", -" { \\\r\n", -" pcnt = 1; \\\r\n", -" prom_cnt += ( _TRANS_P * ( x ) ); \\\r\n", -" } \\\r\n", -" } \\\r\n", -" } \\\r\n", -" }\r\n", -"\r\n", -"extern double ops_cnt;\r\n", -"extern double prom_cnt;\r\n", -"extern double inst_cnt[NUM_INST];\r\n", -"\r\n", -"void reset_wmops( void );\r\n", -"void push_wmops( const char *label );\r\n", -"void pop_wmops( void );\r\n", -"void update_wmops( void );\r\n", -"void update_mem( void );\r\n", -"void print_wmops( void );\r\n", -"\r\n", -"#else /* WMOPS counting disabled */\r\n", -"\r\n", -"#define reset_wmops()\r\n", -"extern int cntr_push_pop;\r\n", -"#define push_wmops( x ) ( cntr_push_pop++ )\r\n", -"#define pop_wmops() ( cntr_push_pop-- )\r\n", -"#define update_wmops() ( assert( cntr_push_pop == 0 ) )\r\n", -"#define update_mem()\r\n", -"#define print_wmops()\r\n", -"\r\n", -"#define ADD( x )\r\n", -"#define ABS( x )\r\n", -"#define MULT( x )\r\n", -"#define MAC( x )\r\n", -"#define MOVE( x )\r\n", -"#define STORE( x )\r\n", -"#define LOGIC( x )\r\n", -"#define SHIFT( x )\r\n", -"#define BRANCH( x )\r\n", -"#define DIV( x )\r\n", -"#define SQRT( x )\r\n", -"#define TRANS( x )\r\n", -"#define FUNC( x )\r\n", -"#define LOOP( x )\r\n", -"#define INDIRECT( x )\r\n", -"#define PTR_INIT( x )\r\n", -"#define TEST( x )\r\n", -"#define POWER( x )\r\n", -"#define LOG( x )\r\n", -"#define MISC( x )\r\n", -"\r\n", -"#define DADD( x )\r\n", -"#define DMULT( x )\r\n", -"#define DMAC( x )\r\n", -"#define DMOVE( x )\r\n", -"#define DSTORE( x )\r\n", -"#define DLOGIC( x )\r\n", -"#define DSHIFT( x )\r\n", -"#define DDIV( x )\r\n", -"#define DSQRT( x )\r\n", -"#define DTRANS( x )\r\n", -"\r\n", -"#endif\r\n", -"\r\n", -"#ifndef WMOPS\r\n", -"/* DESACTIVATE the Counting Mechanism */\r\n", -"#define OP_COUNT_( op, n )\r\n", -"\r\n", -"/* DESACTIVATE Operation Counter Wrappers */\r\n", -"#define OP_COUNT_WRAPPER1_( op, val ) ( val )\r\n", -"#define OP_COUNT_WRAPPER2_( expr )\r\n", -"#define OP_COUNT_WRAPPER3_( op, expr ) expr\r\n", -"\r\n", -"/* DESACTIVATE Logical & Ternary Operators */\r\n", -"#define __\r\n", -"#define _\r\n", -"\r\n", -"#else\r\n", -"\r\n", -"/* '*ops_cnt_ptr' is Used to Avoid: \"warning: operation on 'ops_cnt' may be undefined\" with Cygwin gcc Compiler */\r\n", -"static double *ops_cnt_ptr = &ops_cnt;\r\n", -"#define OP_COUNT_( op, x ) ( *ops_cnt_ptr += ( op##_C * ( x ) ), inst_cnt[op] += ( x ) )\r\n", -"\r\n", -"/******************************************************************/\r\n", -"/* NOTES: */\r\n", -"/* The 'wmc_flag_' flag is global to avoid declaration in every */\r\n", -"/* function and 'static' to avoid clashing with other modules */\r\n", -"/* that include this header file. */\r\n", -"/* */\r\n", -"/* The declarations of 'wmc_flag_' and 'wops_' in this header */\r\n", -"/* file prevent the addition of a 'C' file to the Project. */\r\n", -"/******************************************************************/\r\n", -"\r\n", -"/* General Purpose Global Flag */\r\n", -"static int wmc_flag_ = 0;\r\n", -"\r\n", -"/* Operation Counter Wrappers */\r\n", -"#define OP_COUNT_WRAPPER1_( op, val ) ( op, val )\r\n", -"#define OP_COUNT_WRAPPER2_( expr ) \\\r\n", -" if ( expr, 0 ) \\\r\n", -" ; \\\r\n", -" else\r\n", -"#define OP_COUNT_WRAPPER3_( op, expr ) \\\r\n", -" if ( op, 0 ) \\\r\n", -" ; \\\r\n", -" else \\\r\n", -" expr\r\n", -"\r\n", -"#endif\r\n", -"\r\n", -"/* Define all Macros without '{' & '}' (None of these should be called externally!) */\r\n", -"#define ABS_( x ) OP_COUNT_( _ABS, ( x ) )\r\n", -"#define ADD_( x ) OP_COUNT_( _ADD, ( x ) )\r\n", -"#define MULT_( x ) OP_COUNT_( _MULT, ( x ) )\r\n", -"#define MAC_( x ) OP_COUNT_( _MAC, ( x ) )\r\n", -"#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) )\r\n", -"#define STORE_( x ) OP_COUNT_( _STORE, ( x ) )\r\n", -"#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) )\r\n", -"#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) )\r\n", -"#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) )\r\n", -"#define DIV_( x ) OP_COUNT_( _DIV, ( x ) )\r\n", -"#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) )\r\n", -"#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) )\r\n", -"#define POWER_( x ) TRANS_( x )\r\n", -"#define LOG_( x ) TRANS_( x )\r\n", -"#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) )\r\n", -"#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) )\r\n", -"#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) )\r\n", -"#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) )\r\n", -"#define MISC_( x ) ABS_( x )\r\n", -"\r\n", -"/* Math Operations */\r\n", -"#define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs )\r\n", -"#define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs )\r\n", -"#define fabsf_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabsf )\r\n", -"#define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs )\r\n", -"#define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor )\r\n", -"#define floorf_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floorf )\r\n", -"#define sqrt_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrt )\r\n", -"#define sqrtf_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf )\r\n", -"#define pow_ OP_COUNT_WRAPPER1_( POWER_( 1 ), pow )\r\n", -"#define powf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), powf )\r\n", -"#define exp_ OP_COUNT_WRAPPER1_( POWER_( 1 ), exp )\r\n", -"#define expf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), expf )\r\n", -"#define log_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log )\r\n", -"#define logf_ OP_COUNT_WRAPPER1_( LOG_( 1 ), logf )\r\n", -"#define log10_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10 )\r\n", -"#define log10f_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10f )\r\n", -"#define cos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cos )\r\n", -"#define cosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosf )\r\n", -"#define sin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sin )\r\n", -"#define sinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinf )\r\n", -"#define tan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tan )\r\n", -"#define tanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanf )\r\n", -"#define acos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acos )\r\n", -"#define acosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acosf )\r\n", -"#define asin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asin )\r\n", -"#define asinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asinf )\r\n", -"#define atan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan )\r\n", -"#define atanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atanf )\r\n", -"#define atan2_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2 )\r\n", -"#define atan2f_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2f )\r\n", -"#define cosh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosh )\r\n", -"#define coshf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), coshf )\r\n", -"#define sinh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinh )\r\n", -"#define sinhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinhf )\r\n", -"#define tanh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanh )\r\n", -"#define tanhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanhf )\r\n", -"#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod )\r\n", -"#define fmodf_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmodf )\r\n", -"#define frexp_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexp )\r\n", -"#define frexpf_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexpf )\r\n", -"\r\n", -"/* the macros below are instrumented versions of user-defined macros that might be used in the source code \r\n", -"/* representing some well-known and recognized mathematical operations (that are not defined in math.h) */\r\n", -"/* Note: the 'wmc_flag_=wmc_flag_' is used to avoid warning: left-hand operand of comma expression has no effect with gcc */\r\n", -"\r\n", -"#define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) )\r\n", -"#define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) )\r\n", -"#define MIN_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MIN( ( a ), ( b ) ) )\r\n", -"#define MAX_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MAX( ( a ), ( b ) ) )\r\n", -"#define Min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Min( ( a ), ( b ) ) )\r\n", -"#define Max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Max( ( a ), ( b ) ) )\r\n", -"#define sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), sqr( ( x ) ) )\r\n", -"#define Sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Sqr( ( x ) ) )\r\n", -"#define SQR_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQR( ( x ) ) )\r\n", -"#define square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), square( ( x ) ) )\r\n", -"#define Square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Square( ( x ) ) )\r\n", -"#define SQUARE_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQUARE( ( x ) ) )\r\n", -"#define sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), sign( ( x ) ) )\r\n", -"#define Sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), Sign( ( x ) ) )\r\n", -"#define SIGN_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), SIGN( ( x ) ) )\r\n", -"#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) )\r\n", -"#define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrtf( ( x ) ) )\r\n", -"#define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) )\r\n", -"#define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) )\r\n", -"#define log2f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2f( ( x ) ) )\r\n", -"#define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) )\r\n", -"#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) )\r\n", -"#define round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round( ( x ) ) )\r\n", -"#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) )\r\n", -"#define roundf_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, roundf( ( x ) ) )\r\n", -"#define set_min_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_min( ( a ), ( b ) ) )\r\n", -"#define set_max_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_max( ( a ), ( b ) ) )\r\n", -"\r\n", -"/* Functions */\r\n", -"#define func_( name, x ) OP_COUNT_WRAPPER1_( FUNC_( x ), name )\r\n", -"\r\n", -"/* Logical Operators */\r\n", -"#ifndef __\r\n", -"#define __ ( BRANCH_( 1 ), 1 ) &&\r\n", -"#endif\r\n", -"\r\n", -"/* Ternary Operators (? and :) */\r\n", -"#ifndef _\r\n", -"#define _ ( BRANCH_( 1 ), 0 ) ? 0:\r\n", -"#endif\r\n", -"\r\n", -"/* Flow Control keywords */\r\n", -"#define if_ \\\r\n", -" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n", -" if\r\n", -"#define for_ OP_COUNT_WRAPPER2_( LOOP_(1)) for\r\n", -"#define while_( c ) \\\r\n", -" while \\\r\n", -" OP_COUNT_WRAPPER1_( BRANCH_( 1 ), ( c ) ) /* needs extra \"()\" if ',' encountered */\r\n", -"#define do_ \\\r\n", -" do \\\r\n", -" {\r\n", -"#define _while \\\r\n", -" BRANCH_( 1 ); \\\r\n", -" } \\\r\n", -" while\r\n", -"\r\n", -"#define goto_ \\\r\n", -" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n", -" goto\r\n", -"#define break_ \\\r\n", -" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n", -" break\r\n", -"#define continue_ \\\r\n", -" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n", -" continue\r\n", -"#define return_ \\\r\n", -" OP_COUNT_WRAPPER2_( ( wmc_flag_ = stack_tree_level_, STACK_DEPTH_FCT_RETURN ) ) \\\r\n", -" return\r\n", -"\r\n", -"#define switch_ \\\r\n", -" OP_COUNT_WRAPPER2_( ( BRANCH_( 1 ), wmc_flag_ = 1 ) ) \\\r\n", -" switch\r\n", -"#define cost_( n ) OP_COUNT_WRAPPER2_( wmc_flag_ ? ( ADD_( n ), BRANCH_( n ), wmc_flag_ = 0 ) : 0 );\r\n", -"\r\n", -"#ifdef WMOPS\r\n", -"\r\n", -"#define ACC 2\r\n", -"#define MUL 1\r\n", -"\r\n", -"/* Counting Function (should not be called externally!) */\r\n", -"static void wops_( const char *ops )\r\n", -"{\r\n", -" char lm = 0; /* lm: Last Operation is Math */\r\n", -" static char lo = 0; /* Last Operation */\r\n", -"\r\n", -" void ( *fct )( const char *ops ) = wops_;\r\n", -"\r\n", -"st:\r\n", -" while ( *ops != '\\0' )\r\n", -" {\r\n", -" switch ( *ops++ )\r\n", -" {\r\n", -" int cnt;\r\n", -" case '-':\r\n", -" for ( cnt = 0; ops[cnt] == '>'; cnt++ )\r\n", -" ;\r\n", -" if ( cnt & 1 )\r\n", -" goto ind;\r\n", -" case '+':\r\n", -" lm = 2;\r\n", -" if ( lo & MUL )\r\n", -" {\r\n", -" MULT_( -1 );\r\n", -" MAC_( 1 );\r\n", -" break;\r\n", -" }\r\n", -" lo = ACC << 2;\r\n", -" case 'U':\r\n", -" case 'D':\r\n", -" ADD_( 1 );\r\n", -" break;\r\n", -" case '*':\r\n", -" lm = 2;\r\n", -" if ( lo & ACC )\r\n", -" {\r\n", -" ADD_( -1 );\r\n", -" MAC_( 1 );\r\n", -" break;\r\n", -" }\r\n", -" lo = MUL << 2;\r\n", -" MULT_( 1 );\r\n", -" break;\r\n", -" case '/':\r\n", -" case '%':\r\n", -" lm = 2;\r\n", -" DIV_( 1 );\r\n", -" break;\r\n", -" case '&':\r\n", -" case '|':\r\n", -" case '^':\r\n", -" lm = 2;\r\n", -" case '~':\r\n", -" LOGIC_( 1 );\r\n", -" break;\r\n", -" case '<':\r\n", -" case '>':\r\n", -" if ( *ops != ops[-1] )\r\n", -" goto error;\r\n", -" ops++;\r\n", -" case -85:\r\n", -" case -69:\r\n", -" lm = 2;\r\n", -" SHIFT_( 1 );\r\n", -" break;\r\n", -" case 'L':\r\n", -" case 'G':\r\n", -" if ( *ops == 't' )\r\n", -" goto comp;\r\n", -" case 'E':\r\n", -" case 'N':\r\n", -" if ( *ops != 'e' )\r\n", -" goto error;\r\n", -" comp:\r\n", -" ops++;\r\n", -" ADD_( 1 );\r\n", -" break;\r\n", -" case '!':\r\n", -" MISC_( 2 );\r\n", -" break;\r\n", -" case 'M':\r\n", -" MOVE_( 1 );\r\n", -" break;\r\n", -" case 'S':\r\n", -" STORE_( 1 );\r\n", -" break;\r\n", -" case 'P':\r\n", -" PTR_INIT_( 1 );\r\n", -" break;\r\n", -" case '[':\r\n", -" case ']':\r\n", -" goto st;\r\n", -" ind:\r\n", -" ops++;\r\n", -" case 'I':\r\n", -" case '.':\r\n", -" INDIRECT_( 1 );\r\n", -" break;\r\n", -" case '=':\r\n", -" if ( lm )\r\n", -" goto st;\r\n", -" case '\\0':\r\n", -" /* This Shouldn't Happen */\r\n", -" /* These are Used to Avoid: \"warning: 'name' defined but not used\" with Cygwin gcc Compiler */\r\n", -" wmc_flag_ = wmc_flag_;\r\n", -" ops_cnt_ptr = ops_cnt_ptr;\r\n", -" fct( \"\" );\r\n", -" error:\r\n", -" default:\r\n", -" fprintf( stderr, \"\\r wops: Invalid Counting Operation '%s'\\n\", ops - 1 );\r\n", -" exit( -1 );\r\n", -" }\r\n", -" lm >>= 1;\r\n", -" lo >>= 2;\r\n", -" }\r\n", -"\r\n", -" return;\r\n", -"}\r\n", -"\r\n", -"#endif\r\n", -"\r\n", -"/* All Other Operations */\r\n", -"#define $( str ) OP_COUNT_WRAPPER2_( wops_( str ) )\r\n", -"\r\n", -"\r\n", -"/*-------------------------------------------------------------------*\r\n", -" * Memory counting tool\r\n", -" *-------------------------------------------------------------------*/\r\n", -"\r\n", -"/* Enhanced Const Data Size Counting (Rounding Up to the Nearest 'Integer' Size) */\r\n", -"#define rsize( item ) ( ( sizeof( item ) + sizeof( int ) - 1 ) / sizeof( int ) * sizeof( int ) )\r\n", -"\r\n", -"#ifdef _MSC_VER\r\n", -"/* Disable \"warning C4210: nonstandard extension used : function given file scope\" with Visual Studio Compiler */\r\n", -"#pragma warning( disable : 4210 )\r\n", -"#endif\r\n", -"\r\n", -"/* Const Data Size and PROM Size Wrapper Functions */\r\n", -"#define Const_Data_Size_Func( file ) Const_Data_Size_##file( void )\r\n", -"#define Get_Const_Data_Size( file, val_ptr ) \\\r\n", -" { \\\r\n", -" extern int Const_Data_Size_##file( void ); \\\r\n", -" *( val_ptr ) = Const_Data_Size_##file(); \\\r\n", -" }\r\n", -"#define PROM_Size_Func( file ) PROM_Size_##file( void )\r\n", -"#define Get_PROM_Size( file, val_ptr ) \\\r\n", -" { \\\r\n", -" int PROM_Size_##file( void ); \\\r\n", -" *( val_ptr ) = PROM_Size_##file(); \\\r\n", -" }\r\n", -"\r\n", -"/* ROM Size Lookup Table - contains information about PROM size and Const Data Size in all source files */\r\n", -"/* The print_mem() function looks for this table to print the results of Const Data usage and PROM usage */\r\n", -"typedef struct ROM_Size_Lookup_Table\r\n", -"{\r\n", -" const char file_spec[255];\r\n", -" int PROM_size;\r\n", -" int ( *Get_Const_Data_Size_Func )( void );\r\n", -"} ROM_Size_Lookup_Table;\r\n", -"\r\n", -"/* The WMC tool inserts the following declaration during the innstrumentation process in the .c file where the function print_mem() is located */\r\n", -"/* and modifies it to print_mem(Const_Data_PROM_Table) */\r\n", -"\r\n", -"/* #ifdef WMOPS\r\n", -" * ROM_Size_Lookup_Table Const_Data_PROM_Table[] =\r\n", -" * {\r\n", -" * {\"../lib_enc/rom_enc.c\", 0, NULL},\r\n", -" * {\"../lib_com/*.c\", 0, NULL},\r\n", -" * {\"\", -1, NULL}\r\n", -" * };\r\n", -" * #endif\r\n", -" */\r\n", -"\r\n", -"/*#define MEM_ALIGN_64BITS */ /* Define this when using 64 Bits values in the code (ex: double), otherwise it will align on 32 Bits */\r\n", -"/*#define MEM_COUNT_DETAILS*/\r\n", -"\r\n", -"typedef enum\r\n", -"{\r\n", -" USE_BYTES = 0,\r\n", -" USE_16BITS = 1,\r\n", -" USE_32BITS = 2,\r\n", -" USE_64BITS = 3\r\n", -"} Counting_Size;\r\n", -"\r\n", -"#if ( defined( _WIN32 ) && ( _MSC_VER <= 1800 ) && ( _MSC_VER >= 1300 ) )\r\n", -"#define __func__ __FUNCTION__\r\n", -"#elif defined( __STDC_VERSION__ ) && __STDC_VERSION__ < 199901L\r\n", -"#if ( __GNUC__ >= 2 )\r\n", -"#define __func__ __FUNCTION__\r\n", -"#else\r\n", -"#define __func__ \"\"\r\n", -"#endif\r\n", -"#elif defined( __GNUC__ )\r\n", -"#define __func__ __extension__ __FUNCTION__\r\n", -"#endif\r\n", -"\r\n", -"\r\n", -"#ifdef WMOPS\r\n", -"\r\n", -"void *mem_alloc( const char *func_name, int func_lineno, size_t size, char *alloc_str );\r\n", -"void mem_free( const char *func_name, int func_lineno, void *ptr );\r\n", -"\r\n", -"#define malloc_( size ) mem_alloc( __func__, __LINE__, size, \"m:\" #size )\r\n", -"#define calloc_( n, size ) mem_alloc( __func__, __LINE__, ( n ) * ( size ), \"c:\" #n \", \" #size )\r\n", -"#define free_( ptr ) mem_free( __func__, __LINE__, ptr )\r\n", -"\r\n", -"void reset_mem( Counting_Size cnt_size );\r\n", -"void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] );\r\n", -"\r\n", -"int push_stack( const char *filename, const char *fctname );\r\n", -"int pop_stack( const char *filename, const char *fctname );\r\n", -"\r\n", -"#ifdef WMOPS_DETAIL\r\n", -"#define STACK_DEPTH_FCT_CALL ( push_wmops( __FUNCTION__ \" [WMC_AUTO]\" ), push_stack( __FILE__, __FUNCTION__ ) ) /* add push_wmops() in all function calls */\r\n", -"#define STACK_DEPTH_FCT_RETURN ( pop_wmops(), pop_stack( __FILE__, __FUNCTION__ ) ) /* add pop_wmops() in all function returns */\r\n", -"#else\r\n", -"#define STACK_DEPTH_FCT_CALL push_stack( __FILE__, __FUNCTION__ )\r\n", -"#define STACK_DEPTH_FCT_RETURN pop_stack( __FILE__, __FUNCTION__ )\r\n", -"#endif\r\n", -"\r\n", -"void reset_stack( void );\r\n", -"#define func_start_ int stack_tree_level_ = STACK_DEPTH_FCT_CALL;\r\n", -"\r\n", -"#else\r\n", -"#define malloc_( n1 ) malloc( n1 )\r\n", -"#define calloc_( n1, n2 ) calloc( n1, n2 )\r\n", -"#define free_( ptr ) free( ptr )\r\n", -"#define reset_mem( cnt_size )\r\n", -"#define print_mem( Const_Data_PROM_Table )\r\n", -"\r\n", -"#define push_stack( file, fct )\r\n", -"#define pop_stack( file, fct )\r\n", -"#define reset_stack()\r\n", -"#define func_start_\r\n", -"\r\n", -"#endif\r\n", -"\r\n", -"\r\n", -"/* Global counter variable for calculation of complexity weight */\r\n", -"typedef struct\r\n", -"{\r\n", -" unsigned int add; /* Complexity Weight of 1 */\r\n", -" unsigned int sub; /* Complexity Weight of 1 */\r\n", -" unsigned int abs_s; /* Complexity Weight of 1 */\r\n", -" unsigned int shl; /* Complexity Weight of 1 */\r\n", -" unsigned int shr; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int extract_h; /* Complexity Weight of 1 */\r\n", -" unsigned int extract_l; /* Complexity Weight of 1 */\r\n", -" unsigned int mult; /* Complexity Weight of 1 */\r\n", -" unsigned int L_mult; /* Complexity Weight of 1 */\r\n", -" unsigned int negate; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int round; /* Complexity Weight of 1 */\r\n", -" unsigned int L_mac; /* Complexity Weight of 1 */\r\n", -" unsigned int L_msu; /* Complexity Weight of 1 */\r\n", -" unsigned int L_macNs; /* Complexity Weight of 1 */\r\n", -" unsigned int L_msuNs; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int L_add; /* Complexity Weight of 1 */\r\n", -" unsigned int L_sub; /* Complexity Weight of 1 */\r\n", -" unsigned int L_add_c; /* Complexity Weight of 2 */\r\n", -" unsigned int L_sub_c; /* Complexity Weight of 2 */\r\n", -" unsigned int L_negate; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int L_shl; /* Complexity Weight of 1 */\r\n", -" unsigned int L_shr; /* Complexity Weight of 1 */\r\n", -" unsigned int mult_r; /* Complexity Weight of 1 */\r\n", -" unsigned int shr_r; /* Complexity Weight of 3 */\r\n", -" unsigned int mac_r; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int msu_r; /* Complexity Weight of 1 */\r\n", -" unsigned int L_deposit_h; /* Complexity Weight of 1 */\r\n", -" unsigned int L_deposit_l; /* Complexity Weight of 1 */\r\n", -" unsigned int L_shr_r; /* Complexity Weight of 3 */\r\n", -" unsigned int L_abs; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int L_sat; /* Complexity Weight of 4 */\r\n", -" unsigned int norm_s; /* Complexity Weight of 1 */\r\n", -" unsigned int div_s; /* Complexity Weight of 18 */\r\n", -" unsigned int norm_l; /* Complexity Weight of 1 */\r\n", -" unsigned int move16; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int move32; /* Complexity Weight of 2 */\r\n", -" unsigned int Logic16; /* Complexity Weight of 1 */\r\n", -" unsigned int Logic32; /* Complexity Weight of 2 */\r\n", -" unsigned int Test; /* Complexity Weight of 2 */\r\n", -" unsigned int s_max; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int s_min; /* Complexity Weight of 1 */\r\n", -" unsigned int L_max; /* Complexity Weight of 1 */\r\n", -" unsigned int L_min; /* Complexity Weight of 1 */\r\n", -" unsigned int L40_max; /* Complexity Weight of 1 */\r\n", -" unsigned int L40_min; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int shl_r; /* Complexity Weight of 3 */\r\n", -" unsigned int L_shl_r; /* Complexity Weight of 3 */\r\n", -" unsigned int L40_shr_r; /* Complexity Weight of 3 */\r\n", -" unsigned int L40_shl_r; /* Complexity Weight of 3 */\r\n", -" unsigned int norm_L40; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int L40_shl; /* Complexity Weight of 1 */\r\n", -" unsigned int L40_shr; /* Complexity Weight of 1 */\r\n", -" unsigned int L40_negate; /* Complexity Weight of 1 */\r\n", -" unsigned int L40_add; /* Complexity Weight of 1 */\r\n", -" unsigned int L40_sub; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int L40_abs; /* Complexity Weight of 1 */\r\n", -" unsigned int L40_mult; /* Complexity Weight of 1 */\r\n", -" unsigned int L40_mac; /* Complexity Weight of 1 */\r\n", -" unsigned int mac_r40; /* Complexity Weight of 2 */\r\n", -"\r\n", -" unsigned int L40_msu; /* Complexity Weight of 1 */\r\n", -" unsigned int msu_r40; /* Complexity Weight of 2 */\r\n", -" unsigned int Mpy_32_16_ss; /* Complexity Weight of 2 */\r\n", -" unsigned int Mpy_32_32_ss; /* Complexity Weight of 4 */\r\n", -" unsigned int L_mult0; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int L_mac0; /* Complexity Weight of 1 */\r\n", -" unsigned int L_msu0; /* Complexity Weight of 1 */\r\n", -" unsigned int lshl; /* Complexity Weight of 1 */\r\n", -" unsigned int lshr; /* Complexity Weight of 1 */\r\n", -" unsigned int L_lshl; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int L_lshr; /* Complexity Weight of 1 */\r\n", -" unsigned int L40_lshl; /* Complexity Weight of 1 */\r\n", -" unsigned int L40_lshr; /* Complexity Weight of 1 */\r\n", -" unsigned int s_and; /* Complexity Weight of 1 */\r\n", -" unsigned int s_or; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int s_xor; /* Complexity Weight of 1 */\r\n", -" unsigned int L_and; /* Complexity Weight of 1 */\r\n", -" unsigned int L_or; /* Complexity Weight of 1 */\r\n", -" unsigned int L_xor; /* Complexity Weight of 1 */\r\n", -" unsigned int rotl; /* Complexity Weight of 3 */\r\n", -"\r\n", -" unsigned int rotr; /* Complexity Weight of 3 */\r\n", -" unsigned int L_rotl; /* Complexity Weight of 3 */\r\n", -" unsigned int L_rotr; /* Complexity Weight of 3 */\r\n", -" unsigned int L40_set; /* Complexity Weight of 3 */\r\n", -" unsigned int L40_deposit_h; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int L40_deposit_l; /* Complexity Weight of 1 */\r\n", -" unsigned int L40_deposit32; /* Complexity Weight of 1 */\r\n", -" unsigned int Extract40_H; /* Complexity Weight of 1 */\r\n", -" unsigned int Extract40_L; /* Complexity Weight of 1 */\r\n", -" unsigned int L_Extract40; /* Complexity Weight of 1 */\r\n", -"\r\n", -" unsigned int L40_round; /* Complexity Weight of 1 */\r\n", -" unsigned int L_saturate40; /* Complexity Weight of 1 */\r\n", -" unsigned int round40; /* Complexity Weight of 1 */\r\n", -" unsigned int If; /* Complexity Weight of 4 */\r\n", -" unsigned int Goto; /* Complexity Weight of 4 */\r\n", -"\r\n", -" unsigned int Break; /* Complexity Weight of 4 */\r\n", -" unsigned int Switch; /* Complexity Weight of 8 */\r\n", -" unsigned int For; /* Complexity Weight of 3 */\r\n", -" unsigned int While; /* Complexity Weight of 4 */\r\n", -" unsigned int Continue; /* Complexity Weight of 4 */\r\n", -"\r\n", -" unsigned int L_mls; /* Complexity Weight of 6 */\r\n", -" unsigned int div_l; /* Complexity Weight of 32 */\r\n", -" unsigned int i_mult; /* Complexity Weight of 3 */\r\n", -"} BASIC_OP;\r\n", -"\r\n", -"#ifdef WMOPS\r\n", -"extern BASIC_OP *multiCounter;\r\n", -"extern int currCounter;\r\n", -"\r\n", -"/* Technical note :\r\n", -" * The following 3 variables are only used for correct complexity\r\n", -" * evaluation of the following structure :\r\n", -" * IF{\r\n", -" * ...\r\n", -" * } ELSE IF {\r\n", -" * ...\r\n", -" * } ELSE IF {\r\n", -" * ...\r\n", -" * }\r\n", -" * ...\r\n", -" * } ELSE {\r\n", -" * ...\r\n", -" * }\r\n", -" */\r\n", -"extern int funcId_where_last_call_to_else_occurred;\r\n", -"extern long funcid_total_wmops_at_last_call_to_else;\r\n", -"extern int call_occurred;\r\n", -"\r\n", -"extern long TotalWeightedOperation( void );\r\n", -"long DeltaWeightedOperation( void );\r\n", -"\r\n", -"void Set_BASOP_WMOPS_counter( int counterId );\r\n", -"void Reset_BASOP_WMOPS_counter( void );\r\n", -"\r\n", -"#endif\r\n", -"\r\n", -"/*****************************************************************************\r\n", -" *\r\n", -" * Function Name : FOR\r\n", -" *\r\n", -" * Purpose :\r\n", -" *\r\n", -" * The macro FOR should be used instead of the 'for' C statement.\r\n", -" * The complexity is independent of the number of loop iterations that are\r\n", -" * performed.\r\n", -" *\r\n", -" * Complexity weight : 3 (regardless of number of iterations).\r\n", -" *\r\n", -" *****************************************************************************/\r\n", -"#ifndef WMOPS\r\n", -"#define FOR( a) for( a)\r\n", -"\r\n", -"#else \r\n", -"#define FOR( a) if( incrFor(), 0); else for( a)\r\n", -"\r\n", -"static __inline void incrFor( void) {\r\n", -" multiCounter[currCounter].For++;\r\n", -"}\r\n", -"#endif \r\n", -"\r\n", -"\r\n", -"/*****************************************************************************\r\n", -" *\r\n", -" * Function Name : WHILE\r\n", -" *\r\n", -" * Purpose :\r\n", -" *\r\n", -" * The macro WHILE should be used instead of the 'while' C statement.\r\n", -" * The complexity is proportional to the number of loop iterations that\r\n", -" * are performed.\r\n", -" *\r\n", -" * Complexity weight : 4 x 'number of loop iterations'.\r\n", -" *\r\n", -" *****************************************************************************/\r\n", -"#ifndef WMOPS\r\n", -"#define WHILE( a) while( a)\r\n", -"\r\n", -"#else \r\n", -"#define WHILE( a) while( incrWhile(), a)\r\n", -"\r\n", -"static __inline void incrWhile( void) {\r\n", -" multiCounter[currCounter].While++;\r\n", -"}\r\n", -"#endif \r\n", -"\r\n", -"\r\n", -"/*****************************************************************************\r\n", -" *\r\n", -" * Function Name : DO\r\n", -" *\r\n", -" * Purpose :\r\n", -" *\r\n", -" * The macro DO should be used instead of the 'do' C statement.\r\n", -" *\r\n", -" * Complexity weight : 0 (complexity counted by WHILE macro).\r\n", -" *\r\n", -" *****************************************************************************/\r\n", -"#ifndef WMOPS\r\n", -"#define DO do\r\n", -"\r\n", -"#else \r\n", -"#define DO do\r\n", -"\r\n", -"#endif \r\n", -"\r\n", -"\r\n", -"/*****************************************************************************\r\n", -" *\r\n", -" * Function Name : IF\r\n", -" *\r\n", -" * Purpose :\r\n", -" *\r\n", -" * The macro IF should :\r\n", -" *\r\n", -" * - not be used when :\r\n", -" * - the 'if' structure does not have any 'else if' nor 'else' statement\r\n", -" * - and it conditions only one DSP basic operations.\r\n", -" *\r\n", -" * - be used instead of the 'if' C statement in every other case :\r\n", -" * - when there is an 'else' or 'else if' statement,\r\n", -" * - or when the 'if' conditions several DSP basic operations,\r\n", -" * - or when the 'if' conditions a function call.\r\n", -" *\r\n", -" * Complexity weight : 4\r\n", -" *\r\n", -" *****************************************************************************/\r\n", -"#ifndef WMOPS\r\n", -"#define IF( a) if( a)\r\n", -"\r\n", -"#else \r\n", -"#define IF( a) if( incrIf(), a)\r\n", -"\r\n", -"static __inline void incrIf( void) {\r\n", -" /* Technical note :\r\n", -" * If the \"IF\" operator comes just after an \"ELSE\", its counter\r\n", -" * must not be incremented.\r\n", -" */\r\n", -" if ( ( currCounter != funcId_where_last_call_to_else_occurred ) || ( TotalWeightedOperation() != funcid_total_wmops_at_last_call_to_else ) || ( call_occurred == 1 ) )\r\n", -" {\r\n", -" multiCounter[currCounter].If++;\r\n", -" }\r\n", -"\r\n", -" call_occurred = 0;\r\n", -" funcId_where_last_call_to_else_occurred = INT_MAX;\r\n", -"}\r\n", -"#endif \r\n", -"\r\n", -"\r\n", -"/*****************************************************************************\r\n", -" *\r\n", -" * Function Name : ELSE\r\n", -" *\r\n", -" * Purpose :\r\n", -" *\r\n", -" * The macro ELSE should be used instead of the 'else' C statement.\r\n", -" *\r\n", -" * Complexity weight : 4\r\n", -" *\r\n", -" *****************************************************************************/\r\n", -"#ifndef WMOPS\r\n", -"#define ELSE else\r\n", -"\r\n", -"#else \r\n", -"#define ELSE else if( incrElse(), 0) ; else\r\n", -"\r\n", -"static __inline void incrElse( void) {\r\n", -" multiCounter[currCounter].If++;\r\n", -"\r\n", -" /* We keep track of the funcId of the last function\r\n", -" * which used ELSE {...} structure.\r\n", -" */\r\n", -" funcId_where_last_call_to_else_occurred = currCounter;\r\n", -"\r\n", -" /* We keep track of the number of WMOPS of this funcId\r\n", -" * when the ELSE macro was called.\r\n", -" */\r\n", -" funcid_total_wmops_at_last_call_to_else = TotalWeightedOperation();\r\n", -"\r\n", -" /* call_occurred is set to 0, in order to count the next IF (if necessary)\r\n", -" */\r\n", -" call_occurred = 0;\r\n", -"}\r\n", -"#endif \r\n", -"\r\n", -"\r\n", -"/*****************************************************************************\r\n", -" *\r\n", -" * Function Name : SWITCH\r\n", -" *\r\n", -" * Purpose :\r\n", -" *\r\n", -" * The macro SWITCH should be used instead of the 'switch' C statement.\r\n", -" *\r\n", -" * Complexity weight : 8\r\n", -" *\r\n", -" *****************************************************************************/\r\n", -"#ifndef WMOPS\r\n", -"#define SWITCH( a) switch( a)\r\n", -"\r\n", -"#else \r\n", -"#define SWITCH( a) switch( incrSwitch(), a)\r\n", -"\r\n", -"static __inline void incrSwitch( void) {\r\n", -" multiCounter[currCounter].Switch++;\r\n", -"}\r\n", -"#endif \r\n", -"\r\n", -"\r\n", -"/*****************************************************************************\r\n", -" *\r\n", -" * Function Name : CONTINUE\r\n", -" *\r\n", -" * Purpose :\r\n", -" *\r\n", -" * The macro CONTINUE should be used instead of the 'continue' C statement.\r\n", -" *\r\n", -" * Complexity weight : 4\r\n", -" *\r\n", -" *****************************************************************************/\r\n", -"#ifndef WMOPS\r\n", -"#define CONTINUE continue\r\n", -"\r\n", -"#else \r\n", -"#define CONTINUE if( incrContinue(), 0); else continue\r\n", -"\r\n", -"static __inline void incrContinue( void) {\r\n", -" multiCounter[currCounter].Continue++;\r\n", -"}\r\n", -"#endif \r\n", -"\r\n", -"\r\n", -"/*****************************************************************************\r\n", -" *\r\n", -" * Function Name : BREAK\r\n", -" *\r\n", -" * Purpose :\r\n", -" *\r\n", -" * The macro BREAK should be used instead of the 'break' C statement.\r\n", -" *\r\n", -" * Complexity weight : 4\r\n", -" *\r\n", -" *****************************************************************************/\r\n", -"#ifndef WMOPS\r\n", -"#define BREAK break\r\n", -"\r\n", -"#else \r\n", -"#define BREAK if( incrBreak(), 0) break; else break\r\n", -"\r\n", -"static __inline void incrBreak( void) {\r\n", -" multiCounter[currCounter].Break++;\r\n", -"}\r\n", -"#endif \r\n", -"\r\n", -"\r\n", -"/*****************************************************************************\r\n", -" *\r\n", -" * Function Name : GOTO\r\n", -" *\r\n", -" * Purpose :\r\n", -" *\r\n", -" * The macro GOTO should be used instead of the 'goto' C statement.\r\n", -" *\r\n", -" * Complexity weight : 4\r\n", -" *\r\n", -" *****************************************************************************/\r\n", -"#ifndef WMOPS\r\n", -"#define GOTO goto\r\n", -"\r\n", -"#else \r\n", -"#define GOTO if( incrGoto(), 0); else goto\r\n", -"\r\n", -"static __inline void incrGoto( void) {\r\n", -" multiCounter[currCounter].Goto++;\r\n", -"}\r\n", -"#endif \r\n", -"\r\n", -"#endif /* WMOPS_H */\r\n", -"\r\n", -"\r\n", -"\r\n", \ No newline at end of file +"/*\r\n" +" * (C) 2024 copyright VoiceAge Corporation. All Rights Reserved.\r\n" +" *\r\n" +" * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n" +" * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n" +" * or refer to ITU-T Recommendation G.191 on \"SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS\".\r\n" +" *\r\n" +" * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor\r\n" +" * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software\r\n" +" * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE.\r\n" +" *\r\n" +" * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca)\r\n" +" */\r\n" +"\r\n" +"#ifndef WMOPS_H\r\n" +"#define WMOPS_H\r\n" +"\r\n" +"#ifndef EXIT_FAILURE\r\n" +"#include /* stdlib is needed for exit() */\r\n" +"#endif\r\n" +"\r\n" +"#ifndef EOF\r\n" +"#include /* stdio is needed for fprintf() */\r\n" +"#endif\r\n" +"\r\n" +"/* To Prevent \"warning: '$' in identifier or number\" message under GCC */\r\n" +"#ifdef __GNUC__\r\n" +"#pragma GCC system_header\r\n" +"#endif\r\n" +"\r\n" +"#define ENH_32_BIT_OPERATOR\r\n" +"#define ENH_64_BIT_OPERATOR\r\n" +"#define ENH_U_32_BIT_OPERATOR\r\n" +"#define COMPLEX_OPERATOR\r\n" +"#define CONTROL_CODE_OPS /* enable control code operators such as LT_16, GT_16, ... */\r\n" +"\r\n" +"#ifdef WMOPS\r\n" +"enum instructions\r\n" +"{\r\n" +" _ADD,\r\n" +" _ABS,\r\n" +" _MULT,\r\n" +" _MAC,\r\n" +" _MOVE,\r\n" +" _STORE,\r\n" +" _LOGIC,\r\n" +" _SHIFT,\r\n" +" _BRANCH,\r\n" +" _DIV,\r\n" +" _SQRT,\r\n" +" _TRANS,\r\n" +" _FUNC,\r\n" +" _LOOP,\r\n" +" _INDIRECT,\r\n" +" _PTR_INIT,\r\n" +" _TEST,\r\n" +" _POWER,\r\n" +" _LOG,\r\n" +" _MISC,\r\n" +" NUM_INST\r\n" +"};\r\n" +"\r\n" +"extern double ops_cnt;\r\n" +"extern double inst_cnt[NUM_INST];\r\n" +"\r\n" +"/******************************************************************/\r\n" +"/* NOTES: */\r\n" +"/* The 'wmc_flag_' flag is global to avoid declaration in every */\r\n" +"/* function and 'static' to avoid clashing with other modules */\r\n" +"/* that include this header file. */\r\n" +"/* */\r\n" +"/* The declarations of 'wmc_flag_' and 'wops_' in this header */\r\n" +"/* file prevent the addition of a 'C' file to the Project. */\r\n" +"/******************************************************************/\r\n" +"\r\n" +"/* General Purpose Global int */\r\n" +"static int wmc_flag_ = 0;\r\n" +"\r\n" +"#define push_wmops( ... ) push_wmops_fct( __VA_ARGS__, NULL )\r\n" +"void push_wmops_fct( const char *label, ... );\r\n" +"void pop_wmops( void );\r\n" +"void reset_wmops( void );\r\n" +"void print_wmops( void );\r\n" +"void update_wmops( void );\r\n" +"void update_mem( void );\r\n" +"\r\n" +"#define _ADD_C 1\r\n" +"#define _ABS_C 1\r\n" +"#define _MULT_C 1\r\n" +"#define _MAC_C 1\r\n" +"#define _MOVE_C 1\r\n" +"#define _STORE_C 1\r\n" +"#define _LOGIC_C 1\r\n" +"#define _SHIFT_C 1\r\n" +"#define _BRANCH_C 4\r\n" +"#define _DIV_C 18\r\n" +"#define _SQRT_C 10\r\n" +"#define _TRANS_C 25\r\n" +"#define _FUNC_C 2 /* need to add number of arguments */\r\n" +"#define _LOOP_C 3\r\n" +"#define _INDIRECT_C 2\r\n" +"#define _PTR_INIT_C 1\r\n" +"#define _TEST_C 2\r\n" +"#define _POWER_C 25\r\n" +"#define _LOG_C 25\r\n" +"#define _MISC_C 1\r\n" +"\r\n" +"#define ADD( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _ADD_C * ( x ) ); \\\r\n" +" inst_cnt[_ADD] += ( x ); \\\r\n" +" }\r\n" +"#define ABS( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _ABS_C * ( x ) ); \\\r\n" +" inst_cnt[_ABS] += ( x ); \\\r\n" +" }\r\n" +"#define MULT( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _MULT_C * ( x ) ); \\\r\n" +" inst_cnt[_MULT] += ( x ); \\\r\n" +" }\r\n" +"#define MAC( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _MAC_C * ( x ) ); \\\r\n" +" inst_cnt[_MAC] += ( x ); \\\r\n" +" }\r\n" +"#define MOVE( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _MOVE_C * ( x ) ); \\\r\n" +" inst_cnt[_MOVE] += ( x ); \\\r\n" +" }\r\n" +"#define STORE( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _STORE_C * ( x ) ); \\\r\n" +" inst_cnt[_STORE] += ( x ); \\\r\n" +" }\r\n" +"#define LOGIC( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _LOGIC_C * ( x ) ); \\\r\n" +" inst_cnt[_LOGIC] += ( x ); \\\r\n" +" }\r\n" +"#define SHIFT( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _SHIFT_C * ( x ) ); \\\r\n" +" inst_cnt[_SHIFT] += ( x ); \\\r\n" +" }\r\n" +"#define BRANCH( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _BRANCH_C * ( x ) ); \\\r\n" +" inst_cnt[_BRANCH] += ( x ); \\\r\n" +" }\r\n" +"#define DIV( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _DIV_C * ( x ) ); \\\r\n" +" inst_cnt[_DIV] += ( x ); \\\r\n" +" }\r\n" +"#define SQRT( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _SQRT_C * ( x ) ); \\\r\n" +" inst_cnt[_SQRT] += ( x ); \\\r\n" +" }\r\n" +"#define TRANS( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _TRANS_C * ( x ) ); \\\r\n" +" inst_cnt[_TRANS] += ( x ); \\\r\n" +" }\r\n" +"#define LOOP( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _LOOP_C * ( x ) ); \\\r\n" +" inst_cnt[_LOOP] += ( x ); \\\r\n" +" }\r\n" +"#define INDIRECT( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _INDIRECT_C * ( x ) ); \\\r\n" +" inst_cnt[_INDIRECT] += ( x ); \\\r\n" +" }\r\n" +"#define PTR_INIT( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _PTR_INIT_C * ( x ) ); \\\r\n" +" inst_cnt[_PTR_INIT] += ( x ); \\\r\n" +" }\r\n" +"#define TEST( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _TEST_C * ( x ) ); \\\r\n" +" inst_cnt[_TEST] += ( x ); \\\r\n" +" }\r\n" +"#define POWER( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _POWER_C * ( x ) ); \\\r\n" +" inst_cnt[_POWER] += ( x ); \\\r\n" +" }\r\n" +"#define LOG( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _LOG_C * ( x ) ); \\\r\n" +" inst_cnt[_LOG] += ( x ); \\\r\n" +" }\r\n" +"#define MISC( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _MISC_C * ( x ) ); \\\r\n" +" inst_cnt[_MISC] += ( x ); \\\r\n" +" }\r\n" +"#define FUNC( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( _FUNC_C + _MOVE_C * ( x ) ); \\\r\n" +" inst_cnt[_FUNC]++; \\\r\n" +" inst_cnt[_MOVE] += ( x ); \\\r\n" +" }\r\n" +"#define DADD( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( 2 * _ADD_C * ( x ) ); \\\r\n" +" inst_cnt[_ADD] += ( x ); \\\r\n" +" }\r\n" +"#define DMULT( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( 2 * _MULT_C * ( x ) ); \\\r\n" +" inst_cnt[_MULT] += ( x ); \\\r\n" +" }\r\n" +"#define DMAC( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( 2 * _MAC_C * ( x ) ); \\\r\n" +" inst_cnt[_MAC] += ( x ); \\\r\n" +" }\r\n" +"#define DMOVE( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( 2 * _MOVE_C * ( x ) ); \\\r\n" +" inst_cnt[_MOVE] += ( x ); \\\r\n" +" }\r\n" +"#define DSTORE( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( 2 * _STORE_C * ( x ) ); \\\r\n" +" inst_cnt[_STORE] += ( x ); \\\r\n" +" }\r\n" +"#define DLOGIC( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( 2 * _LOGIC_C * ( x ) ); \\\r\n" +" inst_cnt[_LOGIC] += ( x ); \\\r\n" +" }\r\n" +"#define DSHIFT( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( 2 * _SHIFT_C * ( x ) ); \\\r\n" +" inst_cnt[_SHIFT] += ( x ); \\\r\n" +" }\r\n" +"#define DDIV( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( 2 * _DIV_C * ( x ) ); \\\r\n" +" inst_cnt[_DIV] += ( x ); \\\r\n" +" }\r\n" +"#define DSQRT( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( 2 * _SQRT_C * ( x ) ); \\\r\n" +" inst_cnt[_SQRT] += ( x ); \\\r\n" +" }\r\n" +"#define DTRANS( x ) \\\r\n" +" { \\\r\n" +" ops_cnt += ( 2 * _TRANS_C * ( x ) ); \\\r\n" +" inst_cnt[_TRANS] += ( x ); \\\r\n" +" } \r\n" +"\r\n" +"#else\r\n" +"\r\n" +"extern int cntr_push_pop;\r\n" +"#define push_wmops( x ) ( cntr_push_pop++ )\r\n" +"#define pop_wmops() ( cntr_push_pop-- )\r\n" +"#define reset_wmops()\r\n" +"#define print_wmops()\r\n" +"#define update_wmops() ( assert( cntr_push_pop == 0 ) )\r\n" +"#define update_mem()\r\n" +"\r\n" +"#define ADD( x )\r\n" +"#define ABS( x )\r\n" +"#define MULT( x )\r\n" +"#define MAC( x )\r\n" +"#define MOVE( x )\r\n" +"#define STORE( x )\r\n" +"#define LOGIC( x )\r\n" +"#define SHIFT( x )\r\n" +"#define BRANCH( x )\r\n" +"#define DIV( x )\r\n" +"#define SQRT( x )\r\n" +"#define TRANS( x )\r\n" +"#define FUNC( x )\r\n" +"#define LOOP( x )\r\n" +"#define INDIRECT( x )\r\n" +"#define PTR_INIT( x )\r\n" +"#define TEST( x )\r\n" +"#define POWER( x )\r\n" +"#define LOG( x )\r\n" +"#define MISC( x )\r\n" +"\r\n" +"#define DADD( x )\r\n" +"#define DMULT( x )\r\n" +"#define DMAC( x )\r\n" +"#define DMOVE( x )\r\n" +"#define DSTORE( x )\r\n" +"#define DLOGIC( x )\r\n" +"#define DSHIFT( x )\r\n" +"#define DDIV( x )\r\n" +"#define DSQRT( x )\r\n" +"#define DTRANS( x )\r\n" +"\r\n" +"#endif\r\n" +"\r\n" +"#ifndef WMOPS\r\n" +"/* DESACTIVATE the Counting Mechanism */\r\n" +"#define OP_COUNT_( op, n )\r\n" +"\r\n" +"/* DESACTIVATE Operation Counter Wrappers */\r\n" +"#define OP_COUNT_WRAPPER1_( op, val ) ( val )\r\n" +"#define OP_COUNT_WRAPPER2_( expr )\r\n" +"#define OP_COUNT_WRAPPER3_( op, expr ) expr\r\n" +"\r\n" +"/* DESACTIVATE Logical & Ternary Operators */\r\n" +"#define __\r\n" +"#define _\r\n" +"\r\n" +"#else\r\n" +"\r\n" +"/* Operation Counter Wrappers */\r\n" +"#define OP_COUNT_( op, x ) ( ops_cnt += ( op##_C * ( x ) ), inst_cnt[op] += ( x ) )\r\n" +"#define OP_COUNT_WRAPPER1_( op, val ) ( op, val )\r\n" +"#define OP_COUNT_WRAPPER2_( expr ) \\\r\n" +" if ( expr, 0 ) \\\r\n" +" ; \\\r\n" +" else\r\n" +"#define OP_COUNT_WRAPPER3_( op, expr ) \\\r\n" +" if ( op, 0 ) \\\r\n" +" ; \\\r\n" +" else \\\r\n" +" expr\r\n" +"\r\n" +"#endif\r\n" +"\r\n" +"/* Define all Macros without '{' & '}' (None of these should be called externally!) */\r\n" +"#define ABS_( x ) OP_COUNT_( _ABS, ( x ) )\r\n" +"#define ADD_( x ) OP_COUNT_( _ADD, ( x ) )\r\n" +"#define MULT_( x ) OP_COUNT_( _MULT, ( x ) )\r\n" +"#define MAC_( x ) OP_COUNT_( _MAC, ( x ) )\r\n" +"#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) )\r\n" +"#define STORE_( x ) OP_COUNT_( _STORE, ( x ) )\r\n" +"#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) )\r\n" +"#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) )\r\n" +"#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) )\r\n" +"#define DIV_( x ) OP_COUNT_( _DIV, ( x ) )\r\n" +"#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) )\r\n" +"#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) )\r\n" +"#define POWER_( x ) TRANS_( x )\r\n" +"#define LOG_( x ) TRANS_( x )\r\n" +"#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) )\r\n" +"#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) )\r\n" +"#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) )\r\n" +"#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) )\r\n" +"#define MISC_( x ) ABS_( x )\r\n" +"\r\n" +"/* Math Operations */\r\n" +"#define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs )\r\n" +"#define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs )\r\n" +"#define fabsf_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabsf )\r\n" +"#define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs )\r\n" +"#define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor )\r\n" +"#define floorf_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floorf )\r\n" +"#define sqrt_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrt )\r\n" +"#define sqrtf_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf )\r\n" +"#define pow_ OP_COUNT_WRAPPER1_( POWER_( 1 ), pow )\r\n" +"#define powf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), powf )\r\n" +"#define exp_ OP_COUNT_WRAPPER1_( POWER_( 1 ), exp )\r\n" +"#define expf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), expf )\r\n" +"#define log_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log )\r\n" +"#define logf_ OP_COUNT_WRAPPER1_( LOG_( 1 ), logf )\r\n" +"#define log10_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10 )\r\n" +"#define log10f_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10f )\r\n" +"#define cos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cos )\r\n" +"#define cosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosf )\r\n" +"#define sin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sin )\r\n" +"#define sinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinf )\r\n" +"#define tan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tan )\r\n" +"#define tanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanf )\r\n" +"#define acos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acos )\r\n" +"#define acosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acosf )\r\n" +"#define asin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asin )\r\n" +"#define asinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asinf )\r\n" +"#define atan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan )\r\n" +"#define atanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atanf )\r\n" +"#define atan2_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2 )\r\n" +"#define atan2f_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2f )\r\n" +"#define cosh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosh )\r\n" +"#define coshf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), coshf )\r\n" +"#define sinh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinh )\r\n" +"#define sinhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinhf )\r\n" +"#define tanh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanh )\r\n" +"#define tanhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanhf )\r\n" +"#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod )\r\n" +"#define fmodf_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmodf )\r\n" +"#define frexp_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexp )\r\n" +"#define frexpf_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexpf )\r\n" +"\r\n" +"/* the macros below are instrumented versions of user-defined macros that might be used in the source code \r\n" +" representing some well-known and recognized mathematical operations (that are not defined in math.h) \r\n" +" Note: the 'wmc_flag_=wmc_flag_' is used to avoid warning: left-hand operand of comma expression has no effect with gcc */\r\n" +"\r\n" +"#define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) )\r\n" +"#define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) )\r\n" +"#define MIN_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MIN( ( a ), ( b ) ) )\r\n" +"#define MAX_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MAX( ( a ), ( b ) ) )\r\n" +"#define Min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Min( ( a ), ( b ) ) )\r\n" +"#define Max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Max( ( a ), ( b ) ) )\r\n" +"#define sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), sqr( ( x ) ) )\r\n" +"#define Sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Sqr( ( x ) ) )\r\n" +"#define SQR_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQR( ( x ) ) )\r\n" +"#define square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), square( ( x ) ) )\r\n" +"#define Square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Square( ( x ) ) )\r\n" +"#define SQUARE_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQUARE( ( x ) ) )\r\n" +"#define sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), sign( ( x ) ) )\r\n" +"#define Sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), Sign( ( x ) ) )\r\n" +"#define SIGN_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), SIGN( ( x ) ) )\r\n" +"#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) )\r\n" +"#define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrtf( ( x ) ) )\r\n" +"#define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) )\r\n" +"#define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) )\r\n" +"#define log2f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2f( ( x ) ) )\r\n" +"#define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) )\r\n" +"#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) )\r\n" +"#define round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round( ( x ) ) )\r\n" +"#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) )\r\n" +"#define roundf_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, roundf( ( x ) ) )\r\n" +"#define set_min_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_min( ( a ), ( b ) ) )\r\n" +"#define set_max_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_max( ( a ), ( b ) ) )\r\n" +"\r\n" +"/* Functions */\r\n" +"#define func_( name, x ) OP_COUNT_WRAPPER1_( FUNC_( x ), name )\r\n" +"\r\n" +"/* Logical Operators */\r\n" +"#ifndef __\r\n" +"#define __ ( BRANCH_( 1 ), 1 ) &&\r\n" +"#endif\r\n" +"\r\n" +"/* Ternary Operators (? and :) */\r\n" +"#ifndef _\r\n" +"#define _ ( BRANCH_( 1 ), 0 ) ? 0:\r\n" +"#endif\r\n" +"\r\n" +"/* Flow Control keywords */\r\n" +"#define if_ \\\r\n" +" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n" +" if\r\n" +"#define for_ OP_COUNT_WRAPPER2_( LOOP_(1)) for\r\n" +"#define while_( c ) \\\r\n" +" while \\\r\n" +" OP_COUNT_WRAPPER1_( BRANCH_( 1 ), ( c ) ) /* needs extra \"()\" if ',' encountered */\r\n" +"#define do_ \\\r\n" +" do \\\r\n" +" {\r\n" +"#define _while \\\r\n" +" BRANCH_( 1 ); \\\r\n" +" } \\\r\n" +" while\r\n" +"\r\n" +"#define goto_ \\\r\n" +" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n" +" goto\r\n" +"#define break_ \\\r\n" +" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n" +" break\r\n" +"#define continue_ \\\r\n" +" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n" +" continue\r\n" +"#define return_ \\\r\n" +" OP_COUNT_WRAPPER2_( ( wmc_flag_ = stack_tree_level_, STACK_DEPTH_FCT_RETURN ) ) \\\r\n" +" return\r\n" +"#define switch_ \\\r\n" +" OP_COUNT_WRAPPER2_( ( BRANCH_( 1 ), wmc_flag_ = 1 ) ) \\\r\n" +" switch\r\n" +"#define cost_( n ) OP_COUNT_WRAPPER2_( wmc_flag_ ? ( ADD_( n ), BRANCH_( n ), wmc_flag_ = 0 ) : 0 );\r\n" +"\r\n" +"#ifdef WMOPS\r\n" +"\r\n" +"#define ACC 2\r\n" +"#define MUL 1\r\n" +"\r\n" +"/* Counting Function (should not be called externally!) */\r\n" +"static void wops_( const char *ops )\r\n" +"{\r\n" +" char lm = 0; /* lm: Last Operation is Math */\r\n" +" static char lo = 0; /* Last Operation */\r\n" +"\r\n" +" void ( *fct )( const char *ops ) = wops_;\r\n" +"\r\n" +"st:\r\n" +" while ( *ops != '\\0' )\r\n" +" {\r\n" +" switch ( *ops++ )\r\n" +" {\r\n" +" int cnt;\r\n" +" case '-':\r\n" +" for ( cnt = 0; ops[cnt] == '>'; cnt++ )\r\n" +" ;\r\n" +" if ( cnt & 1 )\r\n" +" goto ind;\r\n" +" case '+':\r\n" +" lm = 2;\r\n" +" if ( lo & MUL )\r\n" +" {\r\n" +" MULT_( -1 );\r\n" +" MAC_( 1 );\r\n" +" break;\r\n" +" }\r\n" +" lo = ACC << 2;\r\n" +" case 'U':\r\n" +" case 'D':\r\n" +" ADD_( 1 );\r\n" +" break;\r\n" +" case '*':\r\n" +" lm = 2;\r\n" +" if ( lo & ACC )\r\n" +" {\r\n" +" ADD_( -1 );\r\n" +" MAC_( 1 );\r\n" +" break;\r\n" +" }\r\n" +" lo = MUL << 2;\r\n" +" MULT_( 1 );\r\n" +" break;\r\n" +" case '/':\r\n" +" case '%':\r\n" +" lm = 2;\r\n" +" DIV_( 1 );\r\n" +" break;\r\n" +" case '&':\r\n" +" case '|':\r\n" +" case '^':\r\n" +" lm = 2;\r\n" +" case '~':\r\n" +" LOGIC_( 1 );\r\n" +" break;\r\n" +" case '<':\r\n" +" case '>':\r\n" +" if ( *ops != ops[-1] )\r\n" +" goto error;\r\n" +" ops++;\r\n" +" case -85:\r\n" +" case -69:\r\n" +" lm = 2;\r\n" +" SHIFT_( 1 );\r\n" +" break;\r\n" +" case 'L':\r\n" +" case 'G':\r\n" +" if ( *ops == 't' )\r\n" +" goto comp;\r\n" +" case 'E':\r\n" +" case 'N':\r\n" +" if ( *ops != 'e' )\r\n" +" goto error;\r\n" +" comp:\r\n" +" ops++;\r\n" +" ADD_( 1 );\r\n" +" break;\r\n" +" case '!':\r\n" +" MISC_( 2 );\r\n" +" break;\r\n" +" case 'M':\r\n" +" MOVE_( 1 );\r\n" +" break;\r\n" +" case 'S':\r\n" +" STORE_( 1 );\r\n" +" break;\r\n" +" case 'P':\r\n" +" PTR_INIT_( 1 );\r\n" +" break;\r\n" +" case '[':\r\n" +" case ']':\r\n" +" goto st;\r\n" +" ind:\r\n" +" ops++;\r\n" +" case 'I':\r\n" +" case '.':\r\n" +" INDIRECT_( 1 );\r\n" +" break;\r\n" +" case '=':\r\n" +" if ( lm )\r\n" +" goto st;\r\n" +" case '\\0':\r\n" +" /* This Shouldn't Happen */\r\n" +" /* These are Used to Avoid: \"warning: 'name' defined but not used\" with Cygwin gcc Compiler */\r\n" +" wmc_flag_ = wmc_flag_;\r\n" +" fct( \"\" );\r\n" +" error:\r\n" +" default:\r\n" +" fprintf( stderr, \"\\r wops: Invalid Counting Operation '%s'\\n\", ops - 1 );\r\n" +" exit( -1 );\r\n" +" }\r\n" +" lm >>= 1;\r\n" +" lo >>= 2;\r\n" +" }\r\n" +"\r\n" +" return;\r\n" +"}\r\n" +"\r\n" +"#endif\r\n" +"\r\n" +"/* All Other Operations */\r\n" +"#define $( str ) OP_COUNT_WRAPPER2_( wops_( str ) )\r\n" +"\r\n" +"\r\n" +"/*-------------------------------------------------------------------*\r\n" +" * Memory counting tool\r\n" +" *-------------------------------------------------------------------*/\r\n" +"\r\n" +"/* Enhanced Const Data Size Counting (Rounding Up to the Nearest 'Integer' Size) */\r\n" +"#define rsize( item ) ( ( sizeof( item ) + sizeof( int ) - 1 ) / sizeof( int ) * sizeof( int ) )\r\n" +"\r\n" +"#ifdef _MSC_VER\r\n" +"/* Disable \"warning C4210: nonstandard extension used : function given file scope\" with Visual Studio Compiler */\r\n" +"#pragma warning( disable : 4210 )\r\n" +"#endif\r\n" +"\r\n" +"/* Const Data Size and PROM Size Wrapper Functions */\r\n" +"#define Const_Data_Size_Func( file ) Const_Data_Size_##file( void )\r\n" +"#define Get_Const_Data_Size( file, val_ptr ) \\\r\n" +" { \\\r\n" +" extern int Const_Data_Size_##file( void ); \\\r\n" +" *( val_ptr ) = Const_Data_Size_##file(); \\\r\n" +" }\r\n" +"#define PROM_Size_Func( file ) PROM_Size_##file( void )\r\n" +"#define Get_PROM_Size( file, val_ptr ) \\\r\n" +" { \\\r\n" +" int PROM_Size_##file( void ); \\\r\n" +" *( val_ptr ) = PROM_Size_##file(); \\\r\n" +" }\r\n" +"\r\n" +"/* ROM Size Lookup Table - contains information about PROM size and Const Data Size in all source files */\r\n" +"/* The print_mem() function looks for this table to print the results of Const Data usage and PROM usage */\r\n" +"typedef struct ROM_Size_Lookup_Table\r\n" +"{\r\n" +" const char file_spec[255];\r\n" +" int PROM_size;\r\n" +" int ( *Get_Const_Data_Size_Func )( void );\r\n" +"} ROM_Size_Lookup_Table;\r\n" +"\r\n" +"/* The WMC tool inserts the following declaration during the innstrumentation process in the .c file where the function print_mem() is located */\r\n" +"/* and modifies it to print_mem(Const_Data_PROM_Table) */\r\n" +"\r\n" +"/* #ifdef WMOPS\r\n" +" * ROM_Size_Lookup_Table Const_Data_PROM_Table[] =\r\n" +" * {\r\n" +" * {\"../lib_enc/rom_enc.c\", 0, NULL},\r\n" +" * {\"../lib_com/[star].c\", 0, NULL},\r\n" +" * {\"\", -1, NULL}\r\n" +" * };\r\n" +" * #endif\r\n" +" */\r\n" +"\r\n" +"/*#define MEM_ALIGN_64BITS */ /* Define this when using 64 Bits values in the code (ex: double), otherwise it will align on 32 Bits */\r\n" +"/*#define MEM_COUNT_DETAILS*/\r\n" +"\r\n" +"typedef enum\r\n" +"{\r\n" +" USE_BYTES = 0,\r\n" +" USE_16BITS = 1,\r\n" +" USE_32BITS = 2\r\n" +"} Counting_Size;\r\n" +"\r\n" +"\r\n" +"#ifdef WMOPS\r\n" +"\r\n" +"void *mem_alloc( const char *func_name, int func_lineno, size_t size, char *alloc_str );\r\n" +"void mem_free( const char *func_name, int func_lineno, void *ptr );\r\n" +"\r\n" +"#define malloc_( size ) mem_alloc( __func__, __LINE__, size, \"m:\" #size )\r\n" +"#define calloc_( n, size ) mem_alloc( __func__, __LINE__, ( n ) * ( size ), \"c:\" #n \", \" #size )\r\n" +"#define free_( ptr ) mem_free( __func__, __LINE__, ptr )\r\n" +"\r\n" +"void reset_mem( Counting_Size cnt_size );\r\n" +"void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] );\r\n" +"\r\n" +"int push_stack( const char *filename, const char *fctname );\r\n" +"int pop_stack( const char *filename, const char *fctname );\r\n" +"\r\n" +"#ifdef WMOPS_DETAIL\r\n" +"#define STACK_DEPTH_FCT_CALL ( push_wmops( __func__, \"[WMC_AUTO]\" ), push_stack( __FILE__, __func__ ) ) /* add push_wmops() in all function calls */\r\n" +"#define STACK_DEPTH_FCT_RETURN ( pop_wmops(), pop_stack( __FILE__, __func__ ) ) /* add pop_wmops() in all function returns */\r\n" +"#else\r\n" +"#define STACK_DEPTH_FCT_CALL push_stack( __FILE__, __func__ )\r\n" +"#define STACK_DEPTH_FCT_RETURN pop_stack( __FILE__, __func__ )\r\n" +"#endif\r\n" +"\r\n" +"void reset_stack( void );\r\n" +"#define func_start_ int stack_tree_level_ = STACK_DEPTH_FCT_CALL;\r\n" +"\r\n" +"#else\r\n" +"#define malloc_( n1 ) malloc( n1 )\r\n" +"#define calloc_( n1, n2 ) calloc( n1, n2 )\r\n" +"#define free_( ptr ) free( ptr )\r\n" +"#define reset_mem( cnt_size )\r\n" +"#define print_mem( Const_Data_PROM_Table )\r\n" +"\r\n" +"#define push_stack( file, fct )\r\n" +"#define pop_stack( file, fct )\r\n" +"#define reset_stack()\r\n" +"#define func_start_\r\n" +"\r\n" +"#endif\r\n" +"\r\n" +"/* Global counter variable for calculation of complexity weight */\r\n" +"typedef struct\r\n" +"{\r\n" +" unsigned int add; /* Complexity Weight of 1 */\r\n" +" unsigned int sub; /* Complexity Weight of 1 */\r\n" +" unsigned int abs_s; /* Complexity Weight of 1 */\r\n" +" unsigned int shl; /* Complexity Weight of 1 */\r\n" +" unsigned int shr; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int extract_h; /* Complexity Weight of 1 */\r\n" +" unsigned int extract_l; /* Complexity Weight of 1 */\r\n" +" unsigned int mult; /* Complexity Weight of 1 */\r\n" +" unsigned int L_mult; /* Complexity Weight of 1 */\r\n" +" unsigned int negate; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int round; /* Complexity Weight of 1 */\r\n" +" unsigned int L_mac; /* Complexity Weight of 1 */\r\n" +" unsigned int L_msu; /* Complexity Weight of 1 */\r\n" +" unsigned int L_macNs; /* Complexity Weight of 1 */\r\n" +" unsigned int L_msuNs; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L_add; /* Complexity Weight of 1 */\r\n" +" unsigned int L_sub; /* Complexity Weight of 1 */\r\n" +" unsigned int L_add_c; /* Complexity Weight of 2 */\r\n" +" unsigned int L_sub_c; /* Complexity Weight of 2 */\r\n" +" unsigned int L_negate; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L_shl; /* Complexity Weight of 1 */\r\n" +" unsigned int L_shr; /* Complexity Weight of 1 */\r\n" +" unsigned int mult_r; /* Complexity Weight of 1 */\r\n" +" unsigned int shr_r; /* Complexity Weight of 3 */\r\n" +" unsigned int mac_r; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int msu_r; /* Complexity Weight of 1 */\r\n" +" unsigned int L_deposit_h; /* Complexity Weight of 1 */\r\n" +" unsigned int L_deposit_l; /* Complexity Weight of 1 */\r\n" +" unsigned int L_shr_r; /* Complexity Weight of 3 */\r\n" +" unsigned int L_abs; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L_sat; /* Complexity Weight of 4 */\r\n" +" unsigned int norm_s; /* Complexity Weight of 1 */\r\n" +" unsigned int div_s; /* Complexity Weight of 18 */\r\n" +" unsigned int norm_l; /* Complexity Weight of 1 */\r\n" +" unsigned int move16; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int move32; /* Complexity Weight of 2 */\r\n" +" unsigned int Logic16; /* Complexity Weight of 1 */\r\n" +" unsigned int Logic32; /* Complexity Weight of 2 */\r\n" +" unsigned int Test; /* Complexity Weight of 2 */\r\n" +" unsigned int s_max; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int s_min; /* Complexity Weight of 1 */\r\n" +" unsigned int L_max; /* Complexity Weight of 1 */\r\n" +" unsigned int L_min; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_max; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_min; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int shl_r; /* Complexity Weight of 2 */\r\n" +" unsigned int L_shl_r; /* Complexity Weight of 2 */\r\n" +" unsigned int L40_shr_r; /* Complexity Weight of 2 */\r\n" +" unsigned int L40_shl_r; /* Complexity Weight of 2 */\r\n" +" unsigned int norm_L40; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L40_shl; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_shr; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_negate; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_add; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_sub; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L40_abs; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_mult; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_mac; /* Complexity Weight of 1 */\r\n" +" unsigned int mac_r40; /* Complexity Weight of 2 */\r\n" +"\r\n" +" unsigned int L40_msu; /* Complexity Weight of 1 */\r\n" +" unsigned int msu_r40; /* Complexity Weight of 2 */\r\n" +" unsigned int Mpy_32_16_ss; /* Complexity Weight of 2 */\r\n" +" unsigned int Mpy_32_32_ss; /* Complexity Weight of 2 */\r\n" +" unsigned int L_mult0; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L_mac0; /* Complexity Weight of 1 */\r\n" +" unsigned int L_msu0; /* Complexity Weight of 1 */\r\n" +" unsigned int lshl; /* Complexity Weight of 1 */\r\n" +" unsigned int lshr; /* Complexity Weight of 1 */\r\n" +" unsigned int L_lshl; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L_lshr; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_lshl; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_lshr; /* Complexity Weight of 1 */\r\n" +" unsigned int s_and; /* Complexity Weight of 1 */\r\n" +" unsigned int s_or; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int s_xor; /* Complexity Weight of 1 */\r\n" +" unsigned int L_and; /* Complexity Weight of 1 */\r\n" +" unsigned int L_or; /* Complexity Weight of 1 */\r\n" +" unsigned int L_xor; /* Complexity Weight of 1 */\r\n" +" unsigned int rotl; /* Complexity Weight of 3 */\r\n" +"\r\n" +" unsigned int rotr; /* Complexity Weight of 3 */\r\n" +" unsigned int L_rotl; /* Complexity Weight of 3 */\r\n" +" unsigned int L_rotr; /* Complexity Weight of 3 */\r\n" +" unsigned int L40_set; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_deposit_h; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L40_deposit_l; /* Complexity Weight of 1 */\r\n" +" unsigned int L40_deposit32; /* Complexity Weight of 1 */\r\n" +" unsigned int Extract40_H; /* Complexity Weight of 1 */\r\n" +" unsigned int Extract40_L; /* Complexity Weight of 1 */\r\n" +" unsigned int L_Extract40; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int L40_round; /* Complexity Weight of 1 */\r\n" +" unsigned int L_saturate40; /* Complexity Weight of 1 */\r\n" +" unsigned int round40; /* Complexity Weight of 1 */\r\n" +" unsigned int If; /* Complexity Weight of 3 */\r\n" +" unsigned int Goto; /* Complexity Weight of 2 */\r\n" +"\r\n" +" unsigned int Break; /* Complexity Weight of 2 */\r\n" +" unsigned int Switch; /* Complexity Weight of 6 */\r\n" +" unsigned int For; /* Complexity Weight of 3 */\r\n" +" unsigned int While; /* Complexity Weight of 3 */\r\n" +" unsigned int Continue; /* Complexity Weight of 2 */\r\n" +"\r\n" +" unsigned int L_mls; /* Complexity Weight of 1 */\r\n" +" unsigned int div_l; /* Complexity Weight of 32 */\r\n" +" unsigned int i_mult; /* Complexity Weight of 1 */\r\n" +"\r\n" +"/* New complex basic operators */\r\n" +"#ifdef COMPLEX_OPERATOR\r\n" +" unsigned int CL_shr; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_shl; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_add; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_sub; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_scale; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_dscale; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_msu_j; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_mac_j; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_move; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_Extract_real; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_Extract_imag; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_form; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_multr_32x16; /* Complexity Weight of 2 */\r\n" +" unsigned int CL_negate; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_conjugate; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_mul_j; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_swap_real_imag; /* Complexity Weight of 1 */\r\n" +" unsigned int C_add; /* Complexity Weight of 1 */\r\n" +" unsigned int C_sub; /* Complexity Weight of 1 */\r\n" +" unsigned int C_mul_j; /* Complexity Weight of 1 */\r\n" +" unsigned int C_multr; /* Complexity Weight of 2 */\r\n" +" unsigned int C_form; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int C_scale; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_round32_16; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_scale_32; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_dscale_32; /* Complexity Weight of 1 */\r\n" +" unsigned int CL_multr_32x32; /* Complexity Weight of 2 */\r\n" +" unsigned int C_mac_r; /* Complexity Weight of 2 */\r\n" +" unsigned int C_msu_r; /* Complexity Weight of 2 */\r\n" +" unsigned int C_Extract_real; /* Complexity Weight of 1 */\r\n" +" unsigned int C_Extract_imag; /* Complexity Weight of 1 */\r\n" +" unsigned int C_negate; /* Complexity Weight of 1 */\r\n" +" unsigned int C_conjugate; /* Complexity Weight of 1 */\r\n" +" unsigned int C_shr; /* Complexity Weight of 1 */\r\n" +" unsigned int C_shl; /* Complexity Weight of 1 */\r\n" +"\r\n" +"#endif /* #ifdef COMPLEX_OPERATOR */\r\n" +"\r\n" +"/* New 64 bit basops */\r\n" +"#ifdef ENH_64_BIT_OPERATOR\r\n" +" unsigned int move64; /* Complexity Weight of 1 */\r\n" +" unsigned int W_add_nosat; /* Complexity Weight of 1 */\r\n" +" unsigned int W_sub_nosat; /* Complexity Weight of 1 */\r\n" +" unsigned int W_shl; /* Complexity Weight of 1 */\r\n" +" unsigned int W_shr; /* Complexity Weight of 1 */\r\n" +" unsigned int W_shl_nosat; /* Complexity Weight of 1 */\r\n" +" unsigned int W_shr_nosat; /* Complexity Weight of 1 */\r\n" +" unsigned int W_mac_32_16; /* Complexity Weight of 1 */\r\n" +" unsigned int W_msu_32_16; /* Complexity Weight of 1 */\r\n" +" unsigned int W_mult_32_16; /* Complexity Weight of 1 */\r\n" +" unsigned int W_mult0_16_16; /* Complexity Weight of 1 */\r\n" +" unsigned int W_mac0_16_16; /* Complexity Weight of 1 */\r\n" +" unsigned int W_msu0_16_16; /* Complexity Weight of 1 */\r\n" +" unsigned int W_mult_16_16; /* Complexity Weight of 1 */\r\n" +" unsigned int W_mac_16_16; /* Complexity Weight of 1 */\r\n" +" unsigned int W_msu_16_16; /* Complexity Weight of 1 */\r\n" +" unsigned int W_shl_sat_l; /* Complexity Weight of 1 */\r\n" +" unsigned int W_sat_l; /* Complexity Weight of 1 */\r\n" +" unsigned int W_sat_m; /* Complexity Weight of 1 */\r\n" +" unsigned int W_deposit32_l; /* Complexity Weight of 1 */\r\n" +" unsigned int W_deposit32_h; /* Complexity Weight of 1 */\r\n" +" unsigned int W_extract_l; /* Complexity Weight of 1 */\r\n" +" unsigned int W_extract_h; /* Complexity Weight of 1 */\r\n" +" unsigned int W_round48_L; /* Complexity Weight of 1 */\r\n" +" unsigned int W_round32_s; /* Complexity Weight of 1 */\r\n" +" unsigned int W_norm; /* Complexity Weight of 1 */\r\n" +"\r\n" +" unsigned int W_add; /* Complexity Weight of 1 */\r\n" +" unsigned int W_sub; /* Complexity Weight of 1 */\r\n" +" unsigned int W_neg; /* Complexity Weight of 1 */\r\n" +" unsigned int W_abs; /* Complexity Weight of 1 */\r\n" +" unsigned int W_mult_32_32; /* Complexity Weight of 1 */\r\n" +" unsigned int W_mult0_32_32; /* Complexity Weight of 1 */\r\n" +" unsigned int W_lshl; /* Complexity Weight of 1 */\r\n" +" unsigned int W_lshr; /* Complexity Weight of 1 */\r\n" +" unsigned int W_round64_L; /* Complexity Weight of 1 */\r\n" +"\r\n" +"#endif /* #ifdef ENH_64_BIT_OPERATOR */\r\n" +"\r\n" +"#ifdef ENH_32_BIT_OPERATOR\r\n" +" unsigned int Mpy_32_16_1; /* Complexity Weight of 1 */\r\n" +" unsigned int Mpy_32_16_r; /* Complexity Weight of 1 */\r\n" +" unsigned int Mpy_32_32; /* Complexity Weight of 1 */\r\n" +" unsigned int Mpy_32_32_r; /* Complexity Weight of 1 */\r\n" +" unsigned int Madd_32_16; /* Complexity Weight of 1 */\r\n" +" unsigned int Madd_32_16_r; /* Complexity Weight of 1 */\r\n" +" unsigned int Msub_32_16; /* Complexity Weight of 1 */\r\n" +" unsigned int Msub_32_16_r; /* Complexity Weight of 1 */\r\n" +" unsigned int Madd_32_32; /* Complexity Weight of 1 */\r\n" +" unsigned int Madd_32_32_r; /* Complexity Weight of 1 */\r\n" +" unsigned int Msub_32_32; /* Complexity Weight of 1 */\r\n" +" unsigned int Msub_32_32_r; /* Complexity Weight of 1 */\r\n" +"#endif /* #ifdef ENH_32_BIT_OPERATOR */\r\n" +"\r\n" +"#ifdef ENH_U_32_BIT_OPERATOR\r\n" +" unsigned int UL_addNs; /* Complexity Weight of 1 */\r\n" +" unsigned int UL_subNs; /* Complexity Weight of 1 */\r\n" +" unsigned int UL_Mpy_32_32; /* Complexity Weight of 1 */\r\n" +" unsigned int Mpy_32_32_uu; /* Complexity Weight of 2 */\r\n" +" unsigned int Mpy_32_16_uu; /* Complexity Weight of 2 */\r\n" +" unsigned int norm_ul_float; /* Complexity Weight of 1 */\r\n" +" unsigned int UL_deposit_l; /* Complexity Weight of 1 */\r\n" +"#endif /* #ifdef ENH_U_32_BIT_OPERATOR */\r\n" +"\r\n" +"#ifdef CONTROL_CODE_OPS\r\n" +" unsigned int LT_16; /* Complexity Weight of 1 */\r\n" +" unsigned int GT_16; /* Complexity Weight of 1 */\r\n" +" unsigned int LE_16; /* Complexity Weight of 1 */\r\n" +" unsigned int GE_16; /* Complexity Weight of 1 */\r\n" +" unsigned int EQ_16; /* Complexity Weight of 1 */\r\n" +" unsigned int NE_16; /* Complexity Weight of 1 */\r\n" +" unsigned int LT_32; /* Complexity Weight of 1 */\r\n" +" unsigned int GT_32; /* Complexity Weight of 1 */\r\n" +" unsigned int LE_32; /* Complexity Weight of 1 */\r\n" +" unsigned int GE_32; /* Complexity Weight of 1 */\r\n" +" unsigned int EQ_32; /* Complexity Weight of 1 */\r\n" +" unsigned int NE_32; /* Complexity Weight of 1 */\r\n" +" unsigned int LT_64; /* Complexity Weight of 1 */\r\n" +" unsigned int GT_64; /* Complexity Weight of 1 */\r\n" +" unsigned int LE_64; /* Complexity Weight of 1 */\r\n" +" unsigned int GE_64; /* Complexity Weight of 1 */\r\n" +" unsigned int EQ_64; /* Complexity Weight of 1 */\r\n" +" unsigned int NE_64; /* Complexity Weight of 1 */\r\n" +"\r\n" +"#endif /* #ifdef CONTROL_CODE_OPS */\r\n" +"} BASIC_OP;\r\n" +"\r\n" +"#ifdef WMOPS\r\n" +"extern BASIC_OP *multiCounter;\r\n" +"extern unsigned int currCounter;\r\n" +"extern int funcId_where_last_call_to_else_occurred;\r\n" +"extern long funcid_total_wmops_at_last_call_to_else;\r\n" +"extern int call_occurred;\r\n" +"\r\n" +"long TotalWeightedOperation( unsigned int counterId );\r\n" +"long DeltaWeightedOperation( unsigned int counterId );\r\n" +"void Reset_BASOP_WMOPS_counter( unsigned int counterId );\r\n" +"\r\n" +"#endif\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : FOR\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro FOR should be used instead of the 'for' C statement.\r\n" +" * The complexity is independent of the number of loop iterations that are\r\n" +" * performed.\r\n" +" *\r\n" +" * Complexity weight : 3 (regardless of number of iterations).\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define FOR( a ) for ( a )\r\n" +"\r\n" +"#else /* ifndef WMOPS */\r\n" +"#define FOR( a ) \\\r\n" +" if ( incrFor(), 0 ) \\\r\n" +" ; \\\r\n" +" else \\\r\n" +" for ( a )\r\n" +"\r\n" +"static __inline void incrFor( void )\r\n" +"{\r\n" +" multiCounter[currCounter].For++;\r\n" +"}\r\n" +"#endif /* ifndef WMOPS */\r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : WHILE\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro WHILE should be used instead of the 'while' C statement.\r\n" +" * The complexity is proportional to the number of loop iterations that\r\n" +" * are performed.\r\n" +" *\r\n" +" * Complexity weight : 4 x 'number of loop iterations'.\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define WHILE( a ) while ( a )\r\n" +"\r\n" +"#else /* ifndef WMOPS */\r\n" +"#define WHILE( a ) while ( incrWhile(), a )\r\n" +"\r\n" +"static __inline void incrWhile( void )\r\n" +"{\r\n" +" multiCounter[currCounter].While++;\r\n" +"}\r\n" +"#endif /* ifndef WMOPS */\r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : DO\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro DO should be used instead of the 'do' C statement.\r\n" +" *\r\n" +" * Complexity weight : 0 (complexity counted by WHILE macro).\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define DO do\r\n" +"\r\n" +"#else /* ifndef WMOPS */\r\n" +"#define DO do\r\n" +"\r\n" +"#endif /* ifndef WMOPS */\r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : IF\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro IF should :\r\n" +" *\r\n" +" * - not be used when :\r\n" +" * - the 'if' structure does not have any 'else if' nor 'else' statement\r\n" +" * - and it conditions only one DSP basic operations.\r\n" +" *\r\n" +" * - be used instead of the 'if' C statement in every other case :\r\n" +" * - when there is an 'else' or 'else if' statement,\r\n" +" * - or when the 'if' conditions several DSP basic operations,\r\n" +" * - or when the 'if' conditions a function call.\r\n" +" *\r\n" +" * Complexity weight : 3\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"\r\n" +"#ifndef WMOPS\r\n" +"#define IF( a ) if ( a )\r\n" +"#else /* ifndef WMOPS */\r\n" +"#define IF( a ) if ( incrIf( __func__ ), a )\r\n" +"void incrIf( const char *func_name );\r\n" +"#endif /* ifndef WMOPS */\r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : ELSE\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro ELSE should be used instead of the 'else' C statement.\r\n" +" *\r\n" +" * Complexity weight : 3\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"\r\n" +"#ifndef WMOPS\r\n" +"#define ELSE else\r\n" +"#else /* ifndef WMOPS */\r\n" +"#define ELSE else if ( incrElse( __func__ ), 0 ); else\r\n" +"void incrElse( const char *func_name );\r\n" +"#endif /* ifndef WMOPS */\r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : SWITCH\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro SWITCH should be used instead of the 'switch' C statement.\r\n" +" *\r\n" +" * Complexity weight : 6\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define SWITCH( a ) switch ( a )\r\n" +"\r\n" +"#else /* ifndef WMOPS */\r\n" +"#define SWITCH( a ) switch ( incrSwitch(), a )\r\n" +"\r\n" +"static __inline void incrSwitch( void )\r\n" +"{\r\n" +" multiCounter[currCounter].Switch++;\r\n" +"}\r\n" +"#endif /* ifndef WMOPS */\r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : CONTINUE\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro CONTINUE should be used instead of the 'continue' C statement.\r\n" +" *\r\n" +" * Complexity weight : 2\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define CONTINUE continue\r\n" +"\r\n" +"#else /* ifndef WMOPS */\r\n" +"#define CONTINUE \\\r\n" +" if ( incrContinue(), 0 ) \\\r\n" +" ; \\\r\n" +" else \\\r\n" +" continue\r\n" +"\r\n" +"static __inline void incrContinue( void )\r\n" +"{\r\n" +" multiCounter[currCounter].Continue++;\r\n" +"}\r\n" +"#endif /* ifndef WMOPS */\r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : BREAK\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro BREAK should be used instead of the 'break' C statement.\r\n" +" *\r\n" +" * Complexity weight : 2\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define BREAK break\r\n" +"\r\n" +"#else /* ifndef WMOPS */\r\n" +"#define BREAK \\\r\n" +" if ( incrBreak(), 0 ) \\\r\n" +" ; \\\r\n" +" else \\\r\n" +" break\r\n" +"\r\n" +"static __inline void incrBreak( void )\r\n" +"{\r\n" +" multiCounter[currCounter].Break++;\r\n" +"}\r\n" +"#endif /* ifndef WMOPS */\r\n" +"\r\n" +"\r\n" +"/*****************************************************************************\r\n" +" *\r\n" +" * Function Name : GOTO\r\n" +" *\r\n" +" * Purpose :\r\n" +" *\r\n" +" * The macro GOTO should be used instead of the 'goto' C statement.\r\n" +" *\r\n" +" * Complexity weight : 2\r\n" +" *\r\n" +" *****************************************************************************/\r\n" +"#ifndef WMOPS\r\n" +"#define GOTO goto\r\n" +"\r\n" +"#else /* ifndef WMOPS */\r\n" +"#define GOTO \\\r\n" +" if ( incrGoto(), 0 ) \\\r\n" +" ; \\\r\n" +" else \\\r\n" +" goto\r\n" +"\r\n" +"static __inline void incrGoto( void )\r\n" +"{\r\n" +" multiCounter[currCounter].Goto++;\r\n" +"}\r\n" +"#endif /* ifndef WMOPS */\r\n" +"\r\n" +"\r\n" +"#ifdef CONTROL_CODE_OPS\r\n" +"\r\n" +"extern int LT_16( short var1, short var2 );\r\n" +"extern int GT_16( short var1, short var2 );\r\n" +"extern int LE_16( short var1, short var2 );\r\n" +"extern int GE_16( short var1, short var2 );\r\n" +"extern int EQ_16( short var1, short var2 );\r\n" +"extern int NE_16( short var1, short var2 );\r\n" +"\r\n" +"extern int LT_32( int L_var1, int L_var2 );\r\n" +"extern int GT_32( int L_var1, int L_var2 );\r\n" +"extern int LE_32( int L_var1, int L_var2 );\r\n" +"extern int GE_32( int L_var1, int L_var2 );\r\n" +"extern int EQ_32( int L_var1, int L_var2 );\r\n" +"extern int NE_32( int L_var1, int L_var2 );\r\n" +"\r\n" +"extern int LT_64( long long int L64_var1, long long int L64_var2 );\r\n" +"extern int GT_64( long long int L64_var1, long long int L64_var2 );\r\n" +"extern int LE_64( long long int L64_var1, long long int L64_var2 );\r\n" +"extern int GE_64( long long int L64_var1, long long int L64_var2 );\r\n" +"extern int EQ_64( long long int L64_var1, long long int L64_var2 );\r\n" +"extern int NE_64( long long int L64_var1, long long int L64_var2 );\r\n" +"\r\n" +"#endif /* #ifdef CONTROL_CODE_OPS */\r\n" +"\r\n" +"\r\n" +"#endif /* WMOPS_H */\r\n" +"\r\n" \ No newline at end of file From 4e83ce90c694d0fd8352d052c83fac3e1b15b17d Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 3 Dec 2024 15:53:55 +0100 Subject: [PATCH 64/67] version update --- src/wmc_tool/wmc_tool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wmc_tool/wmc_tool.h b/src/wmc_tool/wmc_tool.h index 891d69b..6fdcae0 100644 --- a/src/wmc_tool/wmc_tool.h +++ b/src/wmc_tool/wmc_tool.h @@ -19,7 +19,7 @@ * Switches *-------------------------------------------------------------------*/ -#define WMC_TOOL_VERSION_NO "1.6" /* Current version */ +#define WMC_TOOL_VERSION_NO "1.7" /* Current version */ /*#define DEBUG_PRINT*/ /* For debugging purposes */ /*-------------------------------------------------------------------* From b03548b6f5e52a5378ab7f466ec913b5d0fc8243 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 3 Dec 2024 15:54:39 +0100 Subject: [PATCH 65/67] update of recognized BASOP operators that should NOT be instrumented as regular functions --- src/wmc_tool/c_parser.cpp | 41 +++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/wmc_tool/c_parser.cpp b/src/wmc_tool/c_parser.cpp index 0ea8eae..591f266 100644 --- a/src/wmc_tool/c_parser.cpp +++ b/src/wmc_tool/c_parser.cpp @@ -142,17 +142,38 @@ "_round round round_f roundf " \ "set_min set_max " +/* Note: the following set of intrinsic BASOP operators has been extracted with */ +/* ctags - x --c - kinds = f move.h control.h control.c complex_basop.h complex_basop.c basop32.h basop32.c enh32.h enh32.c enh40.h enh40.c + enh64.h enh64.c enh1632.h enh1632.c enhUL32.h enhUL32.c math_32.h */ #define BASOP_FUNCTS_STRING \ - "add sub abs_s shl shr extract_h extract_l mult L_mult negate round " \ - "L_mac L_msu L_macNs L_msuNs L_add L_sub L_add_c L_sub_c L_negate L_shl L_shr " \ - "mult_r shr_r mac_r msu_r L_deposit_h L_deposit_l L_shr_r L_abs L_sat norm_s div_s " \ - "norm_l move16 move32 Logic16 Logic32 Test s_max s_min L_max L_min L40_max " \ - "L40_min shl_r L_shl_r L40_shr_r L40_shl_r norm_L40 L40_shl L40_shr L40_negate " \ - "L40_add L40_sub L40_abs L40_mult L40_mac mac_r40 L40_msu msu_r40 Mpy_32_16_ss " \ - "Mpy_32_32_ss L_mult0 L_mac0 L_msu0 lshl lshr L_lshl L_lshr L40_lshl L40_lshr " \ - "s_and s_or s_xor L_and L_or L_xor rotl rotr L_rotl L_rotr L40_set L40_deposit_h " \ - "L40_deposit_l L40_deposit32 Extract40_H Extract40_L L_Extract40 L40_round " \ - "L_saturate40 round40 If Goto Break Switch For While Continue L_mls div_l i_mult " +"Break CL_Extract_imag CL_Extract_imag CL_Extract_real CL_Extract_real CL_add CL_add CL_conjugate CL_conjugate CL_dscale CL_dscale CL_dscale_32 CL_dscale_32" \ +"CL_form CL_form CL_mac_j CL_mac_j CL_move CL_move CL_msu_j CL_msu_j CL_mul_j CL_mul_j CL_multr_32x16 CL_multr_32x16 CL_multr_32x32 CL_multr_32x32 CL_negate" \ +"CL_negate CL_round32_16 CL_round32_16 CL_scale CL_scale CL_scale_32 CL_scale_32 CL_shl CL_shl CL_shr CL_shr CL_sub CL_sub CL_swap_real_imag CL_swap_real_imag" \ +"C_Extract_imag C_Extract_imag C_Extract_real C_Extract_real C_add C_add C_conjugate C_conjugate C_form C_form C_mac_r C_mac_r C_msu_r C_msu_r C_mul_j C_mul_j" \ +"C_multr C_multr C_negate C_negate C_scale C_scale C_shl C_shl C_shr C_shr C_sub C_sub Continue EQ_16 EQ_32 EQ_64 Extract40_H Extract40_L For GE_16 GE_16 GE_32" \ +"GE_32 GE_64 GE_64 GT_16 GT_16 GT_32 GT_32 GT_64 GT_64 Goto If L40_abs L40_abs L40_add L40_add L40_add_o L40_deposit32 L40_deposit32 L40_deposit_h L40_deposit_h" \ +"L40_deposit_l L40_deposit_l L40_lshl L40_lshl L40_lshr L40_lshr L40_mac L40_mac L40_max L40_max L40_min L40_min L40_msu L40_msu L40_mult L40_mult L40_negate" \ +"L40_negate L40_round L40_round L40_set L40_set L40_shl L40_shl L40_shl_o L40_shl_r L40_shl_r L40_shr L40_shr L40_shr_r L40_shr_r L40_sub L40_sub L40_sub_o" \ +"LE_16 LE_16 LE_32 LE_32 LE_64 LE_64 LT_16 LT_16 LT_32 LT_32 LT_64 LT_64 L_Extract40 L_abs L_abs L_add L_add L_add_c L_add_c L_add_co L_add_o L_add_sat L_and" \ +"L_and L_deposit_h L_deposit_h L_deposit_l L_deposit_l L_lshl L_lshl L_lshr L_lshr L_mac L_mac L_mac0 L_mac0 L_mac0_o L_mac0_sat L_macNs L_macNs L_macNs_co" \ +"L_macNs_sat L_mac_o L_mac_sat L_max L_max L_min L_min L_mls L_mls L_mls_o L_mls_sat L_msu L_msu L_msu0 L_msu0 L_msu0_o L_msu0_sat L_msuNs L_msuNs L_msuNs_co" \ +"L_msuNs_sat L_msu_o L_msu_sat L_mult L_mult L_mult0 L_mult0 L_mult_o L_mult_sat L_negate L_negate L_or L_or L_rotl L_rotl L_rotr L_rotr L_sat L_sat L_sat_co" \ +"L_saturate40 L_saturate40 L_saturate40_o L_shl L_shl L_shl_o L_shl_r L_shl_r L_shl_sat L_shr L_shr L_shr_o L_shr_r L_shr_r L_shr_r_sat L_shr_ro L_shr_sat L_sub" \ +"L_sub L_sub_c L_sub_c L_sub_co L_sub_o L_sub_sat L_xor L_xor Logic16 Logic32 Madd_32_16 Madd_32_16 Madd_32_16_r Madd_32_16_r Madd_32_32 Madd_32_32 Madd_32_32_r" \ +"Madd_32_32_r Mpy_32_16_1 Mpy_32_16_1 Mpy_32_16_r Mpy_32_16_r Mpy_32_16_ss Mpy_32_16_ss Mpy_32_16_uu Mpy_32_16_uu Mpy_32_32 Mpy_32_32 Mpy_32_32_r Mpy_32_32_r" \ +"Mpy_32_32_ss Mpy_32_32_ss Mpy_32_32_uu Mpy_32_32_uu Msub_32_16 Msub_32_16 Msub_32_16_r Msub_32_16_r Msub_32_32 Msub_32_32 Msub_32_32_r Msub_32_32_r NE_16 NE_16" \ +"NE_32 NE_32 NE_64 NE_64 Switch Test UL_Mpy_32_32 UL_Mpy_32_32 UL_addNs UL_addNs UL_addNsD UL_and UL_deposit_h UL_deposit_l UL_deposit_l UL_lshl UL_lshr UL_or" \ +"UL_subNs UL_subNs UL_subNsD UL_xor W_abs W_abs W_abs_o W_add W_add W_add_nosat W_add_nosat W_add_o W_deposit32_h W_deposit32_h W_deposit32_l W_deposit32_l" \ +"W_extract_h W_extract_h W_extract_l W_extract_l W_lshl W_lshl W_lshr W_lshr W_mac0_16_16 W_mac0_16_16 W_mac_16_16 W_mac_16_16 W_mac_32_16 W_mac_32_16" \ +"W_mac_32_32 W_msu0_16_16 W_msu0_16_16 W_msu_16_16 W_msu_16_16 W_msu_32_16 W_msu_32_16 W_mult0_16_16 W_mult0_16_16 W_mult0_32_32 W_mult0_32_32 W_mult_16_16" \ +"W_mult_16_16 W_mult_32_16 W_mult_32_16 W_mult_32_32 W_mult_32_32 W_mult_32_32_o W_neg W_neg W_neg_o W_norm W_norm W_round32_s W_round32_s W_round32_s_o" \ +"W_round48_L W_round48_L W_round48_L_o W_round64_L W_round64_L W_sat_l W_sat_l W_sat_m W_sat_m W_shl W_shl W_shl_nosat W_shl_nosat W_shl_o W_shl_sat_l" \ +"W_shl_sat_l W_shr W_shr W_shr_nosat W_shr_nosat W_sub W_sub W_sub_nosat W_sub_nosat W_sub_o While abs_s abs_s add add add_o add_sat div_l div_l div_s div_s" \ +"extract_h extract_h extract_l extract_l get_carry i_mult i_mult i_mult_o i_mult_sat logic16 logic32 lshl lshr mac_r mac_r40 mac_r_sat mac_ro move16 move16" \ +"move32 move32 move64 move64 msu_r msu_r msu_r40 msu_r40 msu_r_sat msu_ro mult mult mult_o mult_r mult_r mult_r_sat mult_ro mult_sat negate negate norm_L40" \ +"norm_L40 norm_l norm_l norm_s norm_s norm_ul_float rotl rotl rotr rotr round round40 round40 round_fx round_fx_o round_fx_sat s_and s_and s_max s_max s_min" \ +"s_min s_or s_or s_xor s_xor saturate saturate_o set_carry set_overflow shl shl shl_o shl_r shl_r shl_ro shl_sat shr shr shr_o shr_r shr_r shr_r_sat shr_ro" \ +"shr_sat sub sub sub_o sub_sat test u_extract_h u_extract_l unset_carry unset_overflow" #define WMOPS_LIB_INCLUDE_STRING \ "wmc_auto.h" From 55d13348739cf97eba951e0fef069550cf0b7053 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Tue, 3 Dec 2024 16:34:18 +0100 Subject: [PATCH 66/67] udpate of reference files for ctest --- src/wmc_tool/test_data/ref/main2.c | 2 +- src/wmc_tool/test_data/ref/test_basop32.c | 2 +- src/wmc_tool/test_data/ref/wmc_auto.c | 614 ++- src/wmc_tool/test_data/ref/wmc_auto.h | 1076 ++--- src/wmc_tool/wmc_auto_c.txt | 5058 ++++++++++----------- src/wmc_tool/wmc_auto_h.txt | 2464 +++++----- 6 files changed, 4678 insertions(+), 4538 deletions(-) diff --git a/src/wmc_tool/test_data/ref/main2.c b/src/wmc_tool/test_data/ref/main2.c index e77f327..1a8adfa 100644 --- a/src/wmc_tool/test_data/ref/main2.c +++ b/src/wmc_tool/test_data/ref/main2.c @@ -20,7 +20,7 @@ /*AddedByWMC_Tool*/} /*AddedByWMC_Tool*/ROM_Size_Lookup_Table Const_Data_PROM_Table[] = /*AddedByWMC_Tool*/{ -/*AddedByWMC_Tool*/ { "out/test*.c", 291, Get_Const_Data_Size_out_test_c }, +/*AddedByWMC_Tool*/ { "out/test*.c", 292, Get_Const_Data_Size_out_test_c }, /*AddedByWMC_Tool*/ { "", -1, NULL } /*AddedByWMC_Tool*/}; /*AddedByWMC_Tool*/#endif diff --git a/src/wmc_tool/test_data/ref/test_basop32.c b/src/wmc_tool/test_data/ref/test_basop32.c index 9fcdf1e..fd6f726 100644 --- a/src/wmc_tool/test_data/ref/test_basop32.c +++ b/src/wmc_tool/test_data/ref/test_basop32.c @@ -2430,4 +2430,4 @@ Word32 L_msu0 (Word32 L_var3, Word16 var1, Word16 var2) { #undef WMC_TOOL_SKIP /* end of file */ -/*AddedByWMC_Tool*/ int PROM_Size_Func( test_basop32 ) { return 157; } +/*AddedByWMC_Tool*/ int PROM_Size_Func( test_basop32 ) { return 158; } diff --git a/src/wmc_tool/test_data/ref/wmc_auto.c b/src/wmc_tool/test_data/ref/wmc_auto.c index 7dfcf8b..e9b7f86 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.c +++ b/src/wmc_tool/test_data/ref/wmc_auto.c @@ -1,5 +1,5 @@ /* - * (C) 2022 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2024 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file @@ -16,7 +16,9 @@ #include #include #include +#include #include +#include #ifndef _MSC_VER #include @@ -25,27 +27,31 @@ #include #endif -#include "options.h" #include "wmc_auto.h" #define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */ -#ifdef WMOPS +#ifndef WMOPS +int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */ +#endif +#ifdef WMOPS /*-------------------------------------------------------------------* * Complexity counting tool *--------------------------------------------------------------------*/ -#define MAX_FUNCTION_NAME_LENGTH 50 /* Maximum length of the function name */ -#define MAX_PARAMS_LENGTH 50 /* Maximum length of the function parameter string */ -#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> mightb be increased during runtime, if needed */ + +#define MAX_FUNCTION_NAME_LENGTH 200 /* Maximum length of the function name */ +#define MAX_PARAMS_LENGTH 200 /* Maximum length of the function parameter string */ +#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> might be increased during runtime, if needed */ #define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */ #define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */ #define DOUBLE_MAX 0x80000000 #define FAC ( FRAMES_PER_SECOND / 1e6 ) +#define FRAMES_PER_SECOND 50.0 #define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */ -typedef struct +typedef struct { char label[MAX_FUNCTION_NAME_LENGTH]; long call_number; @@ -57,7 +63,7 @@ typedef struct double max_selfcnt; double min_selfcnt; double tot_selfcnt; - double start_cnt; + double start_cnt; /* The following take into account the decendants */ double current_cnt; double max_cnt; double min_cnt; @@ -71,7 +77,6 @@ typedef struct } wmops_record; double ops_cnt; -double prom_cnt; double inst_cnt[NUM_INST]; static wmops_record *wmops = NULL; @@ -86,10 +91,75 @@ static long fnum_cnt_wc; static int *wmops_caller_stack = NULL, wmops_caller_stack_index, max_wmops_caller_stack_index = 0; static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0; +static BASIC_OP op_weight = { + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 2, 2, 1, + 1, 1, 1, 2, 1, + + 1, 1, 1, 2, 1, + 1, 1, 18, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 2, 2, 2, 2, 1, + + 1, 1, 1, 1, 1, + 1, 1, 1, 2, + 1, 2, 2, 2, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 3, + 3, 3, 3, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 3, 2, + 2, 6, 3, 3, 2, + + 1, 32, 1 + +/* New complex basops */ +#ifdef COMPLEX_OPERATOR + , + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1 + + , + 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1 + +#endif /* #ifdef COMPLEX_OPERATOR */ + +#ifdef ENH_64_BIT_OPERATOR + /* Weights of new 64 bit basops */ + , + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +#endif /* #ifdef ENH_64_BIT_OPERATOR */ + +#ifdef ENH_32_BIT_OPERATOR + , + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +#endif /* #ifdef ENH_32_BIT_OPERATOR */ + +#ifdef ENH_U_32_BIT_OPERATOR + , + 1, 1, 1, 2, 2, 1, 1 +#endif /* #ifdef ENH_U_32_BIT_OPERATOR */ + +#ifdef CONTROL_CODE_OPS + , + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +#endif /* #ifdef CONTROL_CODE_OPS */ +}; + +BASIC_OP *multiCounter = NULL; +unsigned int currCounter = 0; +int funcId_where_last_call_to_else_occurred; +long funcid_total_wmops_at_last_call_to_else; +int call_occurred = 1; +char func_name_where_last_call_to_else_occurred[MAX_FUNCTION_NAME_LENGTH + 1]; + void reset_wmops( void ) { int i, j; - unsigned int *ptr; num_wmops_records = 0; max_num_wmops_records = MAX_NUM_RECORDS; @@ -101,10 +171,10 @@ void reset_wmops( void ) start_cnt = 0.0; ops_cnt = 0.0; - /* allocate the list of wmops records */ + /* allocate the list of WMOPS records */ if ( wmops == NULL ) { - wmops = (wmops_record *)malloc( max_num_wmops_records * sizeof( wmops_record ) ); + wmops = (wmops_record *) malloc( max_num_wmops_records * sizeof( wmops_record ) ); } if ( wmops == NULL ) @@ -113,7 +183,7 @@ void reset_wmops( void ) exit( -1 ); } - /* allocate the BASOP WMOPS counter */ + /* allocate the list of BASOP WMOPS records */ if ( multiCounter == NULL ) { multiCounter = (BASIC_OP *) malloc( max_num_wmops_records * sizeof( BASIC_OP ) ); @@ -125,8 +195,8 @@ void reset_wmops( void ) exit( -1 ); } - /* initilize the list of wmops records */ - /* initilize the BASOP WMOPS counters */ + /* initilize the list of WMOPS records */ + /* initilize BASOP operation counters */ for ( i = 0; i < max_num_wmops_records; i++ ) { strcpy( &wmops[i].label[0], "\0" ); @@ -153,13 +223,8 @@ void reset_wmops( void ) wmops[i].wc_call_number = -1; #endif - /* clear all BASOP operation counters */ - ptr = (unsigned int*) &multiCounter[i]; - for ( j = 0; j < (int) ( sizeof(BASIC_OP ) / sizeof( unsigned int ) ); j++ ) - { - *ptr++ = 0; - } - wmops[i].LastWOper = 0; + /* Reset BASOP operation counter */ + Reset_BASOP_WMOPS_counter( i ); } /* allocate the list of wmops callers to track the sequence of function calls */ @@ -181,47 +246,88 @@ void reset_wmops( void ) wmops_caller_stack[i] = -1; } - /* initialize auxiliary BASOP WMOPS variables */ + /* initialize auxiliary BASOP counter variables */ + currCounter = 0; /* Note: currCounter cannot be set to -1 because it's defined as unsigned int ! */ call_occurred = 1; - funcId_where_last_call_to_else_occurred = INT_MAX; + funcId_where_last_call_to_else_occurred = -100; return; } - -void push_wmops( const char *label ) +void push_wmops_fct( const char *label, ... ) { int new_flag; - int i, j; + int i, j, index_record; + long tot; + va_list arg; + char func_name[MAX_FUNCTION_NAME_LENGTH] = ""; + + /* concatenate all function name labels into a single string */ + va_start( arg, label ); + while ( label ) + { + strcat( func_name, label ); + label = va_arg( arg, const char * ); + } + va_end( arg ); /* Check, if this is a new function label */ new_flag = 1; for ( i = 0; i < num_wmops_records; i++ ) { - if ( strcmp( wmops[i].label, label ) == 0 ) + if ( strcmp( wmops[i].label, func_name ) == 0 ) { new_flag = 0; break; } } + index_record = i; - /* Create a new record in the list */ + /* Create a new WMOPS record in the list */ if ( new_flag ) { if ( num_wmops_records >= max_num_wmops_records ) { - /* There is no room for a new wmops record -> reallocate the list */ + /* There is no room for a new WMOPS record -> reallocate the list */ max_num_wmops_records += MAX_NUM_RECORDS_REALLOC_STEP; wmops = realloc( wmops, max_num_wmops_records * sizeof( wmops_record ) ); multiCounter = realloc( multiCounter, max_num_wmops_records * sizeof( BASIC_OP ) ); } - strcpy( wmops[i].label, label ); + /* initilize the new WMOPS record */ + strcpy( &wmops[index_record].label[0], "\0" ); + wmops[index_record].call_number = 0; + wmops[index_record].update_cnt = 0; + for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ ) + { + wmops[index_record].call_tree[j] = -1; + } + wmops[index_record].start_selfcnt = 0.0; + wmops[index_record].current_selfcnt = 0.0; + wmops[index_record].max_selfcnt = 0.0; + wmops[index_record].min_selfcnt = DOUBLE_MAX; + wmops[index_record].tot_selfcnt = 0.0; + wmops[index_record].start_cnt = 0.0; + wmops[index_record].current_cnt = 0.0; + wmops[index_record].max_cnt = 0.0; + wmops[index_record].min_cnt = DOUBLE_MAX; + wmops[index_record].tot_cnt = 0.0; +#ifdef WMOPS_WC_FRAME_ANALYSIS + wmops[index_record].wc_cnt = 0.0; + wmops[index_record].wc_selfcnt = 0.0; + wmops[index_record].current_call_number = 0; + wmops[index_record].wc_call_number = -1; +#endif + + /* Reset BASOP operation counter */ + Reset_BASOP_WMOPS_counter( index_record ); + + strcpy( wmops[index_record].label, func_name ); num_wmops_records++; } - /* Push the current context info to the new record */ + /* Update the WMOPS context info of the old record before switching to the new one */ if ( current_record >= 0 ) { if ( wmops_caller_stack_index >= max_wmops_caller_stack_index ) @@ -232,40 +338,49 @@ void push_wmops( const char *label ) } wmops_caller_stack[wmops_caller_stack_index++] = current_record; - /* accumulate op counts */ + /* add the BASOP complexity to the counter and update the old WMOPS counter */ + tot = DeltaWeightedOperation( current_record ); + ops_cnt += tot; wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; /* update call tree */ for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ ) { - if ( wmops[i].call_tree[j] == current_record ) + if ( wmops[index_record].call_tree[j] == current_record ) { break; } - else if ( wmops[i].call_tree[j] == -1 ) + else if ( wmops[index_record].call_tree[j] == -1 ) { - wmops[i].call_tree[j] = current_record; + wmops[index_record].call_tree[j] = current_record; break; } } } - /* update the current context info */ - current_record = i; - wmops[current_record].start_selfcnt = ops_cnt; - wmops[current_record].start_cnt = ops_cnt; - wmops[current_record].call_number++; + /* Need to reset the BASOP operation counter of the 0th record in every push_wmops() */ + /* because currCounter can never be -1 */ + if ( current_record == -1 && index_record == 0 ) + { + wmops[index_record].LastWOper = TotalWeightedOperation( index_record ); + } + + /* switch to the new record */ + current_record = index_record; + wmops[index_record].start_selfcnt = ops_cnt; + wmops[index_record].start_cnt = ops_cnt; + wmops[index_record].call_number++; #ifdef WMOPS_WC_FRAME_ANALYSIS - wmops[current_record].current_call_number++; + wmops[index_record].current_call_number++; #endif - /* set the ID of BASOP functions counters */ - Set_BASOP_WMOPS_counter( current_record ); + /* set the ID of the current BASOP operations counter */ + currCounter = index_record; + call_occurred = 1; return; } - void pop_wmops( void ) { long tot; @@ -278,10 +393,10 @@ void pop_wmops( void ) } /* add the BASOP complexity to the counter */ - tot = DeltaWeightedOperation(); + tot = DeltaWeightedOperation( currCounter ); ops_cnt += tot; - /* update count of current record */ + /* update count of current record */ wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt; wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt; @@ -290,15 +405,22 @@ void pop_wmops( void ) { current_record = wmops_caller_stack[--wmops_caller_stack_index]; wmops[current_record].start_selfcnt = ops_cnt; - - /* set the ID of the previous BASOP counter */ - Set_BASOP_WMOPS_counter( current_record ); } else { current_record = -1; } + /* set the ID of the previous BASOP operations counter */ + if ( current_record == -1 ) + { + currCounter = 0; /* Note: currCounter cannot be set to -1 because it's defined as unsigned int ! */ + } + else + { + currCounter = current_record; + } + call_occurred = 1; return; } @@ -391,9 +513,9 @@ void update_wmops( void ) wmops[i].current_call_number = 0; #endif - /* update the WC of all BASOP counters */ - Set_BASOP_WMOPS_counter( i ); - Reset_BASOP_WMOPS_counter(); + /* reset the BASOP operations counter */ + call_occurred = 1; + Reset_BASOP_WMOPS_counter( i ); } current_cnt = ops_cnt - start_cnt; @@ -427,15 +549,14 @@ void update_wmops( void ) return; } - void print_wmops( void ) { int i, label_len, max_label_len; char *sfmts = "%*s %8s %8s %7s %7s\n"; char *dfmts = "%*s %8.2f %8.3f %7.3f %7.3f\n"; - char *sfmt = "%*s %8s %8s %7s %7s %7s %7s %7s\n"; - char *dfmt = "%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n"; + char *sfmt = "%*s %8s %8s %7s %7s %7s %7s %7s\n"; + char *dfmt = "%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n"; #ifdef WMOPS_WC_FRAME_ANALYSIS int j; @@ -456,7 +577,7 @@ void print_wmops( void ) max_label_len += 4; fprintf( stdout, "\n\n --- Complexity analysis [WMOPS] --- \n\n" ); - + fprintf( stdout, "%*s %33s %23s\n", max_label_len, "", "|------ SELF ------|", "|--- CUMULATIVE ---|" ); fprintf( stdout, sfmt, max_label_len, " routine", " calls", " min ", " max ", " avg ", " min ", " max ", " avg " ); fprintf( stdout, sfmt, max_label_len, "---------------", "------", "------", "------", "------", "------", "------", "------" ); @@ -478,7 +599,7 @@ void print_wmops( void ) #ifdef WMOPS_WC_FRAME_ANALYSIS fprintf( stdout, "\nComplexity analysis for the worst-case frame %ld:\n\n", fnum_cnt_wc ); - fprintf( stdout, "%*s %8s %10s %12s\n", max_label_len, " routine", " calls", " SELF", " CUMULATIVE" ); + fprintf( stdout, "%*s %8s %10s %12s\n", max_label_len, " routine", " calls", " SELF", " CUMULATIVE" ); fprintf( stdout, "%*s %8s %10s %10s\n", max_label_len, "---------------", "------", "------", "----------" ); for ( i = 0; i < num_wmops_records; i++ ) @@ -512,7 +633,7 @@ void print_wmops( void ) fprintf( stdout, "\n\n" ); - fprintf( stdout, "\nInstruction type analysis for the worst-case frame %ld:\n\n", fnum_cnt_wc ); + fprintf( stdout, "\nInstruction type analysis for the worst-case frame %ld:\n\n", fnum_cnt_wc ); for ( i = 0; i < NUM_INST; i++ ) { switch ( (enum instructions) i ) @@ -604,7 +725,6 @@ void print_wmops( void ) return; } - /*-------------------------------------------------------------------* * Memory counting tool measuring RAM usage (stack and heap) * @@ -627,6 +747,7 @@ void print_wmops( void ) * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free(). *--------------------------------------------------------------------*/ + /* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */ #ifdef MEM_ALIGN_64BITS @@ -636,12 +757,14 @@ void print_wmops( void ) #endif #define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) ) -#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) ) #define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */ #define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */ -#define OOB_START 0x1 /* Flag indicating out-of-bounds access before memory block */ -#define OOB_END 0x2 /* Flag indicating out-of-bounds access after memory block */ +#define OOB_START 0x1 /* int indicating out-of-bounds access before memory block */ +#define OOB_END 0x2 /* int indicating out-of-bounds access after memory block */ + +#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) ) +#define IS_CALLOC( str ) ( str[0] == 'c' ) #ifdef MEM_COUNT_DETAILS const char *csv_filename = "mem_analysis.csv"; @@ -654,7 +777,7 @@ typedef struct int16_t *stack_ptr; } caller_info; -static caller_info *stack_callers[2] = {NULL, NULL}; +static caller_info *stack_callers[2] = { NULL, NULL }; static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */ static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */ @@ -663,7 +786,6 @@ static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case static int current_calls = 0, max_num_calls = MAX_NUM_RECORDS; static char location_max_stack[256] = "undefined"; -/* Heap-related variables */ typedef struct { char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */ @@ -889,7 +1011,7 @@ int push_stack( const char *filename, const char *fctname ) /* save the worst-case frame number */ /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */ - wc_stack_frame = update_cnt; + wc_stack_frame = update_cnt; strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 ); location_max_stack[sizeof( location_max_stack ) - 1] = '\0'; @@ -904,7 +1026,7 @@ int push_stack( const char *filename, const char *fctname ) } /* Check, if This is the New Worst-Case RAM (stack + heap) */ - current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); + current_stack_size = ( int32_t )( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); if ( current_stack_size < 0 ) { @@ -1097,7 +1219,7 @@ void *mem_alloc( #ifdef MEM_COUNT_DETAILS /* Export heap memory allocation record to the .csv file */ - fprintf( fid_csv_filename, "A,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); + fprintf( fid_csv_filename, "A,%ld,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); #endif if ( ptr_record->frame_allocated != -1 ) @@ -1112,7 +1234,7 @@ void *mem_alloc( current_heap_size += ptr_record->block_size; /* Check, if this is the new Worst-Case RAM (stack + heap) */ - current_stack_size = (int32_t) ( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); + current_stack_size = ( int32_t )( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) ); if ( current_stack_size + current_heap_size > wc_ram_size ) { wc_ram_size = current_stack_size + current_heap_size; @@ -1395,8 +1517,8 @@ allocator_record *get_mem_record( unsigned long *hash, const char *func_name, in /*-------------------------------------------------------------------* * mem_free() * - * This function de-allocatesd the memory block and frees the mphysical memory with free(). - * It also updates actual and average usage of the memory block. + * This function de-allocates memory blocks and frees physical memory with free(). + * It also updates the actual and average usage of memory blocks. * * Note: The record is not removed from the list and may be reused later on in mem_alloc()! *--------------------------------------------------------------------*/ @@ -1437,7 +1559,7 @@ void mem_free( const char *func_name, int func_lineno, void *ptr ) #ifdef MEM_COUNT_DETAILS /* Export heap memory de-allocation record to the .csv file */ - fprintf( fid_csv_filename, "D,%d,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); + fprintf( fid_csv_filename, "D,%ld,%s,%d,%d\n", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size ); #endif /* De-Allocate Memory Block */ @@ -1697,7 +1819,7 @@ static void mem_count_summary( void ) allocator_record *ptr_record, *ptr; /* Prepare format string */ - sprintf( format_str, "%%-%ds %%5s %%6s %%-%ds %%20s %%6s ", MAX_FUNCTION_NAME_LENGTH, MAX_PARAMS_LENGTH ); + sprintf( format_str, "%%-%d.%ds %%5.5s %%6.6s %%-%d.%ds %%20.20s %%6.6s ", 50, 50, 50, 50 ); if ( n_items_wc_intra_frame_heap > 0 ) { @@ -2064,109 +2186,343 @@ void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] ) #endif /* WMOPS */ -#ifndef WMOPS -int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */ +#ifdef CONTROL_CODE_OPS + +int LT_16( short var1, short var2 ) +{ + int F_ret = 0; + + if ( var1 < var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].LT_16++; #endif + return F_ret; +} + +int GT_16( short var1, short var2 ) +{ + int F_ret = 0; + if ( var1 > var2 ) + { + F_ret = 1; + } #ifdef WMOPS -/* Global counter for the calculation of BASOP complexity */ -BASIC_OP *multiCounter = NULL; -int currCounter = 0; -int funcId_where_last_call_to_else_occurred; -long funcid_total_wmops_at_last_call_to_else; -int call_occurred = 1; + multiCounter[currCounter].GT_16++; +#endif + return F_ret; +} -BASIC_OP op_weight = { - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 2, 2, 1, - 1, 1, 1, 3, 1, +int LE_16( short var1, short var2 ) +{ + int F_ret = 0; - 1, 1, 1, 3, 1, - 4, 1, 18, 1, 1, - 2, 1, 2, 2, 1, - 1, 1, 1, 1, 1, - 3, 3, 3, 3, 1, + if ( var1 <= var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].LE_16++; +#endif + return F_ret; +} - 1, 1, 1, 1, 1, - 1, 1, 1, 2, - 1, 2, 2, 4, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, +int GE_16( short var1, short var2 ) +{ + int F_ret = 0; - 1, 1, 1, 1, 3, - 3, 3, 3, 3, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 4, 4, - 4, 8, 3, 4, 4, + if ( var1 >= var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].GE_16++; +#endif + return F_ret; +} - 5, 32, 3 -}; +int EQ_16( short var1, short var2 ) +{ + int F_ret = 0; + + if ( var1 == var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].EQ_16++; +#endif + return F_ret; +} -/* Set the counter group to use, default is zero */ -void Set_BASOP_WMOPS_counter( int counterId ) +int NE_16( short var1, short var2 ) { - if ( ( counterId > num_wmops_records ) || ( counterId < 0 ) ) + int F_ret = 0; + + if ( var1 != var2 ) { - currCounter = 0; - return; + F_ret = 1; } - currCounter = counterId; - call_occurred = 1; +#ifdef WMOPS + multiCounter[currCounter].NE_16++; +#endif + return F_ret; +} + +int LT_32( int L_var1, int L_var2 ) +{ + int F_ret = 0; + + if ( L_var1 < L_var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].LT_32++; +#endif + return F_ret; +} + +int GT_32( int L_var1, int L_var2 ) +{ + int F_ret = 0; + + if ( L_var1 > L_var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].GT_32++; +#endif + return F_ret; +} + +int LE_32( int L_var1, int L_var2 ) +{ + int F_ret = 0; + + if ( L_var1 <= L_var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].LE_32++; +#endif + return F_ret; +} + +int GE_32( int L_var1, int L_var2 ) +{ + int F_ret = 0; + + if ( L_var1 >= L_var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].GE_32++; +#endif + return F_ret; +} + +int EQ_32( int L_var1, int L_var2 ) +{ + int F_ret = 0; + + if ( L_var1 == L_var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].EQ_32++; +#endif + return F_ret; +} + +int NE_32( int L_var1, int L_var2 ) +{ + int F_ret = 0; + + if ( L_var1 != L_var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].NE_32++; +#endif + return F_ret; +} + +int LT_64( long long int L64_var1, long long int L64_var2 ) +{ + int F_ret = 0; + + if ( L64_var1 < L64_var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].LT_64++; +#endif + return F_ret; +} + +int GT_64( long long int L64_var1, long long int L64_var2 ) +{ + int F_ret = 0; + + if ( L64_var1 > L64_var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].GT_64++; +#endif + return F_ret; +} + +int LE_64( long long int L64_var1, long long int L64_var2 ) +{ + int F_ret = 0; + + if ( L64_var1 <= L64_var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].LE_64++; +#endif + return F_ret; +} +int GE_64( long long int L64_var1, long long int L64_var2 ) +{ + int F_ret = 0; + + if ( L64_var1 >= L64_var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].GE_64++; +#endif + return F_ret; +} + +int EQ_64( long long int L64_var1, long long int L64_var2 ) +{ + int F_ret = 0; + + if ( L64_var1 == L64_var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].EQ_64++; +#endif + return F_ret; +} +int NE_64( long long int L64_var1, long long int L64_var2 ) +{ + int F_ret = 0; + + if ( L64_var1 != L64_var2 ) + { + F_ret = 1; + } +#ifdef WMOPS + multiCounter[currCounter].NE_64++; +#endif + return F_ret; +} + +#endif /* #ifdef CONTROL_CODE_OPS */ + +#ifdef WMOPS + +void incrIf( const char *func_name ) +{ + /* Technical note: If the "IF" operator comes just after an "ELSE", its counter must not be incremented */ + /* The following auxiliary variables are used to check if the "IF" operator doesn't immediately follow an "ELSE" operator */ + if ( ( (int) currCounter != funcId_where_last_call_to_else_occurred ) || ( strncmp( func_name, func_name_where_last_call_to_else_occurred, MAX_FUNCTION_NAME_LENGTH ) != 0 ) || ( TotalWeightedOperation( currCounter) != funcid_total_wmops_at_last_call_to_else ) || ( call_occurred == 1 ) ) + multiCounter[currCounter].If++; + + call_occurred = 0; + funcId_where_last_call_to_else_occurred = -100; } -extern int32_t frame; +void incrElse( const char *func_name ) +{ + multiCounter[currCounter].If++; + + /* Save the BASOP counter Id in the last function in which ELSE() has been called */ + funcId_where_last_call_to_else_occurred = currCounter; + + /* Save the BASOP comeplxity in the last call of the ELSE() statement */ + funcid_total_wmops_at_last_call_to_else = TotalWeightedOperation( currCounter ); -long TotalWeightedOperation() + /* Save the function name in the last call of the ELSE() statement */ + strncpy( func_name_where_last_call_to_else_occurred, func_name, MAX_FUNCTION_NAME_LENGTH ); + func_name_where_last_call_to_else_occurred[MAX_FUNCTION_NAME_LENGTH] = '\0'; + + /* Set call_occurred to 0 to prevent counting of complexity of the next "immediate" IF statement */ + call_occurred = 0; +} + +long TotalWeightedOperation( unsigned int CounterId ) { int i; unsigned int *ptr, *ptr2; - long tot; + long tot; tot = 0; - ptr = (unsigned int *) &multiCounter[currCounter]; + ptr = (unsigned int *) &multiCounter[CounterId]; ptr2 = (unsigned int *) &op_weight; - for ( i = 0; i < ( int )( sizeof( multiCounter[currCounter] ) / sizeof( unsigned int ) ); i++ ) + for ( i = 0; i < (int) ( sizeof( multiCounter[CounterId] ) / sizeof( unsigned int ) ); i++ ) { + if ( *ptr == UINT_MAX ) + { + printf( "\nError in BASOP complexity counters: multiCounter[%d][%d] = %d !!!\n", CounterId, i, *ptr ); + exit( -1 ); + } + tot += ( ( *ptr++ ) * ( *ptr2++ ) ); } return ( tot ); } -long DeltaWeightedOperation( void ) +long DeltaWeightedOperation( unsigned int CounterId ) { long NewWOper, delta; - NewWOper = TotalWeightedOperation(); + NewWOper = TotalWeightedOperation( CounterId ); - delta = NewWOper - wmops[currCounter].LastWOper; - wmops[currCounter].LastWOper = NewWOper; + delta = NewWOper - wmops[CounterId].LastWOper; + wmops[CounterId].LastWOper = NewWOper; return ( delta ); } -/* Resets the current BASOP WMOPS counter */ -void Reset_BASOP_WMOPS_counter( void ) +/* Resets BASOP operation counter */ +void Reset_BASOP_WMOPS_counter( unsigned int counterId ) { int i; long *ptr; - /* clear the current BASOP operation counter before new frame begins */ - ptr = (long *) &multiCounter[currCounter]; - for ( i = 0; i < (int) ( sizeof( multiCounter[currCounter] ) / sizeof( long ) ); i++ ) + /* reset the current BASOP operation counter */ + ptr = (long *) &multiCounter[counterId]; + for ( i = 0; i < (int) ( sizeof( multiCounter[counterId] ) / sizeof( long ) ); i++ ) { *ptr++ = 0; } - wmops[currCounter].LastWOper = 0; + wmops[counterId].LastWOper = 0; return; } #endif - - - diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index 3dae42b..5d24b5a 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.h +++ b/src/wmc_tool/test_data/ref/wmc_auto.h @@ -1,5 +1,5 @@ /* - * (C) 2023 copyright VoiceAge Corporation. All Rights Reserved. + * (C) 2024 copyright VoiceAge Corporation. All Rights Reserved. * * This software is protected by copyright law and by international treaties. The source code, and all of its derivations, * is provided by VoiceAge Corporation under the "ITU-T Software Tools' General Public License". Please, read the license file @@ -23,18 +23,16 @@ #include /* stdio is needed for fprintf() */ #endif - /* To Prevent "warning: '$' in identifier or number" message under GCC */ #ifdef __GNUC__ #pragma GCC system_header #endif -#ifndef INT_MAX -#define INT_MAX 32767 -#endif - -#define FRAMES_PER_SECOND 50.0 -#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */ +#define ENH_32_BIT_OPERATOR +#define ENH_64_BIT_OPERATOR +#define ENH_U_32_BIT_OPERATOR +#define COMPLEX_OPERATOR +#define CONTROL_CODE_OPS /* enable control code operators such as LT_16, GT_16, ... */ #ifdef WMOPS enum instructions @@ -62,6 +60,30 @@ enum instructions NUM_INST }; +extern double ops_cnt; +extern double inst_cnt[NUM_INST]; + +/******************************************************************/ +/* NOTES: */ +/* The 'wmc_flag_' flag is global to avoid declaration in every */ +/* function and 'static' to avoid clashing with other modules */ +/* that include this header file. */ +/* */ +/* The declarations of 'wmc_flag_' and 'wops_' in this header */ +/* file prevent the addition of a 'C' file to the Project. */ +/******************************************************************/ + +/* General Purpose Global int */ +static int wmc_flag_ = 0; + +#define push_wmops( ... ) push_wmops_fct( __VA_ARGS__, NULL ) +void push_wmops_fct( const char *label, ... ); +void pop_wmops( void ); +void reset_wmops( void ); +void print_wmops( void ); +void update_wmops( void ); +void update_mem( void ); + #define _ADD_C 1 #define _ABS_C 1 #define _MULT_C 1 @@ -83,501 +105,167 @@ enum instructions #define _LOG_C 25 #define _MISC_C 1 -#define _ADD_P 1 -#define _ABS_P 1 -#define _MULT_P 1 -#define _MAC_P 1 -#define _MOVE_P 1 -#define _STORE_P 0 -#define _LOGIC_P 1 -#define _SHIFT_P 1 -#define _BRANCH_P 2 -#define _DIV_P 2 -#define _SQRT_P 2 -#define _TRANS_P 2 -#define _FUNC_P 2 /* need to add number of arguments */ -#define _LOOP_P 1 -#define _INDIRECT_P 2 -#define _PTR_INIT_P 1 -#define _TEST_P 1 -#define _POWER_P 2 -#define _LOG_P 2 -#define _MISC_P 1 - -#define ADD( x ) \ - { \ - { \ - ops_cnt += ( _ADD_C * ( x ) ); \ - inst_cnt[_ADD] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _ADD_P * ( x ) ); \ - } \ - } \ - } \ - } -#define ABS( x ) \ - { \ - { \ - ops_cnt += ( _ABS_C * ( x ) ); \ - inst_cnt[_ABS] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _ABS_P * ( x ) ); \ - } \ - } \ - } \ +#define ADD( x ) \ + { \ + ops_cnt += ( _ADD_C * ( x ) ); \ + inst_cnt[_ADD] += ( x ); \ } -#define MULT( x ) \ - { \ - { \ - ops_cnt += ( _MULT_C * ( x ) ); \ - inst_cnt[_MULT] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _MULT_P * ( x ) ); \ - } \ - } \ - } \ +#define ABS( x ) \ + { \ + ops_cnt += ( _ABS_C * ( x ) ); \ + inst_cnt[_ABS] += ( x ); \ } -#define MAC( x ) \ - { \ - { \ - ops_cnt += ( _MAC_C * ( x ) ); \ - inst_cnt[_MAC] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _MAC_P * ( x ) ); \ - } \ - } \ - } \ +#define MULT( x ) \ + { \ + ops_cnt += ( _MULT_C * ( x ) ); \ + inst_cnt[_MULT] += ( x ); \ } -#define MOVE( x ) \ - { \ - { \ - ops_cnt += ( _MOVE_C * ( x ) ); \ - inst_cnt[_MOVE] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _MOVE_P * ( x ) ); \ - } \ - } \ - } \ +#define MAC( x ) \ + { \ + ops_cnt += ( _MAC_C * ( x ) ); \ + inst_cnt[_MAC] += ( x ); \ } -#define STORE( x ) \ - { \ - { \ - ops_cnt += ( _STORE_C * ( x ) ); \ - inst_cnt[_STORE] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _STORE_P * ( x ) ); \ - } \ - } \ - } \ +#define MOVE( x ) \ + { \ + ops_cnt += ( _MOVE_C * ( x ) ); \ + inst_cnt[_MOVE] += ( x ); \ } -#define LOGIC( x ) \ - { \ - { \ - ops_cnt += ( _LOGIC_C * ( x ) ); \ - inst_cnt[_LOGIC] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _LOGIC_P * ( x ) ); \ - } \ - } \ - } \ +#define STORE( x ) \ + { \ + ops_cnt += ( _STORE_C * ( x ) ); \ + inst_cnt[_STORE] += ( x ); \ } -#define SHIFT( x ) \ - { \ - { \ - ops_cnt += ( _SHIFT_C * ( x ) ); \ - inst_cnt[_SHIFT] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _SHIFT_P * ( x ) ); \ - } \ - } \ - } \ +#define LOGIC( x ) \ + { \ + ops_cnt += ( _LOGIC_C * ( x ) ); \ + inst_cnt[_LOGIC] += ( x ); \ } -#define BRANCH( x ) \ - { \ - { \ - ops_cnt += ( _BRANCH_C * ( x ) ); \ - inst_cnt[_BRANCH] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _BRANCH_P * ( x ) ); \ - } \ - } \ - } \ +#define SHIFT( x ) \ + { \ + ops_cnt += ( _SHIFT_C * ( x ) ); \ + inst_cnt[_SHIFT] += ( x ); \ } -#define DIV( x ) \ - { \ - { \ - ops_cnt += ( _DIV_C * ( x ) ); \ - inst_cnt[_DIV] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _DIV_P * ( x ) ); \ - } \ - } \ - } \ +#define BRANCH( x ) \ + { \ + ops_cnt += ( _BRANCH_C * ( x ) ); \ + inst_cnt[_BRANCH] += ( x ); \ } -#define SQRT( x ) \ - { \ - { \ - ops_cnt += ( _SQRT_C * ( x ) ); \ - inst_cnt[_SQRT] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _SQRT_P * ( x ) ); \ - } \ - } \ - } \ +#define DIV( x ) \ + { \ + ops_cnt += ( _DIV_C * ( x ) ); \ + inst_cnt[_DIV] += ( x ); \ } -#define TRANS( x ) \ - { \ - { \ - ops_cnt += ( _TRANS_C * ( x ) ); \ - inst_cnt[_TRANS] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _TRANS_P * ( x ) ); \ - } \ - } \ - } \ +#define SQRT( x ) \ + { \ + ops_cnt += ( _SQRT_C * ( x ) ); \ + inst_cnt[_SQRT] += ( x ); \ } -#define LOOP( x ) \ - { \ - { \ - ops_cnt += ( _LOOP_C * ( x ) ); \ - inst_cnt[_LOOP] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _LOOP_P * ( x ) ); \ - } \ - } \ - } \ +#define TRANS( x ) \ + { \ + ops_cnt += ( _TRANS_C * ( x ) ); \ + inst_cnt[_TRANS] += ( x ); \ } -#define INDIRECT( x ) \ - { \ - { \ - ops_cnt += ( _INDIRECT_C * ( x ) ); \ - inst_cnt[_INDIRECT] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _INDIRECT_P * ( x ) ); \ - } \ - } \ - } \ +#define LOOP( x ) \ + { \ + ops_cnt += ( _LOOP_C * ( x ) ); \ + inst_cnt[_LOOP] += ( x ); \ } -#define PTR_INIT( x ) \ - { \ - { \ - ops_cnt += ( _PTR_INIT_C * ( x ) ); \ - inst_cnt[_PTR_INIT] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _PTR_INIT_P * ( x ) ); \ - } \ - } \ - } \ +#define INDIRECT( x ) \ + { \ + ops_cnt += ( _INDIRECT_C * ( x ) ); \ + inst_cnt[_INDIRECT] += ( x ); \ } -#define TEST( x ) \ - { \ - { \ - ops_cnt += ( _TEST_C * ( x ) ); \ - inst_cnt[_TEST] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _TEST_P * ( x ) ); \ - } \ - } \ - } \ +#define PTR_INIT( x ) \ + { \ + ops_cnt += ( _PTR_INIT_C * ( x ) ); \ + inst_cnt[_PTR_INIT] += ( x ); \ } -#define POWER( x ) \ - { \ - { \ - ops_cnt += ( _POWER_C * ( x ) ); \ - inst_cnt[_POWER] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _POWER_P * ( x ) ); \ - } \ - } \ - } \ +#define TEST( x ) \ + { \ + ops_cnt += ( _TEST_C * ( x ) ); \ + inst_cnt[_TEST] += ( x ); \ } -#define LOG( x ) \ - { \ - { \ - ops_cnt += ( _LOG_C * ( x ) ); \ - inst_cnt[_LOG] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _LOG_P * ( x ) ); \ - } \ - } \ - } \ +#define POWER( x ) \ + { \ + ops_cnt += ( _POWER_C * ( x ) ); \ + inst_cnt[_POWER] += ( x ); \ } -#define MISC( x ) \ - { \ - { \ - ops_cnt += ( _MISC_C * ( x ) ); \ - inst_cnt[_MISC] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _MISC_P * ( x ) ); \ - } \ - } \ - } \ +#define LOG( x ) \ + { \ + ops_cnt += ( _LOG_C * ( x ) ); \ + inst_cnt[_LOG] += ( x ); \ } - -#define FUNC( x ) \ - { \ - { \ - ops_cnt += ( _FUNC_C + _MOVE_C * ( x ) ); \ - inst_cnt[_FUNC]++; \ - inst_cnt[_MOVE] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _FUNC_P + _MOVE_P * ( x ) ); \ - } \ - } \ - } \ +#define MISC( x ) \ + { \ + ops_cnt += ( _MISC_C * ( x ) ); \ + inst_cnt[_MISC] += ( x ); \ } - -#define DADD( x ) \ - { \ - { \ - ops_cnt += ( 2 * _ADD_C * ( x ) ); \ - inst_cnt[_ADD] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _ADD_P * ( x ) ); \ - } \ - } \ - } \ +#define FUNC( x ) \ + { \ + ops_cnt += ( _FUNC_C + _MOVE_C * ( x ) ); \ + inst_cnt[_FUNC]++; \ + inst_cnt[_MOVE] += ( x ); \ } -#define DMULT( x ) \ - { \ - { \ - ops_cnt += ( 2 * _MULT_C * ( x ) ); \ - inst_cnt[_MULT] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _MULT_P * ( x ) ); \ - } \ - } \ - } \ +#define DADD( x ) \ + { \ + ops_cnt += ( 2 * _ADD_C * ( x ) ); \ + inst_cnt[_ADD] += ( x ); \ } -#define DMAC( x ) \ - { \ - { \ - ops_cnt += ( 2 * _MAC_C * ( x ) ); \ - inst_cnt[_MAC] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _MAC_P * ( x ) ); \ - } \ - } \ - } \ +#define DMULT( x ) \ + { \ + ops_cnt += ( 2 * _MULT_C * ( x ) ); \ + inst_cnt[_MULT] += ( x ); \ } -#define DMOVE( x ) \ - { \ - { \ - ops_cnt += ( 2 * _MOVE_C * ( x ) ); \ - inst_cnt[_MOVE] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _MOVE_P * ( x ) ); \ - } \ - } \ - } \ +#define DMAC( x ) \ + { \ + ops_cnt += ( 2 * _MAC_C * ( x ) ); \ + inst_cnt[_MAC] += ( x ); \ } -#define DSTORE( x ) \ - { \ - { \ - ops_cnt += ( 2 * _STORE_C * ( x ) ); \ - inst_cnt[_STORE] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _STORE_P * ( x ) ); \ - } \ - } \ - } \ +#define DMOVE( x ) \ + { \ + ops_cnt += ( 2 * _MOVE_C * ( x ) ); \ + inst_cnt[_MOVE] += ( x ); \ } -#define DLOGIC( x ) \ - { \ - { \ - ops_cnt += ( 2 * _LOGIC_C * ( x ) ); \ - inst_cnt[_LOGIC] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _LOGIC_P * ( x ) ); \ - } \ - } \ - } \ +#define DSTORE( x ) \ + { \ + ops_cnt += ( 2 * _STORE_C * ( x ) ); \ + inst_cnt[_STORE] += ( x ); \ } -#define DSHIFT( x ) \ - { \ - { \ - ops_cnt += ( 2 * _SHIFT_C * ( x ) ); \ - inst_cnt[_SHIFT] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _SHIFT_P * ( x ) ); \ - } \ - } \ - } \ +#define DLOGIC( x ) \ + { \ + ops_cnt += ( 2 * _LOGIC_C * ( x ) ); \ + inst_cnt[_LOGIC] += ( x ); \ } -#define DDIV( x ) \ - { \ - { \ - ops_cnt += ( 2 * _DIV_C * ( x ) ); \ - inst_cnt[_DIV] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _DIV_P * ( x ) ); \ - } \ - } \ - } \ +#define DSHIFT( x ) \ + { \ + ops_cnt += ( 2 * _SHIFT_C * ( x ) ); \ + inst_cnt[_SHIFT] += ( x ); \ } -#define DSQRT( x ) \ - { \ - { \ - ops_cnt += ( 2 * _SQRT_C * ( x ) ); \ - inst_cnt[_SQRT] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _SQRT_P * ( x ) ); \ - } \ - } \ - } \ +#define DDIV( x ) \ + { \ + ops_cnt += ( 2 * _DIV_C * ( x ) ); \ + inst_cnt[_DIV] += ( x ); \ } -#define DTRANS( x ) \ - { \ - { \ - ops_cnt += ( 2 * _TRANS_C * ( x ) ); \ - inst_cnt[_TRANS] += ( x ); \ - { \ - static int pcnt; \ - if ( !pcnt ) \ - { \ - pcnt = 1; \ - prom_cnt += ( _TRANS_P * ( x ) ); \ - } \ - } \ - } \ +#define DSQRT( x ) \ + { \ + ops_cnt += ( 2 * _SQRT_C * ( x ) ); \ + inst_cnt[_SQRT] += ( x ); \ } +#define DTRANS( x ) \ + { \ + ops_cnt += ( 2 * _TRANS_C * ( x ) ); \ + inst_cnt[_TRANS] += ( x ); \ + } -extern double ops_cnt; -extern double prom_cnt; -extern double inst_cnt[NUM_INST]; - -void reset_wmops( void ); -void push_wmops( const char *label ); -void pop_wmops( void ); -void update_wmops( void ); -void update_mem( void ); -void print_wmops( void ); - -#else /* WMOPS counting disabled */ +#else -#define reset_wmops() extern int cntr_push_pop; #define push_wmops( x ) ( cntr_push_pop++ ) #define pop_wmops() ( cntr_push_pop-- ) -#define update_wmops() ( assert( cntr_push_pop == 0 ) ) -#define update_mem() +#define reset_wmops() #define print_wmops() +#define update_wmops() ( assert( cntr_push_pop == 0 ) ) +#define update_mem() #define ADD( x ) #define ABS( x ) @@ -628,24 +316,8 @@ extern int cntr_push_pop; #else -/* '*ops_cnt_ptr' is Used to Avoid: "warning: operation on 'ops_cnt' may be undefined" with Cygwin gcc Compiler */ -static double *ops_cnt_ptr = &ops_cnt; -#define OP_COUNT_( op, x ) ( *ops_cnt_ptr += ( op##_C * ( x ) ), inst_cnt[op] += ( x ) ) - -/******************************************************************/ -/* NOTES: */ -/* The 'wmc_flag_' flag is global to avoid declaration in every */ -/* function and 'static' to avoid clashing with other modules */ -/* that include this header file. */ -/* */ -/* The declarations of 'wmc_flag_' and 'wops_' in this header */ -/* file prevent the addition of a 'C' file to the Project. */ -/******************************************************************/ - -/* General Purpose Global Flag */ -static int wmc_flag_ = 0; - /* Operation Counter Wrappers */ +#define OP_COUNT_( op, x ) ( ops_cnt += ( op##_C * ( x ) ), inst_cnt[op] += ( x ) ) #define OP_COUNT_WRAPPER1_( op, val ) ( op, val ) #define OP_COUNT_WRAPPER2_( expr ) \ if ( expr, 0 ) \ @@ -660,24 +332,24 @@ static int wmc_flag_ = 0; #endif /* Define all Macros without '{' & '}' (None of these should be called externally!) */ -#define ABS_( x ) OP_COUNT_( _ABS, ( x ) ) -#define ADD_( x ) OP_COUNT_( _ADD, ( x ) ) -#define MULT_( x ) OP_COUNT_( _MULT, ( x ) ) -#define MAC_( x ) OP_COUNT_( _MAC, ( x ) ) -#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) ) -#define STORE_( x ) OP_COUNT_( _STORE, ( x ) ) -#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) ) -#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) ) -#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) ) -#define DIV_( x ) OP_COUNT_( _DIV, ( x ) ) -#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) ) -#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) ) +#define ABS_( x ) OP_COUNT_( _ABS, ( x ) ) +#define ADD_( x ) OP_COUNT_( _ADD, ( x ) ) +#define MULT_( x ) OP_COUNT_( _MULT, ( x ) ) +#define MAC_( x ) OP_COUNT_( _MAC, ( x ) ) +#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) ) +#define STORE_( x ) OP_COUNT_( _STORE, ( x ) ) +#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) ) +#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) ) +#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) ) +#define DIV_( x ) OP_COUNT_( _DIV, ( x ) ) +#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) ) +#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) ) #define POWER_( x ) TRANS_( x ) #define LOG_( x ) TRANS_( x ) -#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) ) -#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) ) -#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) ) -#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) ) +#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) ) +#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) ) +#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) ) +#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) ) #define MISC_( x ) ABS_( x ) /* Math Operations */ @@ -723,8 +395,8 @@ static int wmc_flag_ = 0; #define frexpf_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexpf ) /* the macros below are instrumented versions of user-defined macros that might be used in the source code -/* representing some well-known and recognized mathematical operations (that are not defined in math.h) */ -/* Note: the 'wmc_flag_=wmc_flag_' is used to avoid warning: left-hand operand of comma expression has no effect with gcc */ + representing some well-known and recognized mathematical operations (that are not defined in math.h) + Note: the 'wmc_flag_=wmc_flag_' is used to avoid warning: left-hand operand of comma expression has no effect with gcc */ #define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) ) #define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) ) @@ -744,8 +416,8 @@ static int wmc_flag_ = 0; #define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) ) #define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrtf( ( x ) ) ) #define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) ) -#define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) ) -#define log2f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2f( ( x ) ) ) +#define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) ) +#define log2f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2f( ( x ) ) ) #define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) ) #define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) ) #define round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round( ( x ) ) ) @@ -795,7 +467,6 @@ static int wmc_flag_ = 0; #define return_ \ OP_COUNT_WRAPPER2_( ( wmc_flag_ = stack_tree_level_, STACK_DEPTH_FCT_RETURN ) ) \ return - #define switch_ \ OP_COUNT_WRAPPER2_( ( BRANCH_( 1 ), wmc_flag_ = 1 ) ) \ switch @@ -911,7 +582,6 @@ static void wops_( const char *ops ) /* This Shouldn't Happen */ /* These are Used to Avoid: "warning: 'name' defined but not used" with Cygwin gcc Compiler */ wmc_flag_ = wmc_flag_; - ops_cnt_ptr = ops_cnt_ptr; fct( "" ); error: default: @@ -973,7 +643,7 @@ typedef struct ROM_Size_Lookup_Table * ROM_Size_Lookup_Table Const_Data_PROM_Table[] = * { * {"../lib_enc/rom_enc.c", 0, NULL}, - * {"../lib_com/*.c", 0, NULL}, + * {"../lib_com/[star].c", 0, NULL}, * {"", -1, NULL} * }; * #endif @@ -986,22 +656,9 @@ typedef enum { USE_BYTES = 0, USE_16BITS = 1, - USE_32BITS = 2, - USE_64BITS = 3 + USE_32BITS = 2 } Counting_Size; -#if ( defined( _WIN32 ) && ( _MSC_VER <= 1800 ) && ( _MSC_VER >= 1300 ) ) -#define __func__ __FUNCTION__ -#elif defined( __STDC_VERSION__ ) && __STDC_VERSION__ < 199901L -#if ( __GNUC__ >= 2 ) -#define __func__ __FUNCTION__ -#else -#define __func__ "" -#endif -#elif defined( __GNUC__ ) -#define __func__ __extension__ __FUNCTION__ -#endif - #ifdef WMOPS @@ -1019,11 +676,11 @@ int push_stack( const char *filename, const char *fctname ); int pop_stack( const char *filename, const char *fctname ); #ifdef WMOPS_DETAIL -#define STACK_DEPTH_FCT_CALL ( push_wmops( __FUNCTION__ " [WMC_AUTO]" ), push_stack( __FILE__, __FUNCTION__ ) ) /* add push_wmops() in all function calls */ -#define STACK_DEPTH_FCT_RETURN ( pop_wmops(), pop_stack( __FILE__, __FUNCTION__ ) ) /* add pop_wmops() in all function returns */ +#define STACK_DEPTH_FCT_CALL ( push_wmops( __func__, "[WMC_AUTO]" ), push_stack( __FILE__, __func__ ) ) /* add push_wmops() in all function calls */ +#define STACK_DEPTH_FCT_RETURN ( pop_wmops(), pop_stack( __FILE__, __func__ ) ) /* add pop_wmops() in all function returns */ #else -#define STACK_DEPTH_FCT_CALL push_stack( __FILE__, __FUNCTION__ ) -#define STACK_DEPTH_FCT_RETURN pop_stack( __FILE__, __FUNCTION__ ) +#define STACK_DEPTH_FCT_CALL push_stack( __FILE__, __func__ ) +#define STACK_DEPTH_FCT_RETURN pop_stack( __FILE__, __func__ ) #endif void reset_stack( void ); @@ -1043,7 +700,6 @@ void reset_stack( void ); #endif - /* Global counter variable for calculation of complexity weight */ typedef struct { @@ -1101,10 +757,10 @@ typedef struct unsigned int L40_max; /* Complexity Weight of 1 */ unsigned int L40_min; /* Complexity Weight of 1 */ - unsigned int shl_r; /* Complexity Weight of 3 */ - unsigned int L_shl_r; /* Complexity Weight of 3 */ - unsigned int L40_shr_r; /* Complexity Weight of 3 */ - unsigned int L40_shl_r; /* Complexity Weight of 3 */ + unsigned int shl_r; /* Complexity Weight of 2 */ + unsigned int L_shl_r; /* Complexity Weight of 2 */ + unsigned int L40_shr_r; /* Complexity Weight of 2 */ + unsigned int L40_shl_r; /* Complexity Weight of 2 */ unsigned int norm_L40; /* Complexity Weight of 1 */ unsigned int L40_shl; /* Complexity Weight of 1 */ @@ -1121,7 +777,7 @@ typedef struct unsigned int L40_msu; /* Complexity Weight of 1 */ unsigned int msu_r40; /* Complexity Weight of 2 */ unsigned int Mpy_32_16_ss; /* Complexity Weight of 2 */ - unsigned int Mpy_32_32_ss; /* Complexity Weight of 4 */ + unsigned int Mpy_32_32_ss; /* Complexity Weight of 2 */ unsigned int L_mult0; /* Complexity Weight of 1 */ unsigned int L_mac0; /* Complexity Weight of 1 */ @@ -1145,7 +801,7 @@ typedef struct unsigned int rotr; /* Complexity Weight of 3 */ unsigned int L_rotl; /* Complexity Weight of 3 */ unsigned int L_rotr; /* Complexity Weight of 3 */ - unsigned int L40_set; /* Complexity Weight of 3 */ + unsigned int L40_set; /* Complexity Weight of 1 */ unsigned int L40_deposit_h; /* Complexity Weight of 1 */ unsigned int L40_deposit_l; /* Complexity Weight of 1 */ @@ -1157,48 +813,159 @@ typedef struct unsigned int L40_round; /* Complexity Weight of 1 */ unsigned int L_saturate40; /* Complexity Weight of 1 */ unsigned int round40; /* Complexity Weight of 1 */ - unsigned int If; /* Complexity Weight of 4 */ - unsigned int Goto; /* Complexity Weight of 4 */ + unsigned int If; /* Complexity Weight of 3 */ + unsigned int Goto; /* Complexity Weight of 2 */ - unsigned int Break; /* Complexity Weight of 4 */ - unsigned int Switch; /* Complexity Weight of 8 */ + unsigned int Break; /* Complexity Weight of 2 */ + unsigned int Switch; /* Complexity Weight of 6 */ unsigned int For; /* Complexity Weight of 3 */ - unsigned int While; /* Complexity Weight of 4 */ - unsigned int Continue; /* Complexity Weight of 4 */ + unsigned int While; /* Complexity Weight of 3 */ + unsigned int Continue; /* Complexity Weight of 2 */ - unsigned int L_mls; /* Complexity Weight of 6 */ + unsigned int L_mls; /* Complexity Weight of 1 */ unsigned int div_l; /* Complexity Weight of 32 */ - unsigned int i_mult; /* Complexity Weight of 3 */ + unsigned int i_mult; /* Complexity Weight of 1 */ + +/* New complex basic operators */ +#ifdef COMPLEX_OPERATOR + unsigned int CL_shr; /* Complexity Weight of 1 */ + unsigned int CL_shl; /* Complexity Weight of 1 */ + unsigned int CL_add; /* Complexity Weight of 1 */ + unsigned int CL_sub; /* Complexity Weight of 1 */ + unsigned int CL_scale; /* Complexity Weight of 1 */ + unsigned int CL_dscale; /* Complexity Weight of 1 */ + unsigned int CL_msu_j; /* Complexity Weight of 1 */ + unsigned int CL_mac_j; /* Complexity Weight of 1 */ + unsigned int CL_move; /* Complexity Weight of 1 */ + unsigned int CL_Extract_real; /* Complexity Weight of 1 */ + unsigned int CL_Extract_imag; /* Complexity Weight of 1 */ + unsigned int CL_form; /* Complexity Weight of 1 */ + unsigned int CL_multr_32x16; /* Complexity Weight of 2 */ + unsigned int CL_negate; /* Complexity Weight of 1 */ + unsigned int CL_conjugate; /* Complexity Weight of 1 */ + unsigned int CL_mul_j; /* Complexity Weight of 1 */ + unsigned int CL_swap_real_imag; /* Complexity Weight of 1 */ + unsigned int C_add; /* Complexity Weight of 1 */ + unsigned int C_sub; /* Complexity Weight of 1 */ + unsigned int C_mul_j; /* Complexity Weight of 1 */ + unsigned int C_multr; /* Complexity Weight of 2 */ + unsigned int C_form; /* Complexity Weight of 1 */ + + unsigned int C_scale; /* Complexity Weight of 1 */ + unsigned int CL_round32_16; /* Complexity Weight of 1 */ + unsigned int CL_scale_32; /* Complexity Weight of 1 */ + unsigned int CL_dscale_32; /* Complexity Weight of 1 */ + unsigned int CL_multr_32x32; /* Complexity Weight of 2 */ + unsigned int C_mac_r; /* Complexity Weight of 2 */ + unsigned int C_msu_r; /* Complexity Weight of 2 */ + unsigned int C_Extract_real; /* Complexity Weight of 1 */ + unsigned int C_Extract_imag; /* Complexity Weight of 1 */ + unsigned int C_negate; /* Complexity Weight of 1 */ + unsigned int C_conjugate; /* Complexity Weight of 1 */ + unsigned int C_shr; /* Complexity Weight of 1 */ + unsigned int C_shl; /* Complexity Weight of 1 */ + +#endif /* #ifdef COMPLEX_OPERATOR */ + +/* New 64 bit basops */ +#ifdef ENH_64_BIT_OPERATOR + unsigned int move64; /* Complexity Weight of 1 */ + unsigned int W_add_nosat; /* Complexity Weight of 1 */ + unsigned int W_sub_nosat; /* Complexity Weight of 1 */ + unsigned int W_shl; /* Complexity Weight of 1 */ + unsigned int W_shr; /* Complexity Weight of 1 */ + unsigned int W_shl_nosat; /* Complexity Weight of 1 */ + unsigned int W_shr_nosat; /* Complexity Weight of 1 */ + unsigned int W_mac_32_16; /* Complexity Weight of 1 */ + unsigned int W_msu_32_16; /* Complexity Weight of 1 */ + unsigned int W_mult_32_16; /* Complexity Weight of 1 */ + unsigned int W_mult0_16_16; /* Complexity Weight of 1 */ + unsigned int W_mac0_16_16; /* Complexity Weight of 1 */ + unsigned int W_msu0_16_16; /* Complexity Weight of 1 */ + unsigned int W_mult_16_16; /* Complexity Weight of 1 */ + unsigned int W_mac_16_16; /* Complexity Weight of 1 */ + unsigned int W_msu_16_16; /* Complexity Weight of 1 */ + unsigned int W_shl_sat_l; /* Complexity Weight of 1 */ + unsigned int W_sat_l; /* Complexity Weight of 1 */ + unsigned int W_sat_m; /* Complexity Weight of 1 */ + unsigned int W_deposit32_l; /* Complexity Weight of 1 */ + unsigned int W_deposit32_h; /* Complexity Weight of 1 */ + unsigned int W_extract_l; /* Complexity Weight of 1 */ + unsigned int W_extract_h; /* Complexity Weight of 1 */ + unsigned int W_round48_L; /* Complexity Weight of 1 */ + unsigned int W_round32_s; /* Complexity Weight of 1 */ + unsigned int W_norm; /* Complexity Weight of 1 */ + + unsigned int W_add; /* Complexity Weight of 1 */ + unsigned int W_sub; /* Complexity Weight of 1 */ + unsigned int W_neg; /* Complexity Weight of 1 */ + unsigned int W_abs; /* Complexity Weight of 1 */ + unsigned int W_mult_32_32; /* Complexity Weight of 1 */ + unsigned int W_mult0_32_32; /* Complexity Weight of 1 */ + unsigned int W_lshl; /* Complexity Weight of 1 */ + unsigned int W_lshr; /* Complexity Weight of 1 */ + unsigned int W_round64_L; /* Complexity Weight of 1 */ + +#endif /* #ifdef ENH_64_BIT_OPERATOR */ + +#ifdef ENH_32_BIT_OPERATOR + unsigned int Mpy_32_16_1; /* Complexity Weight of 1 */ + unsigned int Mpy_32_16_r; /* Complexity Weight of 1 */ + unsigned int Mpy_32_32; /* Complexity Weight of 1 */ + unsigned int Mpy_32_32_r; /* Complexity Weight of 1 */ + unsigned int Madd_32_16; /* Complexity Weight of 1 */ + unsigned int Madd_32_16_r; /* Complexity Weight of 1 */ + unsigned int Msub_32_16; /* Complexity Weight of 1 */ + unsigned int Msub_32_16_r; /* Complexity Weight of 1 */ + unsigned int Madd_32_32; /* Complexity Weight of 1 */ + unsigned int Madd_32_32_r; /* Complexity Weight of 1 */ + unsigned int Msub_32_32; /* Complexity Weight of 1 */ + unsigned int Msub_32_32_r; /* Complexity Weight of 1 */ +#endif /* #ifdef ENH_32_BIT_OPERATOR */ + +#ifdef ENH_U_32_BIT_OPERATOR + unsigned int UL_addNs; /* Complexity Weight of 1 */ + unsigned int UL_subNs; /* Complexity Weight of 1 */ + unsigned int UL_Mpy_32_32; /* Complexity Weight of 1 */ + unsigned int Mpy_32_32_uu; /* Complexity Weight of 2 */ + unsigned int Mpy_32_16_uu; /* Complexity Weight of 2 */ + unsigned int norm_ul_float; /* Complexity Weight of 1 */ + unsigned int UL_deposit_l; /* Complexity Weight of 1 */ +#endif /* #ifdef ENH_U_32_BIT_OPERATOR */ + +#ifdef CONTROL_CODE_OPS + unsigned int LT_16; /* Complexity Weight of 1 */ + unsigned int GT_16; /* Complexity Weight of 1 */ + unsigned int LE_16; /* Complexity Weight of 1 */ + unsigned int GE_16; /* Complexity Weight of 1 */ + unsigned int EQ_16; /* Complexity Weight of 1 */ + unsigned int NE_16; /* Complexity Weight of 1 */ + unsigned int LT_32; /* Complexity Weight of 1 */ + unsigned int GT_32; /* Complexity Weight of 1 */ + unsigned int LE_32; /* Complexity Weight of 1 */ + unsigned int GE_32; /* Complexity Weight of 1 */ + unsigned int EQ_32; /* Complexity Weight of 1 */ + unsigned int NE_32; /* Complexity Weight of 1 */ + unsigned int LT_64; /* Complexity Weight of 1 */ + unsigned int GT_64; /* Complexity Weight of 1 */ + unsigned int LE_64; /* Complexity Weight of 1 */ + unsigned int GE_64; /* Complexity Weight of 1 */ + unsigned int EQ_64; /* Complexity Weight of 1 */ + unsigned int NE_64; /* Complexity Weight of 1 */ + +#endif /* #ifdef CONTROL_CODE_OPS */ } BASIC_OP; #ifdef WMOPS extern BASIC_OP *multiCounter; -extern int currCounter; - -/* Technical note : - * The following 3 variables are only used for correct complexity - * evaluation of the following structure : - * IF{ - * ... - * } ELSE IF { - * ... - * } ELSE IF { - * ... - * } - * ... - * } ELSE { - * ... - * } - */ +extern unsigned int currCounter; extern int funcId_where_last_call_to_else_occurred; extern long funcid_total_wmops_at_last_call_to_else; extern int call_occurred; -extern long TotalWeightedOperation( void ); -long DeltaWeightedOperation( void ); - -void Set_BASOP_WMOPS_counter( int counterId ); -void Reset_BASOP_WMOPS_counter( void ); +long TotalWeightedOperation( unsigned int counterId ); +long DeltaWeightedOperation( unsigned int counterId ); +void Reset_BASOP_WMOPS_counter( unsigned int counterId ); #endif @@ -1216,15 +983,20 @@ void Reset_BASOP_WMOPS_counter( void ); * *****************************************************************************/ #ifndef WMOPS -#define FOR( a) for( a) +#define FOR( a ) for ( a ) -#else -#define FOR( a) if( incrFor(), 0); else for( a) +#else /* ifndef WMOPS */ +#define FOR( a ) \ + if ( incrFor(), 0 ) \ + ; \ + else \ + for ( a ) -static __inline void incrFor( void) { - multiCounter[currCounter].For++; +static __inline void incrFor( void ) +{ + multiCounter[currCounter].For++; } -#endif +#endif /* ifndef WMOPS */ /***************************************************************************** @@ -1241,15 +1013,16 @@ static __inline void incrFor( void) { * *****************************************************************************/ #ifndef WMOPS -#define WHILE( a) while( a) +#define WHILE( a ) while ( a ) -#else -#define WHILE( a) while( incrWhile(), a) +#else /* ifndef WMOPS */ +#define WHILE( a ) while ( incrWhile(), a ) -static __inline void incrWhile( void) { - multiCounter[currCounter].While++; +static __inline void incrWhile( void ) +{ + multiCounter[currCounter].While++; } -#endif +#endif /* ifndef WMOPS */ /***************************************************************************** @@ -1266,10 +1039,10 @@ static __inline void incrWhile( void) { #ifndef WMOPS #define DO do -#else +#else /* ifndef WMOPS */ #define DO do -#endif +#endif /* ifndef WMOPS */ /***************************************************************************** @@ -1289,29 +1062,16 @@ static __inline void incrWhile( void) { * - or when the 'if' conditions several DSP basic operations, * - or when the 'if' conditions a function call. * - * Complexity weight : 4 + * Complexity weight : 3 * *****************************************************************************/ -#ifndef WMOPS -#define IF( a) if( a) -#else -#define IF( a) if( incrIf(), a) - -static __inline void incrIf( void) { - /* Technical note : - * If the "IF" operator comes just after an "ELSE", its counter - * must not be incremented. - */ - if ( ( currCounter != funcId_where_last_call_to_else_occurred ) || ( TotalWeightedOperation() != funcid_total_wmops_at_last_call_to_else ) || ( call_occurred == 1 ) ) - { - multiCounter[currCounter].If++; - } - - call_occurred = 0; - funcId_where_last_call_to_else_occurred = INT_MAX; -} -#endif +#ifndef WMOPS +#define IF( a ) if ( a ) +#else /* ifndef WMOPS */ +#define IF( a ) if ( incrIf( __func__ ), a ) +void incrIf( const char *func_name ); +#endif /* ifndef WMOPS */ /***************************************************************************** @@ -1322,33 +1082,16 @@ static __inline void incrIf( void) { * * The macro ELSE should be used instead of the 'else' C statement. * - * Complexity weight : 4 + * Complexity weight : 3 * *****************************************************************************/ + #ifndef WMOPS #define ELSE else - -#else -#define ELSE else if( incrElse(), 0) ; else - -static __inline void incrElse( void) { - multiCounter[currCounter].If++; - - /* We keep track of the funcId of the last function - * which used ELSE {...} structure. - */ - funcId_where_last_call_to_else_occurred = currCounter; - - /* We keep track of the number of WMOPS of this funcId - * when the ELSE macro was called. - */ - funcid_total_wmops_at_last_call_to_else = TotalWeightedOperation(); - - /* call_occurred is set to 0, in order to count the next IF (if necessary) - */ - call_occurred = 0; -} -#endif +#else /* ifndef WMOPS */ +#define ELSE else if ( incrElse( __func__ ), 0 ); else +void incrElse( const char *func_name ); +#endif /* ifndef WMOPS */ /***************************************************************************** @@ -1359,19 +1102,20 @@ static __inline void incrElse( void) { * * The macro SWITCH should be used instead of the 'switch' C statement. * - * Complexity weight : 8 + * Complexity weight : 6 * *****************************************************************************/ #ifndef WMOPS -#define SWITCH( a) switch( a) +#define SWITCH( a ) switch ( a ) -#else -#define SWITCH( a) switch( incrSwitch(), a) +#else /* ifndef WMOPS */ +#define SWITCH( a ) switch ( incrSwitch(), a ) -static __inline void incrSwitch( void) { - multiCounter[currCounter].Switch++; +static __inline void incrSwitch( void ) +{ + multiCounter[currCounter].Switch++; } -#endif +#endif /* ifndef WMOPS */ /***************************************************************************** @@ -1382,19 +1126,24 @@ static __inline void incrSwitch( void) { * * The macro CONTINUE should be used instead of the 'continue' C statement. * - * Complexity weight : 4 + * Complexity weight : 2 * *****************************************************************************/ #ifndef WMOPS #define CONTINUE continue -#else -#define CONTINUE if( incrContinue(), 0); else continue +#else /* ifndef WMOPS */ +#define CONTINUE \ + if ( incrContinue(), 0 ) \ + ; \ + else \ + continue -static __inline void incrContinue( void) { - multiCounter[currCounter].Continue++; +static __inline void incrContinue( void ) +{ + multiCounter[currCounter].Continue++; } -#endif +#endif /* ifndef WMOPS */ /***************************************************************************** @@ -1405,19 +1154,24 @@ static __inline void incrContinue( void) { * * The macro BREAK should be used instead of the 'break' C statement. * - * Complexity weight : 4 + * Complexity weight : 2 * *****************************************************************************/ #ifndef WMOPS #define BREAK break -#else -#define BREAK if( incrBreak(), 0) break; else break +#else /* ifndef WMOPS */ +#define BREAK \ + if ( incrBreak(), 0 ) \ + ; \ + else \ + break -static __inline void incrBreak( void) { - multiCounter[currCounter].Break++; +static __inline void incrBreak( void ) +{ + multiCounter[currCounter].Break++; } -#endif +#endif /* ifndef WMOPS */ /***************************************************************************** @@ -1428,21 +1182,51 @@ static __inline void incrBreak( void) { * * The macro GOTO should be used instead of the 'goto' C statement. * - * Complexity weight : 4 + * Complexity weight : 2 * *****************************************************************************/ #ifndef WMOPS #define GOTO goto -#else -#define GOTO if( incrGoto(), 0); else goto +#else /* ifndef WMOPS */ +#define GOTO \ + if ( incrGoto(), 0 ) \ + ; \ + else \ + goto -static __inline void incrGoto( void) { - multiCounter[currCounter].Goto++; +static __inline void incrGoto( void ) +{ + multiCounter[currCounter].Goto++; } -#endif +#endif /* ifndef WMOPS */ -#endif /* WMOPS_H */ +#ifdef CONTROL_CODE_OPS + +extern int LT_16( short var1, short var2 ); +extern int GT_16( short var1, short var2 ); +extern int LE_16( short var1, short var2 ); +extern int GE_16( short var1, short var2 ); +extern int EQ_16( short var1, short var2 ); +extern int NE_16( short var1, short var2 ); +extern int LT_32( int L_var1, int L_var2 ); +extern int GT_32( int L_var1, int L_var2 ); +extern int LE_32( int L_var1, int L_var2 ); +extern int GE_32( int L_var1, int L_var2 ); +extern int EQ_32( int L_var1, int L_var2 ); +extern int NE_32( int L_var1, int L_var2 ); + +extern int LT_64( long long int L64_var1, long long int L64_var2 ); +extern int GT_64( long long int L64_var1, long long int L64_var2 ); +extern int LE_64( long long int L64_var1, long long int L64_var2 ); +extern int GE_64( long long int L64_var1, long long int L64_var2 ); +extern int EQ_64( long long int L64_var1, long long int L64_var2 ); +extern int NE_64( long long int L64_var1, long long int L64_var2 ); + +#endif /* #ifdef CONTROL_CODE_OPS */ + + +#endif /* WMOPS_H */ diff --git a/src/wmc_tool/wmc_auto_c.txt b/src/wmc_tool/wmc_auto_c.txt index 0f64019..c18b9dd 100644 --- a/src/wmc_tool/wmc_auto_c.txt +++ b/src/wmc_tool/wmc_auto_c.txt @@ -1,2529 +1,2529 @@ -"/*\r\n" -" * (C) 2024 copyright VoiceAge Corporation. All Rights Reserved.\r\n" -" *\r\n" -" * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n" -" * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n" -" * or refer to ITU-T Recommendation G.191 on \"SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS\".\r\n" -" *\r\n" -" * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor\r\n" -" * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software\r\n" -" * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE.\r\n" -" *\r\n" -" * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca)\r\n" -" */\r\n" -"\r\n" -"#include \r\n" -"#include \r\n" -"#include \r\n" -"#include \r\n" -"#include \r\n" -"#include \r\n" -"#include \r\n" -"\r\n" -"#ifndef _MSC_VER\r\n" -"#include \r\n" -"#include \r\n" -"#else\r\n" -"#include \r\n" -"#endif\r\n" -"\r\n" -"#include \"wmc_auto.h\"\r\n" -"\r\n" -"#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */\r\n" -"\r\n" -"#ifndef WMOPS\r\n" -"int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */\r\n" -"#endif\r\n" -"\r\n" -"#ifdef WMOPS\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * Complexity counting tool\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"\r\n" -"#define MAX_FUNCTION_NAME_LENGTH 200 /* Maximum length of the function name */\r\n" -"#define MAX_PARAMS_LENGTH 200 /* Maximum length of the function parameter string */\r\n" -"#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> might be increased during runtime, if needed */\r\n" -"#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */\r\n" -"#define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */\r\n" -"#define DOUBLE_MAX 0x80000000\r\n" -"#define FAC ( FRAMES_PER_SECOND / 1e6 )\r\n" -"\r\n" -"#define FRAMES_PER_SECOND 50.0\r\n" -"#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */\r\n" -"\r\n" -"typedef struct\r\n" -"{\r\n" -" char label[MAX_FUNCTION_NAME_LENGTH];\r\n" -" long call_number;\r\n" -" long update_cnt;\r\n" -" int call_tree[MAX_CALL_TREE_DEPTH];\r\n" -" long LastWOper;\r\n" -" double start_selfcnt;\r\n" -" double current_selfcnt;\r\n" -" double max_selfcnt;\r\n" -" double min_selfcnt;\r\n" -" double tot_selfcnt;\r\n" -" double start_cnt; /* The following take into account the decendants */\r\n" -" double current_cnt;\r\n" -" double max_cnt;\r\n" -" double min_cnt;\r\n" -" double tot_cnt;\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" int32_t current_call_number;\r\n" -" double wc_cnt;\r\n" -" double wc_selfcnt;\r\n" -" int32_t wc_call_number;\r\n" -"#endif\r\n" -"} wmops_record;\r\n" -"\r\n" -"double ops_cnt;\r\n" -"double inst_cnt[NUM_INST];\r\n" -"\r\n" -"static wmops_record *wmops = NULL;\r\n" -"static int num_wmops_records, max_num_wmops_records;\r\n" -"static int current_record;\r\n" -"static long update_cnt;\r\n" -"static double start_cnt;\r\n" -"static double max_cnt;\r\n" -"static double min_cnt;\r\n" -"static double inst_cnt_wc[NUM_INST];\r\n" -"static long fnum_cnt_wc;\r\n" -"static int *wmops_caller_stack = NULL, wmops_caller_stack_index, max_wmops_caller_stack_index = 0;\r\n" -"static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0;\r\n" -"\r\n" -"static BASIC_OP op_weight = {\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 2, 2, 1,\r\n" -" 1, 1, 1, 2, 1,\r\n" -"\r\n" -" 1, 1, 1, 2, 1,\r\n" -" 1, 1, 18, 1, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 2, 2, 2, 2, 1,\r\n" -"\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 1, 2,\r\n" -" 1, 2, 2, 2, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -"\r\n" -" 1, 1, 1, 1, 3,\r\n" -" 3, 3, 3, 1, 1,\r\n" -" 1, 1, 1, 1, 1,\r\n" -" 1, 1, 1, 3, 2,\r\n" -" 2, 6, 3, 3, 2,\r\n" -"\r\n" -" 1, 32, 1\r\n" -"\r\n" -"/* New complex basops */\r\n" -"#ifdef COMPLEX_OPERATOR\r\n" -" ,\r\n" -" 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1\r\n" -"\r\n" -" ,\r\n" -" 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1\r\n" -"\r\n" -"#endif /* #ifdef COMPLEX_OPERATOR */\r\n" -"\r\n" -"#ifdef ENH_64_BIT_OPERATOR\r\n" -" /* Weights of new 64 bit basops */\r\n" -" ,\r\n" -" 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\r\n" -"#endif /* #ifdef ENH_64_BIT_OPERATOR */\r\n" -"\r\n" -"#ifdef ENH_32_BIT_OPERATOR\r\n" -" ,\r\n" -" 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\r\n" -"#endif /* #ifdef ENH_32_BIT_OPERATOR */\r\n" -"\r\n" -"#ifdef ENH_U_32_BIT_OPERATOR\r\n" -" ,\r\n" -" 1, 1, 1, 2, 2, 1, 1\r\n" -"#endif /* #ifdef ENH_U_32_BIT_OPERATOR */\r\n" -"\r\n" -"#ifdef CONTROL_CODE_OPS\r\n" -" ,\r\n" -" 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\r\n" -"#endif /* #ifdef CONTROL_CODE_OPS */\r\n" -"};\r\n" -"\r\n" -"BASIC_OP *multiCounter = NULL;\r\n" -"unsigned int currCounter = 0;\r\n" -"int funcId_where_last_call_to_else_occurred;\r\n" -"long funcid_total_wmops_at_last_call_to_else;\r\n" -"int call_occurred = 1;\r\n" -"char func_name_where_last_call_to_else_occurred[MAX_FUNCTION_NAME_LENGTH + 1];\r\n" -"\r\n" -"void reset_wmops( void )\r\n" -"{\r\n" -" int i, j;\r\n" -"\r\n" -" num_wmops_records = 0;\r\n" -" max_num_wmops_records = MAX_NUM_RECORDS;\r\n" -" current_record = -1;\r\n" -" update_cnt = 0;\r\n" -"\r\n" -" max_cnt = 0.0;\r\n" -" min_cnt = DOUBLE_MAX;\r\n" -" start_cnt = 0.0;\r\n" -" ops_cnt = 0.0;\r\n" -"\r\n" -" /* allocate the list of WMOPS records */\r\n" -" if ( wmops == NULL )\r\n" -" {\r\n" -" wmops = (wmops_record *) malloc( max_num_wmops_records * sizeof( wmops_record ) );\r\n" -" }\r\n" -"\r\n" -" if ( wmops == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Records!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* allocate the list of BASOP WMOPS records */\r\n" -" if ( multiCounter == NULL )\r\n" -" {\r\n" -" multiCounter = (BASIC_OP *) malloc( max_num_wmops_records * sizeof( BASIC_OP ) );\r\n" -" }\r\n" -"\r\n" -" if ( multiCounter == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Unable to Allocate the BASOP WMOPS counter!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* initilize the list of WMOPS records */\r\n" -" /* initilize BASOP operation counters */\r\n" -" for ( i = 0; i < max_num_wmops_records; i++ )\r\n" -" {\r\n" -" strcpy( &wmops[i].label[0], \"\\0\" );\r\n" -" wmops[i].call_number = 0;\r\n" -" wmops[i].update_cnt = 0;\r\n" -" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n" -" {\r\n" -" wmops[i].call_tree[j] = -1;\r\n" -" }\r\n" -" wmops[i].start_selfcnt = 0.0;\r\n" -" wmops[i].current_selfcnt = 0.0;\r\n" -" wmops[i].max_selfcnt = 0.0;\r\n" -" wmops[i].min_selfcnt = DOUBLE_MAX;\r\n" -" wmops[i].tot_selfcnt = 0.0;\r\n" -" wmops[i].start_cnt = 0.0;\r\n" -" wmops[i].current_cnt = 0.0;\r\n" -" wmops[i].max_cnt = 0.0;\r\n" -" wmops[i].min_cnt = DOUBLE_MAX;\r\n" -" wmops[i].tot_cnt = 0.0;\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" wmops[i].wc_cnt = 0.0;\r\n" -" wmops[i].wc_selfcnt = 0.0;\r\n" -" wmops[i].current_call_number = 0;\r\n" -" wmops[i].wc_call_number = -1;\r\n" -"#endif\r\n" -"\r\n" -" /* Reset BASOP operation counter */\r\n" -" Reset_BASOP_WMOPS_counter( i );\r\n" -" }\r\n" -"\r\n" -" /* allocate the list of wmops callers to track the sequence of function calls */\r\n" -" wmops_caller_stack_index = 0;\r\n" -" max_wmops_caller_stack_index = MAX_NUM_RECORDS;\r\n" -" if ( wmops_caller_stack == NULL )\r\n" -" {\r\n" -" wmops_caller_stack = malloc( max_wmops_caller_stack_index * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" if ( wmops_caller_stack == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Callers!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" for ( i = 0; i < max_wmops_caller_stack_index; i++ )\r\n" -" {\r\n" -" wmops_caller_stack[i] = -1;\r\n" -" }\r\n" -"\r\n" -" /* initialize auxiliary BASOP counter variables */\r\n" -" currCounter = 0; /* Note: currCounter cannot be set to -1 because it's defined as unsigned int ! */\r\n" -" call_occurred = 1;\r\n" -" funcId_where_last_call_to_else_occurred = -100;\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"void push_wmops_fct( const char *label, ... )\r\n" -"{\r\n" -" int new_flag;\r\n" -" int i, j, index_record;\r\n" -" long tot;\r\n" -" va_list arg;\r\n" -" char func_name[MAX_FUNCTION_NAME_LENGTH] = \"\";\r\n" -"\r\n" -" /* concatenate all function name labels into a single string */\r\n" -" va_start( arg, label );\r\n" -" while ( label )\r\n" -" {\r\n" -" strcat( func_name, label );\r\n" -" label = va_arg( arg, const char * );\r\n" -" }\r\n" -" va_end( arg );\r\n" -"\r\n" -" /* Check, if this is a new function label */\r\n" -" new_flag = 1;\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" if ( strcmp( wmops[i].label, func_name ) == 0 )\r\n" -" {\r\n" -" new_flag = 0;\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -" index_record = i;\r\n" -"\r\n" -" /* Create a new WMOPS record in the list */\r\n" -" if ( new_flag )\r\n" -" {\r\n" -" if ( num_wmops_records >= max_num_wmops_records )\r\n" -" {\r\n" -" /* There is no room for a new WMOPS record -> reallocate the list */\r\n" -" max_num_wmops_records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" wmops = realloc( wmops, max_num_wmops_records * sizeof( wmops_record ) );\r\n" -" multiCounter = realloc( multiCounter, max_num_wmops_records * sizeof( BASIC_OP ) );\r\n" -" }\r\n" -"\r\n" -" /* initilize the new WMOPS record */\r\n" -" strcpy( &wmops[index_record].label[0], \"\\0\" );\r\n" -" wmops[index_record].call_number = 0;\r\n" -" wmops[index_record].update_cnt = 0;\r\n" -" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n" -" {\r\n" -" wmops[index_record].call_tree[j] = -1;\r\n" -" }\r\n" -" wmops[index_record].start_selfcnt = 0.0;\r\n" -" wmops[index_record].current_selfcnt = 0.0;\r\n" -" wmops[index_record].max_selfcnt = 0.0;\r\n" -" wmops[index_record].min_selfcnt = DOUBLE_MAX;\r\n" -" wmops[index_record].tot_selfcnt = 0.0;\r\n" -" wmops[index_record].start_cnt = 0.0;\r\n" -" wmops[index_record].current_cnt = 0.0;\r\n" -" wmops[index_record].max_cnt = 0.0;\r\n" -" wmops[index_record].min_cnt = DOUBLE_MAX;\r\n" -" wmops[index_record].tot_cnt = 0.0;\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" wmops[index_record].wc_cnt = 0.0;\r\n" -" wmops[index_record].wc_selfcnt = 0.0;\r\n" -" wmops[index_record].current_call_number = 0;\r\n" -" wmops[index_record].wc_call_number = -1;\r\n" -"#endif\r\n" -"\r\n" -" /* Reset BASOP operation counter */\r\n" -" Reset_BASOP_WMOPS_counter( index_record );\r\n" -"\r\n" -" strcpy( wmops[index_record].label, func_name );\r\n" -"\r\n" -" num_wmops_records++;\r\n" -" }\r\n" -"\r\n" -" /* Update the WMOPS context info of the old record before switching to the new one */\r\n" -" if ( current_record >= 0 )\r\n" -" {\r\n" -" if ( wmops_caller_stack_index >= max_wmops_caller_stack_index )\r\n" -" {\r\n" -" /* There is no room for a new record -> reallocate the list */\r\n" -" max_wmops_caller_stack_index += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" wmops_caller_stack = realloc( wmops_caller_stack, max_wmops_caller_stack_index * sizeof( int ) );\r\n" -" }\r\n" -" wmops_caller_stack[wmops_caller_stack_index++] = current_record;\r\n" -"\r\n" -" /* add the BASOP complexity to the counter and update the old WMOPS counter */\r\n" -" tot = DeltaWeightedOperation( current_record );\r\n" -" ops_cnt += tot;\r\n" -" wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n" -"\r\n" -" /* update call tree */\r\n" -" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n" -" {\r\n" -" if ( wmops[index_record].call_tree[j] == current_record )\r\n" -" {\r\n" -" break;\r\n" -" }\r\n" -" else if ( wmops[index_record].call_tree[j] == -1 )\r\n" -" {\r\n" -" wmops[index_record].call_tree[j] = current_record;\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Need to reset the BASOP operation counter of the 0th record in every push_wmops() */\r\n" -" /* because currCounter can never be -1 */\r\n" -" if ( current_record == -1 && index_record == 0 )\r\n" -" {\r\n" -" wmops[index_record].LastWOper = TotalWeightedOperation( index_record );\r\n" -" }\r\n" -"\r\n" -" /* switch to the new record */\r\n" -" current_record = index_record;\r\n" -" wmops[index_record].start_selfcnt = ops_cnt;\r\n" -" wmops[index_record].start_cnt = ops_cnt;\r\n" -" wmops[index_record].call_number++;\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" wmops[index_record].current_call_number++;\r\n" -"#endif\r\n" -"\r\n" -" /* set the ID of the current BASOP operations counter */\r\n" -" currCounter = index_record;\r\n" -" call_occurred = 1;\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"void pop_wmops( void )\r\n" -"{\r\n" -" long tot;\r\n" -"\r\n" -" /* Check for underflow */\r\n" -" if ( current_record < 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"\\r pop_wmops(): stack underflow, too many calls to pop_wmops()\\n\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* add the BASOP complexity to the counter */\r\n" -" tot = DeltaWeightedOperation( currCounter );\r\n" -" ops_cnt += tot;\r\n" -"\r\n" -" /* update count of current record */\r\n" -" wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n" -" wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt;\r\n" -"\r\n" -" /* Get back previous context from stack */\r\n" -" if ( wmops_caller_stack_index > 0 )\r\n" -" {\r\n" -" current_record = wmops_caller_stack[--wmops_caller_stack_index];\r\n" -" wmops[current_record].start_selfcnt = ops_cnt;\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" current_record = -1;\r\n" -" }\r\n" -"\r\n" -" /* set the ID of the previous BASOP operations counter */\r\n" -" if ( current_record == -1 )\r\n" -" {\r\n" -" currCounter = 0; /* Note: currCounter cannot be set to -1 because it's defined as unsigned int ! */\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" currCounter = current_record;\r\n" -" }\r\n" -" call_occurred = 1;\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"\r\n" -"void update_wmops( void )\r\n" -"{\r\n" -" int i;\r\n" -" double current_cnt;\r\n" -"#ifdef WMOPS_PER_FRAME\r\n" -" static FILE *fid = NULL;\r\n" -" const char filename[] = \"wmops_analysis\";\r\n" -" float tmpF;\r\n" -"#endif\r\n" -"\r\n" -" if ( wmops_caller_stack_index != 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"update_wmops(): WMOPS caller stack corrupted - check that all push_wmops() are matched with pop_wmops()!\\n\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -"#ifdef WMOPS_PER_FRAME\r\n" -" /* Check, if the output file has already been opened */\r\n" -" if ( fid == NULL )\r\n" -" {\r\n" -" fid = fopen( filename, \"wb\" );\r\n" -"\r\n" -" if ( fid == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", filename );\r\n" -" exit( -1 );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Write current complexity to the external file */\r\n" -" tmpF = (float) ( FAC * wmops[0].current_cnt );\r\n" -" fwrite( &tmpF, sizeof( float ), 1, fid );\r\n" -"#endif\r\n" -"\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" if ( ops_cnt - start_cnt > max_cnt )\r\n" -" {\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" wmops[i].wc_cnt = wmops[i].current_cnt;\r\n" -" wmops[i].wc_selfcnt = wmops[i].current_selfcnt;\r\n" -" wmops[i].wc_call_number = wmops[i].current_call_number;\r\n" -" }\r\n" -" }\r\n" -"#endif\r\n" -"\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" wmops[i].tot_selfcnt += wmops[i].current_selfcnt;\r\n" -" wmops[i].tot_cnt += wmops[i].current_cnt;\r\n" -"\r\n" -" if ( wmops[i].current_selfcnt > 0 )\r\n" -" {\r\n" -" if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt )\r\n" -" {\r\n" -" wmops[i].max_selfcnt = wmops[i].current_selfcnt;\r\n" -" }\r\n" -"\r\n" -" if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt )\r\n" -" {\r\n" -" wmops[i].min_selfcnt = wmops[i].current_selfcnt;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" wmops[i].current_selfcnt = 0;\r\n" -"\r\n" -" if ( wmops[i].current_cnt > 0 )\r\n" -" {\r\n" -" if ( wmops[i].current_cnt > wmops[i].max_cnt )\r\n" -" {\r\n" -" wmops[i].max_cnt = wmops[i].current_cnt;\r\n" -" }\r\n" -"\r\n" -"\r\n" -" if ( wmops[i].current_cnt < wmops[i].min_cnt )\r\n" -" {\r\n" -" wmops[i].min_cnt = wmops[i].current_cnt;\r\n" -" }\r\n" -"\r\n" -" wmops[i].update_cnt++;\r\n" -" }\r\n" -"\r\n" -" wmops[i].current_cnt = 0;\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" wmops[i].current_call_number = 0;\r\n" -"#endif\r\n" -"\r\n" -" /* reset the BASOP operations counter */\r\n" -" call_occurred = 1;\r\n" -" Reset_BASOP_WMOPS_counter( i );\r\n" -" }\r\n" -"\r\n" -" current_cnt = ops_cnt - start_cnt;\r\n" -" if ( current_cnt > max_cnt )\r\n" -" {\r\n" -" max_cnt = current_cnt;\r\n" -"\r\n" -" for ( i = 0; i < NUM_INST; i++ )\r\n" -" {\r\n" -" inst_cnt_wc[i] = inst_cnt[i];\r\n" -" }\r\n" -"\r\n" -" fnum_cnt_wc = update_cnt + 1;\r\n" -" }\r\n" -"\r\n" -" if ( current_cnt < min_cnt )\r\n" -" {\r\n" -" min_cnt = current_cnt;\r\n" -" }\r\n" -"\r\n" -" for ( i = 0; i < NUM_INST; i++ )\r\n" -" {\r\n" -" inst_cnt[i] = 0.0;\r\n" -" }\r\n" -"\r\n" -" start_cnt = ops_cnt;\r\n" -"\r\n" -" /* increment frame counter */\r\n" -" update_cnt++;\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"void print_wmops( void )\r\n" -"{\r\n" -" int i, label_len, max_label_len;\r\n" -"\r\n" -" char *sfmts = \"%*s %8s %8s %7s %7s\\n\";\r\n" -" char *dfmts = \"%*s %8.2f %8.3f %7.3f %7.3f\\n\";\r\n" -" char *sfmt = \"%*s %8s %8s %7s %7s %7s %7s %7s\\n\";\r\n" -" char *dfmt = \"%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\\n\";\r\n" -"\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" int j;\r\n" -" char *sfmtt = \"%20s %4s %15s\\n\";\r\n" -" char *dfmtt = \"%20s %4d \";\r\n" -"#endif\r\n" -"\r\n" -" /* calculate maximum label length for compact prinout */\r\n" -" max_label_len = 0;\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" label_len = strlen( wmops[i].label );\r\n" -" if ( label_len > max_label_len )\r\n" -" {\r\n" -" max_label_len = label_len;\r\n" -" }\r\n" -" }\r\n" -" max_label_len += 4;\r\n" -"\r\n" -" fprintf( stdout, \"\\n\\n --- Complexity analysis [WMOPS] --- \\n\\n\" );\r\n" -"\r\n" -" fprintf( stdout, \"%*s %33s %23s\\n\", max_label_len, \"\", \"|------ SELF ------|\", \"|--- CUMULATIVE ---|\" );\r\n" -" fprintf( stdout, sfmt, max_label_len, \" routine\", \" calls\", \" min \", \" max \", \" avg \", \" min \", \" max \", \" avg \" );\r\n" -" fprintf( stdout, sfmt, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\" );\r\n" -"\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" fprintf( stdout, dfmt, max_label_len, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt,\r\n" -" wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt,\r\n" -" FAC * wmops[i].max_selfcnt,\r\n" -" wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt,\r\n" -" wmops[i].min_cnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_cnt,\r\n" -" FAC * wmops[i].max_cnt,\r\n" -" wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt );\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, sfmts, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\" );\r\n" -" fprintf( stdout, dfmts, max_label_len, \"total\", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt );\r\n" -" fprintf( stdout, \"\\n\" );\r\n" -"\r\n" -"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n" -" fprintf( stdout, \"\\nComplexity analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n" -" fprintf( stdout, \"%*s %8s %10s %12s\\n\", max_label_len, \" routine\", \" calls\", \" SELF\", \" CUMULATIVE\" );\r\n" -" fprintf( stdout, \"%*s %8s %10s %10s\\n\", max_label_len, \"---------------\", \"------\", \"------\", \"----------\" );\r\n" -"\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" if ( wmops[i].wc_call_number > 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"%*s %8d %10.3f %12.3f\\n\", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, \"\\nCall tree for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n" -" fprintf( stdout, sfmtt, \" function\", \"num\", \"called by \" );\r\n" -" fprintf( stdout, sfmtt, \"---------------\", \"---\", \"--------------\" );\r\n" -"\r\n" -" for ( i = 0; i < num_wmops_records; i++ )\r\n" -" {\r\n" -" if ( wmops[i].wc_call_number > 0 )\r\n" -" {\r\n" -" fprintf( stdout, dfmtt, wmops[i].label, i );\r\n" -" for ( j = 0; wmops[i].call_tree[j] != -1 && j < MAX_CALL_TREE_DEPTH; j++ )\r\n" -" {\r\n" -" if ( j != 0 )\r\n" -" {\r\n" -" fprintf( stdout, \", \" );\r\n" -" }\r\n" -" fprintf( stdout, \"%d\", wmops[i].call_tree[j] );\r\n" -" }\r\n" -" fprintf( stdout, \"\\n\" );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, \"\\n\\n\" );\r\n" -"\r\n" -" fprintf( stdout, \"\\nInstruction type analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n" -" for ( i = 0; i < NUM_INST; i++ )\r\n" -" {\r\n" -" switch ( (enum instructions) i )\r\n" -" {\r\n" -" case _ADD:\r\n" -" fprintf( stdout, \"\\tAdds: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _ABS:\r\n" -" fprintf( stdout, \"\\tAbsolutes: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _MULT:\r\n" -" fprintf( stdout, \"\\tMultiplies: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _MAC:\r\n" -" fprintf( stdout, \"\\tMACs: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _MOVE:\r\n" -" fprintf( stdout, \"\\tMoves: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _STORE:\r\n" -" fprintf( stdout, \"\\tStores: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _LOGIC:\r\n" -" fprintf( stdout, \"\\tLogicals: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _SHIFT:\r\n" -" fprintf( stdout, \"\\tShifts: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _BRANCH:\r\n" -" fprintf( stdout, \"\\tBranches: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _DIV:\r\n" -" fprintf( stdout, \"\\tDivisions: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _SQRT:\r\n" -" fprintf( stdout, \"\\tSquare Root: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _TRANS:\r\n" -" fprintf( stdout, \"\\tTrans: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _FUNC:\r\n" -" fprintf( stdout, \"\\tFunc Call: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _LOOP:\r\n" -" fprintf( stdout, \"\\tLoop Init: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _INDIRECT:\r\n" -" fprintf( stdout, \"\\tIndirect Addr: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _PTR_INIT:\r\n" -" fprintf( stdout, \"\\tPointer Init: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _TEST:\r\n" -" fprintf( stdout, \"\\tExtra condit.: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _POWER:\r\n" -" fprintf( stdout, \"\\tExponential: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _LOG:\r\n" -" fprintf( stdout, \"\\tLogarithm: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" case _MISC:\r\n" -" fprintf( stdout, \"\\tAll other op.: %12.1f\\n\", inst_cnt_wc[i] );\r\n" -" break;\r\n" -" default:\r\n" -" fprintf( stdout, \"\\tERROR: Invalid instruction type: %d\\n\\n\", i );\r\n" -" }\r\n" -" }\r\n" -"#endif\r\n" -"\r\n" -" /* De-allocate the list of wmops record */\r\n" -" if ( wmops != NULL )\r\n" -" {\r\n" -" free( wmops );\r\n" -" }\r\n" -"\r\n" -" /* De-allocate the list of wmops caller functions */\r\n" -" if ( wmops_caller_stack != NULL )\r\n" -" {\r\n" -" free( wmops_caller_stack );\r\n" -" }\r\n" -"\r\n" -" /* De-allocate the BASOP WMOPS counter */\r\n" -" if ( multiCounter != NULL )\r\n" -" {\r\n" -" free( multiCounter );\r\n" -" }\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * Memory counting tool measuring RAM usage (stack and heap)\r\n" -" *\r\n" -" * Maximum RAM is measured by monitoring the total allocated memory (stack and heap) in each frame.\r\n" -" *\r\n" -" * Maximum stack is measured by monitoring the difference between the 'top' and 'bottom' of the stack. The 'bottom' of the stack is updated in each function\r\n" -" * with a macro 'func_start_' which is inserted automatically to all functions during the instrumentation process.\r\n" -" *\r\n" -" * Maximum heap is measured by summing the sizes of all memory blocks allocated by malloc() or calloc() and deallocated by free(). The maximum heap size is\r\n" -" * updated each time when the macros malloc_() or calloc_() is invoked. The macros 'malloc_ and calloc_' are inserted automatically during the instrumentation process.\r\n" -" * As part of heap measurements, intra-frame heap and inter-frame heap are measured separately. Intra-frame heap refers to heap memory which is allocated and deallocated\r\n" -" * within a single frame. Inter-frame heap, on the contrary, refers to heap memory which is reserved for more than one frame.\r\n" -" *\r\n" -" * In order to run the memory counting tool the function reset_mem(cnt_size) must be called at the beginning of the encoding/decoding process.\r\n" -" * The unit in which memory consumption is reported is set via the parameter 'cnt_size'. It can be set to 0 (bytes), 1 (32b words) or 2 (64b words).\r\n" -" * At the end of the encoding/decoding process, 'print_mem()' function may be called to print basic information about memory consumption. If the macro 'MEM_COUNT_DETAILS'\r\n" -" * is activated, detailed information is printed\r\n" -" *\r\n" -" * The macro 'WMOPS' needs to be activated to enable memory counting. To avoid the instrumentation of malloc()/calloc()/free() calls, use\r\n" -" * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free().\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"\r\n" -"/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using\r\n" -" a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */\r\n" -"#ifdef MEM_ALIGN_64BITS\r\n" -"#define BLOCK_ROUNDING 8 /* Align on 64 Bits */\r\n" -"#else\r\n" -"#define BLOCK_ROUNDING 4 /* Align on 32 Bits */\r\n" -"#endif\r\n" -"\r\n" -"#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) )\r\n" -"\r\n" -"#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */\r\n" -"#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */\r\n" -"#define OOB_START 0x1 /* int indicating out-of-bounds access before memory block */\r\n" -"#define OOB_END 0x2 /* int indicating out-of-bounds access after memory block */\r\n" -"\r\n" -"#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) )\r\n" -"#define IS_CALLOC( str ) ( str[0] == 'c' )\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -"const char *csv_filename = \"mem_analysis.csv\";\r\n" -"static FILE *fid_csv_filename = NULL;\r\n" -"#endif\r\n" -"\r\n" -"typedef struct\r\n" -"{\r\n" -" char function_name[MAX_FUNCTION_NAME_LENGTH + 1];\r\n" -" int16_t *stack_ptr;\r\n" -"} caller_info;\r\n" -"\r\n" -"static caller_info *stack_callers[2] = { NULL, NULL };\r\n" -"\r\n" -"static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */\r\n" -"static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */\r\n" -"static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */\r\n" -"static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */\r\n" -"static int current_calls = 0, max_num_calls = MAX_NUM_RECORDS;\r\n" -"static char location_max_stack[256] = \"undefined\";\r\n" -"\r\n" -"typedef struct\r\n" -"{\r\n" -" char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */\r\n" -" char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */\r\n" -" unsigned long hash;\r\n" -" int lineno;\r\n" -" void *block_ptr;\r\n" -" int block_size;\r\n" -" unsigned long total_block_size; /* Cumulative sum of the allocated size in the session */\r\n" -" unsigned long total_used_size; /* Cumulative sum of the used size in the session */\r\n" -" int wc_heap_size_intra_frame; /* Worst-Case Intra-Frame Heap Size */\r\n" -" int wc_heap_size_inter_frame; /* Worst-Case Inter-Frame Heap Size */\r\n" -" int frame_allocated; /* Frame number in which the Memory Block has been allocated (-1 if not allocated at the moment) */\r\n" -" int OOB_Flag;\r\n" -" int noccurances; /* Number of times that the memory block has been allocated in a frame */\r\n" -"} allocator_record;\r\n" -"\r\n" -"allocator_record *allocation_list = NULL;\r\n" -"\r\n" -"static int Num_Records, Max_Num_Records;\r\n" -"static size_t Stat_Cnt_Size = USE_BYTES;\r\n" -"static const char *Count_Unit[] = { \"bytes\", \"words\", \"words\", \"words\" };\r\n" -"\r\n" -"static int32_t wc_ram_size, wc_ram_frame;\r\n" -"static int32_t current_heap_size;\r\n" -"static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap;\r\n" -"static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap;\r\n" -"static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap;\r\n" -"\r\n" -"/* Local Functions */\r\n" -"static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str );\r\n" -"allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record );\r\n" -"static void *mem_alloc_block( size_t size, const char *size_str );\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * reset_mem()\r\n" -" *\r\n" -" * Initialize/reset memory counting tool (stack and heap)\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void reset_mem( Counting_Size cnt_size )\r\n" -"{\r\n" -" int16_t something;\r\n" -" size_t tmp_size;\r\n" -"\r\n" -" /* initialize list of stack records */\r\n" -" if ( stack_callers[0] == NULL )\r\n" -" {\r\n" -" stack_callers[0] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n" -" stack_callers[1] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n" -" }\r\n" -"\r\n" -" if ( stack_callers[0] == NULL || stack_callers[1] == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Unable to Allocate List of Stack Records!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" current_calls = 0;\r\n" -" max_num_calls = MAX_NUM_RECORDS;\r\n" -"\r\n" -" /* initialize stack pointers */\r\n" -" ptr_base_stack = &something;\r\n" -" ptr_max_stack = ptr_base_stack;\r\n" -" ptr_current_stack = ptr_base_stack;\r\n" -"\r\n" -" /* initialize the unit of memory block size */\r\n" -" Stat_Cnt_Size = cnt_size;\r\n" -"\r\n" -" /* Check, if sizeof(int32_t) is 4 bytes */\r\n" -" tmp_size = sizeof( int32_t );\r\n" -" if ( tmp_size != 4 )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Expecting 'int32_t' to be a 32 Bits Integer!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* create allocation list for malloc() memory blocks */\r\n" -" if ( allocation_list == NULL )\r\n" -" {\r\n" -" allocation_list = malloc( MAX_NUM_RECORDS * sizeof( allocator_record ) );\r\n" -" }\r\n" -"\r\n" -" if ( allocation_list == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Unable to Create List of Memory Blocks!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" Num_Records = 0;\r\n" -" Max_Num_Records = MAX_NUM_RECORDS;\r\n" -"\r\n" -" wc_ram_size = 0;\r\n" -" wc_ram_frame = -1;\r\n" -" current_heap_size = 0;\r\n" -"\r\n" -" /* heap allocation tree */\r\n" -" heap_allocation_call_tree_max_size = MAX_NUM_RECORDS;\r\n" -" if ( heap_allocation_call_tree == NULL )\r\n" -" {\r\n" -" heap_allocation_call_tree = (int *) malloc( heap_allocation_call_tree_max_size * sizeof( int ) );\r\n" -" memset( heap_allocation_call_tree, -1, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n" -" }\r\n" -" heap_allocation_call_tree_size = 0;\r\n" -"\r\n" -" /* wc intra-frame heap */\r\n" -" max_items_wc_intra_frame_heap = MAX_NUM_RECORDS;\r\n" -" if ( list_wc_intra_frame_heap == NULL )\r\n" -" {\r\n" -" list_wc_intra_frame_heap = (int *) malloc( max_items_wc_intra_frame_heap * sizeof( int ) );\r\n" -" memset( list_wc_intra_frame_heap, -1, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -" n_items_wc_intra_frame_heap = 0;\r\n" -" size_wc_intra_frame_heap = 0;\r\n" -" location_wc_intra_frame_heap = -1;\r\n" -"\r\n" -" /* current inter-frame heap */\r\n" -" max_items_current_inter_frame_heap = MAX_NUM_RECORDS;\r\n" -" if ( list_current_inter_frame_heap == NULL )\r\n" -" {\r\n" -" list_current_inter_frame_heap = (int *) malloc( max_items_current_inter_frame_heap * sizeof( int ) );\r\n" -" memset( list_current_inter_frame_heap, -1, max_items_current_inter_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -" n_items_current_inter_frame_heap = 0;\r\n" -" size_current_inter_frame_heap = 0;\r\n" -"\r\n" -" /* wc inter-frame heap */\r\n" -" max_items_wc_inter_frame_heap = MAX_NUM_RECORDS;\r\n" -" if ( list_wc_inter_frame_heap == NULL )\r\n" -" {\r\n" -" list_wc_inter_frame_heap = (int *) malloc( max_items_wc_inter_frame_heap * sizeof( int ) );\r\n" -" memset( list_wc_inter_frame_heap, -1, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -" n_items_wc_inter_frame_heap = 0;\r\n" -" size_wc_inter_frame_heap = 0;\r\n" -" location_wc_inter_frame_heap = -1;\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -" /* Check, if the .csv file has already been opened */\r\n" -" if ( fid_csv_filename == NULL )\r\n" -" {\r\n" -" fid_csv_filename = fopen( csv_filename, \"wb\" );\r\n" -"\r\n" -" if ( fid_csv_filename == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", csv_filename );\r\n" -" exit( -1 );\r\n" -" }\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" /* reset file */\r\n" -" rewind( fid_csv_filename );\r\n" -" }\r\n" -"#endif\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * reset_stack()\r\n" -" *\r\n" -" * Reset stack pointer\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void reset_stack( void )\r\n" -"{\r\n" -" int16_t something;\r\n" -"\r\n" -" /* initialize/reset stack pointers */\r\n" -" ptr_base_stack = &something;\r\n" -" ptr_max_stack = ptr_base_stack;\r\n" -" ptr_current_stack = ptr_base_stack;\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * push_stack()\r\n" -" *\r\n" -" * Check the current stack pointer and update the maximum stack pointer, if new maximum found.\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"int push_stack( const char *filename, const char *fctname )\r\n" -"{\r\n" -" int16_t something;\r\n" -" int32_t current_stack_size;\r\n" -"\r\n" -" ptr_current_stack = &something;\r\n" -"\r\n" -" (void) *filename; /* to avoid compilation warning */\r\n" -"\r\n" -" if ( current_calls >= max_num_calls )\r\n" -" {\r\n" -" /* There is no room for a new record -> reallocate the list */\r\n" -" max_num_calls += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" stack_callers[0] = realloc( stack_callers[0], max_num_calls * sizeof( caller_info ) );\r\n" -" stack_callers[1] = realloc( stack_callers[1], max_num_calls * sizeof( caller_info ) );\r\n" -" }\r\n" -"\r\n" -" /* Valid Function Name? */\r\n" -" if ( fctname[0] == 0 )\r\n" -" { /* No */\r\n" -" fprintf( stderr, \"Invalid function name for call stack info.\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* Save the Name of the Calling Function in the Table */\r\n" -" strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FUNCTION_NAME_LENGTH );\r\n" -" stack_callers[0][current_calls].function_name[MAX_FUNCTION_NAME_LENGTH] = 0; /* Nul Terminate */\r\n" -"\r\n" -" /* Save the Stack Pointer */\r\n" -" stack_callers[0][current_calls].stack_ptr = ptr_current_stack;\r\n" -"\r\n" -" /* Increase the Number of Calls in the List */\r\n" -" current_calls++;\r\n" -"\r\n" -" /* Is this the First Time or the Worst Case? */\r\n" -" if ( ptr_current_stack < ptr_max_stack || ptr_max_stack == NULL )\r\n" -" { /* Yes */\r\n" -" /* Save Info about it */\r\n" -" ptr_max_stack = ptr_current_stack;\r\n" -"\r\n" -" /* save the worst-case frame number */\r\n" -" /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */\r\n" -" wc_stack_frame = update_cnt;\r\n" -" strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 );\r\n" -" location_max_stack[sizeof( location_max_stack ) - 1] = '\\0';\r\n" -"\r\n" -" /* Save Call Tree */\r\n" -" memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls );\r\n" -"\r\n" -" /* Terminate the List with 0 (for printing purposes) */\r\n" -" if ( current_calls < max_num_calls )\r\n" -" {\r\n" -" stack_callers[1][current_calls].function_name[0] = 0;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Check, if This is the New Worst-Case RAM (stack + heap) */\r\n" -" current_stack_size = ( int32_t )( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) );\r\n" -"\r\n" -" if ( current_stack_size < 0 )\r\n" -" {\r\n" -" /* prevent negative stack size */\r\n" -" current_stack_size = 0;\r\n" -" }\r\n" -"\r\n" -" if ( current_stack_size + current_heap_size > wc_ram_size )\r\n" -" {\r\n" -" wc_ram_size = current_stack_size + current_heap_size;\r\n" -" wc_ram_frame = update_cnt;\r\n" -" }\r\n" -"\r\n" -" return 0 /* for Now */;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * pop_stack()\r\n" -" *\r\n" -" * Remove stack caller entry from the list\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"int pop_stack( const char *filename, const char *fctname )\r\n" -"{\r\n" -" caller_info *caller_info_ptr;\r\n" -"\r\n" -" (void) *filename; /* to avoid compilation warning */\r\n" -"\r\n" -" /* Decrease the Number of Records */\r\n" -" current_calls--;\r\n" -"\r\n" -" /* Get Pointer to Caller Information */\r\n" -" caller_info_ptr = &stack_callers[0][current_calls];\r\n" -"\r\n" -" /* Check, if the Function Names Match */\r\n" -" if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 )\r\n" -" {\r\n" -" fprintf( stderr, \"Invalid usage of pop_stack()\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* Erase Entry */\r\n" -" caller_info_ptr->function_name[0] = 0;\r\n" -"\r\n" -" /* Retrieve previous stack pointer */\r\n" -" if ( current_calls == 0 )\r\n" -" {\r\n" -" ptr_current_stack = ptr_base_stack;\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" ptr_current_stack = stack_callers[0][current_calls - 1].stack_ptr;\r\n" -" }\r\n" -"\r\n" -" return 0 /* for Now */;\r\n" -"}\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * print_stack_call_tree()\r\n" -" *\r\n" -" * Print detailed information about worst-case stack usage\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static void print_stack_call_tree( void )\r\n" -"{\r\n" -" caller_info *caller_info_ptr;\r\n" -" int call_level;\r\n" -" char fctname[MAX_FUNCTION_NAME_LENGTH + 1];\r\n" -"\r\n" -" fprintf( stdout, \"\\nList of functions when maximum stack size is reached:\\n\\n\" );\r\n" -"\r\n" -" caller_info_ptr = &stack_callers[1][0];\r\n" -" for ( call_level = 0; call_level < max_num_calls; call_level++ )\r\n" -" {\r\n" -" /* Done? */\r\n" -" if ( caller_info_ptr->function_name[0] == 0 )\r\n" -" {\r\n" -" break;\r\n" -" }\r\n" -"\r\n" -" /* Print Name */\r\n" -" strncpy( fctname, caller_info_ptr->function_name, MAX_FUNCTION_NAME_LENGTH );\r\n" -" strcat( fctname, \"()\" );\r\n" -" fprintf( stdout, \"%-42s\", fctname );\r\n" -"\r\n" -" /* Print Stack Usage (Based on Difference) */\r\n" -" if ( call_level != 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"%lu %s\\n\", ( ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" fprintf( stdout, \"%lu %s\\n\", ( ( ptr_base_stack - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -"\r\n" -" /* Advance */\r\n" -" caller_info_ptr++;\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, \"\\n\" );\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"#endif\r\n" -"\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * mem_alloc()\r\n" -" *\r\n" -" * Creates new record, stores auxiliary information about which function allocated the memory, line number, parameters, etc.\r\n" -" * Finally, it allocates physical memory using malloc()\r\n" -" * The function also updates worst-case heap size and worst-case RAM size\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void *mem_alloc(\r\n" -" const char *func_name,\r\n" -" int func_lineno,\r\n" -" size_t size,\r\n" -" char *size_str /* the first char indicates m-alloc or c-alloc */ )\r\n" -"{\r\n" -" int index_record;\r\n" -" int32_t current_stack_size;\r\n" -" unsigned long hash;\r\n" -" allocator_record *ptr_record;\r\n" -"\r\n" -" if ( size == 0 )\r\n" -" {\r\n" -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Size of Zero not Supported\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* Search for an existing record (that has been de-allocated before) */\r\n" -" index_record = 0;\r\n" -" while ( ( ptr_record = get_mem_record( &hash, func_name, func_lineno, size_str, &index_record ) ) != NULL )\r\n" -" {\r\n" -" if ( ptr_record->frame_allocated == -1 )\r\n" -" {\r\n" -" break;\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" index_record++;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Create new record */\r\n" -" if ( ptr_record == NULL )\r\n" -" {\r\n" -" if ( Num_Records >= Max_Num_Records )\r\n" -" {\r\n" -" /* There is no room for a new record -> reallocate memory */\r\n" -" Max_Num_Records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" allocation_list = realloc( allocation_list, Max_Num_Records * sizeof( allocator_record ) );\r\n" -" }\r\n" -"\r\n" -" ptr_record = &( allocation_list[Num_Records] );\r\n" -"\r\n" -" /* Initialize new record */\r\n" -" ptr_record->hash = hash;\r\n" -" ptr_record->noccurances = 0;\r\n" -" ptr_record->total_block_size = 0;\r\n" -" ptr_record->total_used_size = 0;\r\n" -" ptr_record->frame_allocated = -1;\r\n" -" ptr_record->OOB_Flag = 0;\r\n" -" ptr_record->wc_heap_size_intra_frame = -1;\r\n" -" ptr_record->wc_heap_size_inter_frame = -1;\r\n" -"\r\n" -" index_record = Num_Records;\r\n" -" Num_Records++;\r\n" -" }\r\n" -"\r\n" -" /* Allocate memory block for the new record, add signature before the beginning and after the memory block and fill it with magic value */\r\n" -" ptr_record->block_ptr = mem_alloc_block( size, size_str );\r\n" -"\r\n" -" if ( ptr_record->block_ptr == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Cannot Allocate Memory!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* Save all auxiliary information about the memory block */\r\n" -" strncpy( ptr_record->name, func_name, MAX_FUNCTION_NAME_LENGTH );\r\n" -" ptr_record->name[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n" -" strncpy( ptr_record->params, size_str, MAX_PARAMS_LENGTH ); /* Note: The size string starts with either 'm' or 'c' to indicate 'm'alloc or 'c'alloc */\r\n" -" ptr_record->params[MAX_PARAMS_LENGTH] = '\\0';\r\n" -" ptr_record->lineno = func_lineno;\r\n" -" ptr_record->block_size = size;\r\n" -" ptr_record->total_block_size += size;\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -" /* Export heap memory allocation record to the .csv file */\r\n" -" fprintf( fid_csv_filename, \"A,%ld,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n" -"#endif\r\n" -"\r\n" -" if ( ptr_record->frame_allocated != -1 )\r\n" -" {\r\n" -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Attempt to Allocate the Same Memory Block with Freeing it First!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" ptr_record->frame_allocated = update_cnt; /* Store the current frame number -> later it will be used to determine the total duration */\r\n" -"\r\n" -" /* Update Heap Size in the current frame */\r\n" -" current_heap_size += ptr_record->block_size;\r\n" -"\r\n" -" /* Check, if this is the new Worst-Case RAM (stack + heap) */\r\n" -" current_stack_size = ( int32_t )( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) );\r\n" -" if ( current_stack_size + current_heap_size > wc_ram_size )\r\n" -" {\r\n" -" wc_ram_size = current_stack_size + current_heap_size;\r\n" -" wc_ram_frame = update_cnt;\r\n" -" }\r\n" -"\r\n" -" /* Add new entry to the heap allocation call tree */\r\n" -" if ( heap_allocation_call_tree == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Heap allocation call tree not created!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* check, if the maximum size of the call tree has been reached -> resize if so */\r\n" -" if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size )\r\n" -" {\r\n" -" heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" /* push new entry (positive number means push op, neagtive number means pop op; zero index must be converted to 0.01 :-) */\r\n" -" heap_allocation_call_tree[heap_allocation_call_tree_size++] = index_record;\r\n" -"\r\n" -" return ptr_record->block_ptr;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * mem_alloc_block()\r\n" -" *\r\n" -" * Physical allocation of memory using malloc(). Appends 'signature' before and after the block,\r\n" -" * pre-fills memory block with magic value\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static void *mem_alloc_block( size_t size, const char *size_str )\r\n" -"{\r\n" -" size_t rounded_size;\r\n" -" void *block_ptr;\r\n" -" char *tmp_ptr;\r\n" -" size_t n, f;\r\n" -" int32_t fill_value;\r\n" -" int32_t *ptr32;\r\n" -" int32_t mask, temp;\r\n" -"\r\n" -" /* Round Up Block Size */\r\n" -" rounded_size = ROUND_BLOCK_SIZE( size );\r\n" -"\r\n" -" /* Allocate memory using the standard malloc() by adding room for Signature Values */\r\n" -" block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 );\r\n" -"\r\n" -" if ( block_ptr == NULL )\r\n" -" {\r\n" -" return NULL;\r\n" -" }\r\n" -"\r\n" -" /* Add Signature Before the Start of the Block */\r\n" -" ptr32 = (int32_t *) block_ptr;\r\n" -" n = N_32BITS_BLOCKS;\r\n" -" do\r\n" -" {\r\n" -" *ptr32++ = MAGIC_VALUE_OOB;\r\n" -" } while ( --n );\r\n" -"\r\n" -" /* Fill Memory Block with Magic Value or 0 */\r\n" -" fill_value = MAGIC_VALUE_USED;\r\n" -" if ( size_str[0] == 'c' )\r\n" -" {\r\n" -" fill_value = 0x00000000;\r\n" -" }\r\n" -" n = size / sizeof( int32_t );\r\n" -" while ( n-- )\r\n" -" {\r\n" -" *ptr32++ = fill_value;\r\n" -" }\r\n" -"\r\n" -" /* Fill the Reminder of the Memory Block - After Rounding */\r\n" -" n = rounded_size - size;\r\n" -" f = n % sizeof( int32_t );\r\n" -" if ( f != 0 )\r\n" -" {\r\n" -" /* when filling with '0' need to adapt the magic value */\r\n" -" /* shift by [1->24, 2->16, 3->8] */\r\n" -" mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */\r\n" -" temp = MAGIC_VALUE_OOB & mask;\r\n" -" if ( fill_value != 0x0 )\r\n" -" { /* for malloc merge fill value */\r\n" -" temp += ( ~mask ) & MAGIC_VALUE_USED;\r\n" -" } /* for calloc the code in (1) above already introduces zeros */\r\n" -" *ptr32++ = temp;\r\n" -" }\r\n" -" n /= sizeof( int32_t );\r\n" -" n += N_32BITS_BLOCKS;\r\n" -"\r\n" -" /* Add Signature After the End of Block */\r\n" -" do\r\n" -" {\r\n" -" *ptr32++ = MAGIC_VALUE_OOB;\r\n" -" } while ( --n );\r\n" -"\r\n" -" /* Adjust the Memory Block Pointer (Magic Value Before and After the Memory Block Requested) */\r\n" -" tmp_ptr = (char *) block_ptr;\r\n" -" tmp_ptr += BLOCK_ROUNDING;\r\n" -" block_ptr = (void *) tmp_ptr;\r\n" -"\r\n" -" return block_ptr;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * mem_set_usage()\r\n" -" *\r\n" -" * Calculates actual usage of memory block by checking the magic value that was used to pre-fill\r\n" -" * each memory block during its allocation\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static int mem_set_usage( allocator_record *record_ptr )\r\n" -"{\r\n" -" int total_bytes_used;\r\n" -"\r\n" -" size_t n;\r\n" -" int32_t *ptr32;\r\n" -" char *ptr8;\r\n" -" size_t total_bytes;\r\n" -" int32_t fill_value;\r\n" -"\r\n" -" fill_value = MAGIC_VALUE_USED;\r\n" -" if ( ( record_ptr->params[0] ) == 'c' )\r\n" -" {\r\n" -" fill_value = 0x00000000;\r\n" -" }\r\n" -"\r\n" -" total_bytes = record_ptr->block_size;\r\n" -"\r\n" -" /* Check 4 bytes at a time */\r\n" -" ptr32 = (int32_t *) record_ptr->block_ptr;\r\n" -" total_bytes_used = 0;\r\n" -" for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- )\r\n" -" {\r\n" -" if ( *ptr32++ != fill_value )\r\n" -" {\r\n" -" total_bytes_used += sizeof( int32_t );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Check remaining bytes (If Applicable) 1 byte at a time */\r\n" -" ptr8 = (char *) ptr32;\r\n" -" for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- )\r\n" -" {\r\n" -" if ( *ptr8++ != (char) fill_value )\r\n" -" {\r\n" -" total_bytes_used++;\r\n" -" }\r\n" -"\r\n" -" /* Update Value */\r\n" -" fill_value >>= 8;\r\n" -" }\r\n" -"\r\n" -" return total_bytes_used;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * mem_check_OOB()\r\n" -" *\r\n" -" * Checks, if out-of-bounds access has occured. This is done by inspecting the 'signature' value\r\n" -" * taht has been added before and after the memory block during its allocation\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static unsigned int mem_check_OOB( allocator_record *record_ptr )\r\n" -"{\r\n" -" int32_t *ptr32;\r\n" -" unsigned int OOB_Flag = 0x0;\r\n" -" int32_t mask;\r\n" -" size_t i;\r\n" -" int f;\r\n" -"\r\n" -" ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS;\r\n" -"\r\n" -" /* Check the Signature at the Beginning of Memory Block */\r\n" -" i = N_32BITS_BLOCKS;\r\n" -" do\r\n" -" {\r\n" -" if ( *ptr32++ ^ MAGIC_VALUE_OOB )\r\n" -" {\r\n" -" OOB_Flag |= OOB_START;\r\n" -" }\r\n" -" } while ( --i );\r\n" -"\r\n" -" /* Advance to End (Snap to lowest 32 Bits) */\r\n" -" ptr32 += record_ptr->block_size / sizeof( int32_t );\r\n" -"\r\n" -" /* Calculate Unused Space That has been added to get to the rounded Block Size */\r\n" -" i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size;\r\n" -"\r\n" -" /* Partial Check of Signature at the End of Memory Block (for block size that has been rounded) */\r\n" -" f = i % sizeof( int32_t );\r\n" -" if ( f != 0 )\r\n" -" {\r\n" -" mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 );\r\n" -" if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask )\r\n" -" {\r\n" -" OOB_Flag |= OOB_END;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Full Check of Signature at the End of Memory Block, i.e. all 32 Bits (for the remainder after rounding) */\r\n" -" i /= sizeof( int32_t );\r\n" -" i += N_32BITS_BLOCKS;\r\n" -" do\r\n" -" {\r\n" -" if ( *ptr32++ ^ MAGIC_VALUE_OOB )\r\n" -" {\r\n" -" OOB_Flag |= OOB_END;\r\n" -" }\r\n" -" } while ( --i );\r\n" -"\r\n" -" return OOB_Flag;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * malloc_hash()\r\n" -" *\r\n" -" * Calculate hash from function name, line number and malloc size\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str )\r\n" -"{\r\n" -" unsigned long hash = 5381;\r\n" -" const char *ptr_str;\r\n" -"\r\n" -" ptr_str = func_name;\r\n" -" while ( ptr_str != NULL && *ptr_str != '\\0' )\r\n" -" {\r\n" -" hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */\r\n" -" }\r\n" -"\r\n" -" hash = ( ( hash << 5 ) + hash ) + func_lineno; /* hash * 33 + func_lineno */\r\n" -"\r\n" -" ptr_str = size_str;\r\n" -" while ( ptr_str != NULL && *ptr_str != '\\0' )\r\n" -" {\r\n" -" hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */\r\n" -" }\r\n" -"\r\n" -" return hash;\r\n" -"}\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * get_mem_record()\r\n" -" *\r\n" -" * Search for memory record in the internal list, return NULL if not found\r\n" -" * Start from index_record\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record )\r\n" -"{\r\n" -" int i;\r\n" -"\r\n" -" if ( *index_record < 0 || *index_record > Num_Records )\r\n" -" {\r\n" -" return NULL;\r\n" -" }\r\n" -"\r\n" -" /* calculate hash */\r\n" -" *hash = malloc_hash( func_name, func_lineno, size_str );\r\n" -"\r\n" -" for ( i = *index_record; i < Num_Records; i++ )\r\n" -" {\r\n" -" /* check, if memory block is not allocated at the moment and the hash matches */\r\n" -" if ( allocation_list[i].block_ptr == NULL && *hash == allocation_list[i].hash )\r\n" -" {\r\n" -" *index_record = i;\r\n" -" return &( allocation_list[i] );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* not found */\r\n" -" *index_record = -1;\r\n" -" return NULL;\r\n" -"}\r\n" -"\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * mem_free()\r\n" -" *\r\n" -" * This function de-allocates memory blocks and frees physical memory with free().\r\n" -" * It also updates the actual and average usage of memory blocks.\r\n" -" *\r\n" -" * Note: The record is not removed from the list and may be reused later on in mem_alloc()!\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void mem_free( const char *func_name, int func_lineno, void *ptr )\r\n" -"{\r\n" -" int i, index_record;\r\n" -" char *tmp_ptr;\r\n" -" allocator_record *ptr_record;\r\n" -"\r\n" -" /* Search for the Block Pointer in the List */\r\n" -" ptr_record = NULL;\r\n" -" index_record = -1;\r\n" -" for ( i = 0; i < Num_Records; i++ )\r\n" -" {\r\n" -" if ( ptr == allocation_list[i].block_ptr )\r\n" -" { /* Yes, Found it */\r\n" -" ptr_record = &( allocation_list[i] );\r\n" -" index_record = i;\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" if ( ptr_record == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Unable to Find Record Corresponding to the Allocated Memory Block!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* Update the Heap Size */\r\n" -" current_heap_size -= ptr_record->block_size;\r\n" -"\r\n" -" /* Calculate the Actual Usage of the Memory Block (Look for Signature) */\r\n" -" ptr_record->total_used_size += mem_set_usage( ptr_record );\r\n" -"\r\n" -" /* Check, if Out-Of-Bounds Access has been Detected */\r\n" -" ptr_record->OOB_Flag = mem_check_OOB( ptr_record );\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -" /* Export heap memory de-allocation record to the .csv file */\r\n" -" fprintf( fid_csv_filename, \"D,%ld,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n" -"#endif\r\n" -"\r\n" -" /* De-Allocate Memory Block */\r\n" -" tmp_ptr = (char *) ptr;\r\n" -" tmp_ptr -= BLOCK_ROUNDING;\r\n" -" ptr = (void *) tmp_ptr;\r\n" -" free( ptr );\r\n" -"\r\n" -" /* Add new entry to the heap allocation call tree */\r\n" -" if ( heap_allocation_call_tree == NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Error: Heap allocation call tree not created!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" /* check, if the maximum size of the call tree has been reached -> resize if so */\r\n" -" if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size )\r\n" -" {\r\n" -" heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" heap_allocation_call_tree[heap_allocation_call_tree_size++] = -index_record;\r\n" -"\r\n" -" /* Reset memory block pointer (this is checked when updating wc intra-frame and inter-frame memory) */\r\n" -" ptr_record->block_ptr = NULL;\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * update_mem()\r\n" -" *\r\n" -" * This function updates the worst-case intra-frame memory and the worst-case inter-frame memory.\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void update_mem( void )\r\n" -"{\r\n" -" int i, j, flag_alloc = -1, i_record;\r\n" -" int size_current_intra_frame_heap;\r\n" -" int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap;\r\n" -" allocator_record *ptr_record;\r\n" -"\r\n" -" /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */\r\n" -" n_items_current_intra_frame_heap = 0;\r\n" -" size_current_intra_frame_heap = 0;\r\n" -" for ( i = 0; i < heap_allocation_call_tree_size; i++ )\r\n" -" {\r\n" -" /* get the record */\r\n" -" i_record = heap_allocation_call_tree[i];\r\n" -"\r\n" -" if ( i_record > 0 )\r\n" -" {\r\n" -" flag_alloc = 1;\r\n" -" }\r\n" -" else if ( i_record < 0 )\r\n" -" {\r\n" -" flag_alloc = 0;\r\n" -" i_record = -i_record;\r\n" -" }\r\n" -" ptr_record = &( allocation_list[i_record] );\r\n" -"\r\n" -" if ( ptr_record->frame_allocated == update_cnt && ptr_record->block_ptr == NULL )\r\n" -" {\r\n" -" /* intra-frame heap memory */\r\n" -" if ( list_current_intra_frame_heap == NULL )\r\n" -" {\r\n" -" list_current_intra_frame_heap = (int *) malloc( heap_allocation_call_tree_size * sizeof( int ) );\r\n" -" memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n" -" if ( i_record == 0 )\r\n" -" {\r\n" -" flag_alloc = 1;\r\n" -" for ( j = 0; j < n_items_current_intra_frame_heap; j++ )\r\n" -" {\r\n" -" if ( list_current_intra_frame_heap[j] == i_record )\r\n" -" {\r\n" -" flag_alloc = 0;\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" if ( flag_alloc )\r\n" -" {\r\n" -" /* add to list */\r\n" -" list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record;\r\n" -" size_current_intra_frame_heap += ptr_record->block_size;\r\n" -"\r\n" -" /* no need to re-size the list -> the initially allocated size should be large enough */\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" /* remove from list */\r\n" -" for ( j = 0; j < n_items_current_intra_frame_heap; j++ )\r\n" -" {\r\n" -" if ( list_current_intra_frame_heap[j] == i_record )\r\n" -" {\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -" memmove( &list_current_intra_frame_heap[j], &list_current_intra_frame_heap[j + 1], ( n_items_current_intra_frame_heap - j ) * sizeof( int ) );\r\n" -" n_items_current_intra_frame_heap--;\r\n" -" size_current_intra_frame_heap -= ptr_record->block_size;\r\n" -"\r\n" -" /* reset block size */\r\n" -" ptr_record->frame_allocated = -1;\r\n" -" ptr_record->block_size = 0;\r\n" -" }\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" /* inter-frame heap memory */\r\n" -"\r\n" -" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n" -" if ( i_record == 0 )\r\n" -" {\r\n" -" flag_alloc = 1;\r\n" -" for ( j = 0; j < n_items_current_inter_frame_heap; j++ )\r\n" -" {\r\n" -" if ( list_current_inter_frame_heap[j] == i_record )\r\n" -" {\r\n" -" flag_alloc = 0;\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" if ( flag_alloc )\r\n" -" {\r\n" -" /* add to list */\r\n" -" if ( n_items_current_inter_frame_heap >= max_items_current_inter_frame_heap )\r\n" -" {\r\n" -" /* resize list, if needed */\r\n" -" max_items_current_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" list_current_inter_frame_heap = realloc( list_current_inter_frame_heap, max_items_current_inter_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record;\r\n" -" size_current_inter_frame_heap += ptr_record->block_size;\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" /* remove from list */\r\n" -" for ( j = 0; j < n_items_current_inter_frame_heap; j++ )\r\n" -" {\r\n" -" if ( list_current_inter_frame_heap[j] == i_record )\r\n" -" {\r\n" -" break;\r\n" -" }\r\n" -" }\r\n" -" memmove( &list_current_inter_frame_heap[j], &list_current_inter_frame_heap[j + 1], ( n_items_current_inter_frame_heap - j ) * sizeof( int ) );\r\n" -" n_items_current_inter_frame_heap--;\r\n" -" size_current_inter_frame_heap -= ptr_record->block_size;\r\n" -"\r\n" -" /* reset block size */\r\n" -" ptr_record->frame_allocated = -1;\r\n" -" ptr_record->block_size = 0;\r\n" -" }\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* check, if this is the new worst-case for intra-frame heap memory */\r\n" -" if ( size_current_intra_frame_heap > size_wc_intra_frame_heap )\r\n" -" {\r\n" -" if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap )\r\n" -" {\r\n" -" /* resize the list, if needed */\r\n" -" max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" /* copy current-frame list to worst-case list */\r\n" -" memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) );\r\n" -" n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap;\r\n" -" size_wc_intra_frame_heap = size_current_intra_frame_heap;\r\n" -" location_wc_intra_frame_heap = update_cnt;\r\n" -"\r\n" -" /* update the wc numbers in all individual records */\r\n" -" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n" -" {\r\n" -" i_record = list_wc_intra_frame_heap[i];\r\n" -" ptr_record = &( allocation_list[i_record] );\r\n" -" ptr_record->wc_heap_size_intra_frame = ptr_record->block_size;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* check, if this is the new worst-case for inter-frame heap memory */\r\n" -" if ( size_current_inter_frame_heap > size_wc_inter_frame_heap )\r\n" -" {\r\n" -" if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap )\r\n" -" {\r\n" -" /* resize list, if needed */\r\n" -" max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n" -" list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n" -" }\r\n" -"\r\n" -" /* copy current-frame list to worst-case list */\r\n" -" memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) );\r\n" -" n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap;\r\n" -" size_wc_inter_frame_heap = size_current_inter_frame_heap;\r\n" -" location_wc_inter_frame_heap = update_cnt;\r\n" -"\r\n" -" /* update the wc numbers in all individual records */\r\n" -" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n" -" {\r\n" -" i_record = list_wc_inter_frame_heap[i];\r\n" -" ptr_record = &( allocation_list[i_record] );\r\n" -" ptr_record->wc_heap_size_inter_frame = ptr_record->block_size;\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* reset heap allocation call tree */\r\n" -" heap_allocation_call_tree_size = 0;\r\n" -"\r\n" -" /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */\r\n" -" if ( list_current_intra_frame_heap )\r\n" -" {\r\n" -" free( list_current_intra_frame_heap );\r\n" -" }\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * subst()\r\n" -" *\r\n" -" * Substitute character in string\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static void subst( char *s, char from, char to )\r\n" -"{\r\n" -" while ( *s == from )\r\n" -" {\r\n" -" *s++ = to;\r\n" -" }\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * mem_count_summary()\r\n" -" *\r\n" -" * Print detailed (per-item) information about heap memory usage\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"static void mem_count_summary( void )\r\n" -"{\r\n" -" int i, j, index, index_record;\r\n" -" size_t length;\r\n" -" char buf[300], format_str[50], name_str[MAX_FUNCTION_NAME_LENGTH + 3], parms_str[MAX_PARAMS_LENGTH + 1], type_str[10], usage_str[20], size_str[20], line_str[10];\r\n" -" allocator_record *ptr_record, *ptr;\r\n" -"\r\n" -" /* Prepare format string */\r\n" -" sprintf( format_str, \"%%-%d.%ds %%5.5s %%6.6s %%-%d.%ds %%20.20s %%6.6s \", 50, 50, 50, 50 );\r\n" -"\r\n" -" if ( n_items_wc_intra_frame_heap > 0 )\r\n" -" {\r\n" -" /* Intra-Frame Heap Size */\r\n" -" fprintf( stdout, \"\\nList of memory blocks when maximum intra-frame heap size is reached:\\n\\n\" );\r\n" -"\r\n" -" /* Find duplicate records (same hash and worst-case heap size) */\r\n" -" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n" -" {\r\n" -" index_record = list_wc_intra_frame_heap[i];\r\n" -" if ( index_record == -1 )\r\n" -" {\r\n" -" continue;\r\n" -" }\r\n" -"\r\n" -" ptr_record = &( allocation_list[index_record] );\r\n" -" for ( j = i + 1; j < n_items_wc_intra_frame_heap; j++ )\r\n" -" {\r\n" -" index = list_wc_intra_frame_heap[j];\r\n" -" if ( index == -1 )\r\n" -" {\r\n" -" continue;\r\n" -" }\r\n" -" ptr = &( allocation_list[index] );\r\n" -"\r\n" -" if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_intra_frame == ptr_record->wc_heap_size_intra_frame )\r\n" -" {\r\n" -" ptr_record->noccurances++;\r\n" -" list_wc_intra_frame_heap[j] = -1;\r\n" -" }\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Print Header */\r\n" -" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Maximum Size\", \"Usage\" );\r\n" -" puts( buf );\r\n" -" length = strlen( buf );\r\n" -" sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n" -" subst( buf, '0', '-' );\r\n" -" puts( buf );\r\n" -"\r\n" -" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n" -" {\r\n" -" index_record = list_wc_intra_frame_heap[i];\r\n" -"\r\n" -" if ( index_record != -1 )\r\n" -" {\r\n" -" /* get the record */\r\n" -" ptr_record = &( allocation_list[index_record] );\r\n" -"\r\n" -" /* prepare information strings */\r\n" -" strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH );\r\n" -" strcat( name_str, \"()\" );\r\n" -" name_str[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n" -" strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH );\r\n" -" parms_str[MAX_PARAMS_LENGTH] = '\\0';\r\n" -"\r\n" -" if ( ptr_record->params[0] == 'm' )\r\n" -" {\r\n" -" strcpy( type_str, \"malloc\" );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" strcpy( type_str, \"calloc\" );\r\n" -" }\r\n" -"\r\n" -" sprintf( line_str, \"%d\", ptr_record->lineno );\r\n" -"\r\n" -" /* prepare average usage & memory size strings */\r\n" -" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) );\r\n" -"\r\n" -" if ( ptr_record->noccurances > 1 )\r\n" -" {\r\n" -" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" sprintf( size_str, \"%d %s\", (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -"\r\n" -" sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str );\r\n" -" puts( buf );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, \"\\n\" );\r\n" -" }\r\n" -"\r\n" -" if ( n_items_wc_inter_frame_heap > 0 )\r\n" -" {\r\n" -" /* Inter-Frame Heap Size */\r\n" -" fprintf( stdout, \"\\nList of memory blocks when maximum inter-frame heap size is reached:\\n\\n\" );\r\n" -"\r\n" -" /* Find duplicate records (same hash and worst-case heap size) */\r\n" -" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n" -" {\r\n" -" index_record = list_wc_inter_frame_heap[i];\r\n" -" if ( index_record == -1 )\r\n" -" {\r\n" -" continue;\r\n" -" }\r\n" -" ptr_record = &( allocation_list[index_record] );\r\n" -" ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */\r\n" -" for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ )\r\n" -" {\r\n" -" index = list_wc_inter_frame_heap[j];\r\n" -" if ( index == -1 )\r\n" -" {\r\n" -" continue;\r\n" -" }\r\n" -" ptr = &( allocation_list[index] );\r\n" -"\r\n" -" if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_inter_frame == ptr_record->wc_heap_size_inter_frame )\r\n" -" {\r\n" -" ptr_record->noccurances++;\r\n" -" list_wc_inter_frame_heap[j] = -1;\r\n" -" }\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" /* Print Header */\r\n" -" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Memory Size\", \"Usage\" );\r\n" -" puts( buf );\r\n" -" length = strlen( buf );\r\n" -" sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n" -" subst( buf, '0', '-' );\r\n" -" puts( buf );\r\n" -"\r\n" -" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n" -" {\r\n" -" index_record = list_wc_inter_frame_heap[i];\r\n" -"\r\n" -" if ( index_record != -1 )\r\n" -" {\r\n" -" /* get the record */\r\n" -" ptr_record = &( allocation_list[index_record] );\r\n" -"\r\n" -" /* prepare information strings */\r\n" -" strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH );\r\n" -" strcat( name_str, \"()\" );\r\n" -" name_str[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n" -" strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH );\r\n" -" parms_str[MAX_PARAMS_LENGTH] = '\\0';\r\n" -"\r\n" -" if ( ptr_record->params[0] == 'm' )\r\n" -" {\r\n" -" strcpy( type_str, \"malloc\" );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" strcpy( type_str, \"calloc\" );\r\n" -" }\r\n" -"\r\n" -" sprintf( line_str, \"%d\", ptr_record->lineno );\r\n" -"\r\n" -" /* prepare average usage & memory size strings */\r\n" -" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) );\r\n" -"\r\n" -" if ( ptr_record->noccurances > 1 )\r\n" -" {\r\n" -" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" sprintf( size_str, \"%d %s\", (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -"\r\n" -" sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str );\r\n" -" puts( buf );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, \"\\n\" );\r\n" -" }\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * print_mem()\r\n" -" *\r\n" -" * Print information about ROM and RAM memory usage\r\n" -" *--------------------------------------------------------------------*/\r\n" -"\r\n" -"void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] )\r\n" -"{\r\n" -" int i, nElem;\r\n" -"\r\n" -" fprintf( stdout, \"\\n\\n --- Memory usage --- \\n\\n\" );\r\n" -"\r\n" -" if ( Const_Data_PROM_Table != NULL )\r\n" -" {\r\n" -" nElem = 0;\r\n" -" while ( strcmp( Const_Data_PROM_Table[nElem].file_spec, \"\" ) != 0 )\r\n" -" nElem++;\r\n" -"\r\n" -" for ( i = 0; i < nElem; i++ )\r\n" -" {\r\n" -" if ( Stat_Cnt_Size > 0 )\r\n" -" {\r\n" -" /* words */\r\n" -" fprintf( stdout, \"Program ROM size (%s): %d words\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" /* bytes (here, we assume that each instruction takes PROM_INST_SIZE bits of the PROM memory) */\r\n" -" fprintf( stdout, \"Program ROM size (%s): %d bytes\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size * ( PROM_INST_SIZE / 8 ) );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" for ( i = 0; i < nElem; i++ )\r\n" -" {\r\n" -" if ( Const_Data_PROM_Table[i].Get_Const_Data_Size_Func == NULL )\r\n" -" {\r\n" -" fprintf( stdout, \"Error: Cannot retrieve or calculate Table ROM size of (%s)!\\n\", Const_Data_PROM_Table[i].file_spec );\r\n" -" }\r\n" -"\r\n" -" fprintf( stdout, \"Table ROM (const data) size (%s): %d %s\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].Get_Const_Data_Size_Func() >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n" -" }\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" fprintf( stdout, \"Program ROM size: not available\\n\" );\r\n" -" fprintf( stdout, \"Table ROM (const data) size: not available\\n\" );\r\n" -" }\r\n" -"\r\n" -" if ( wc_ram_size > 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum RAM (stack + heap) size: %d %s in frame %d\\n\", wc_ram_size >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], wc_ram_frame );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum RAM (stack + heap) size: not available\\n\" );\r\n" -" }\r\n" -"\r\n" -" /* check, if the stack is empty */\r\n" -" if ( ptr_current_stack != ptr_base_stack )\r\n" -" {\r\n" -" fprintf( stderr, \"Warning: Stack is not empty.\\n\" );\r\n" -" }\r\n" -"\r\n" -" if ( ptr_base_stack - ptr_max_stack > 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum stack size: %lu %s in frame %d\\n\", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size],\r\n" -" wc_stack_frame );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum stack size: not available\\n\" );\r\n" -" }\r\n" -"\r\n" -" /* last update of intra-frame memory and inter-frame memory, if needed */\r\n" -" if ( heap_allocation_call_tree_size > 0 )\r\n" -" {\r\n" -" update_mem();\r\n" -" }\r\n" -"\r\n" -" /* check, if all memory blocks have been deallocated (freed) */\r\n" -" for ( i = 0; i < Num_Records; i++ )\r\n" -" {\r\n" -" if ( allocation_list[i].block_ptr != NULL )\r\n" -" {\r\n" -" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", allocation_list[i].name, allocation_list[i].lineno, \"Error: Memory Block has not been De-Allocated with free()!\" );\r\n" -" exit( -1 );\r\n" -" }\r\n" -" }\r\n" -"\r\n" -" if ( n_items_wc_intra_frame_heap > 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum intra-frame heap size: %d %s in frame %d\\n\", size_wc_intra_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_intra_frame_heap );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum intra-frame heap size: 0\\n\" );\r\n" -" }\r\n" -"\r\n" -" if ( n_items_wc_inter_frame_heap > 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum inter-frame heap size: %d %s in frame %d\\n\", size_wc_inter_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_inter_frame_heap );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" fprintf( stdout, \"Maximum inter-frame heap size: 0\\n\" );\r\n" -" }\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -" /* Print detailed information about worst-case stack usage */\r\n" -" if ( ptr_base_stack - ptr_max_stack > 0 )\r\n" -" {\r\n" -" print_stack_call_tree();\r\n" -" }\r\n" -"\r\n" -" /* Print detailed information about worst-case heap usage */\r\n" -" mem_count_summary();\r\n" -"#endif\r\n" -"\r\n" -" if ( Stat_Cnt_Size > 0 )\r\n" -" {\r\n" -" /* words */\r\n" -" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", 8 << Stat_Cnt_Size );\r\n" -" }\r\n" -" else\r\n" -" {\r\n" -" /* bytes */\r\n" -" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", PROM_INST_SIZE );\r\n" -" }\r\n" -" fprintf( stdout, \"Note: The Data ROM size is calculated using the sizeof(type) built-in function\\n\" );\r\n" -"\r\n" -" if ( n_items_wc_intra_frame_heap > 0 )\r\n" -" {\r\n" -" fprintf( stdout, \"Intra-frame heap memory is allocated and de-allocated in the same frame\\n\" );\r\n" -" }\r\n" -"\r\n" -" /* De-allocate list of heap memory blocks */\r\n" -" if ( allocation_list != NULL )\r\n" -" {\r\n" -" free( allocation_list );\r\n" -" }\r\n" -"\r\n" -" /* De-allocate list of stack records */\r\n" -" if ( stack_callers[0] != NULL )\r\n" -" {\r\n" -" free( stack_callers[0] );\r\n" -" }\r\n" -"\r\n" -" if ( stack_callers[1] != NULL )\r\n" -" {\r\n" -" free( stack_callers[1] );\r\n" -" }\r\n" -"\r\n" -" /* De-allocate heap allocation call tree */\r\n" -" if ( heap_allocation_call_tree != NULL )\r\n" -" {\r\n" -" free( heap_allocation_call_tree );\r\n" -" }\r\n" -"\r\n" -" /* De-allocate intra-frame and inter-frame heap lists */\r\n" -" if ( list_wc_intra_frame_heap != NULL )\r\n" -" {\r\n" -" free( list_wc_intra_frame_heap );\r\n" -" }\r\n" -"\r\n" -" if ( list_current_inter_frame_heap != NULL )\r\n" -" {\r\n" -" free( list_current_inter_frame_heap );\r\n" -" }\r\n" -"\r\n" -" if ( list_wc_inter_frame_heap != NULL )\r\n" -" {\r\n" -" free( list_wc_inter_frame_heap );\r\n" -" }\r\n" -"\r\n" -"#ifdef MEM_COUNT_DETAILS\r\n" -" if ( fid_csv_filename != NULL )\r\n" -" {\r\n" -" fclose( fid_csv_filename );\r\n" -" }\r\n" -"#endif\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"#endif /* WMOPS */\r\n" -"\r\n" -"#ifdef CONTROL_CODE_OPS\r\n" -"\r\n" -"int LT_16( short var1, short var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( var1 < var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].LT_16++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int GT_16( short var1, short var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( var1 > var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].GT_16++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int LE_16( short var1, short var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( var1 <= var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].LE_16++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int GE_16( short var1, short var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( var1 >= var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].GE_16++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int EQ_16( short var1, short var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( var1 == var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].EQ_16++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int NE_16( short var1, short var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( var1 != var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].NE_16++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int LT_32( int L_var1, int L_var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( L_var1 < L_var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].LT_32++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int GT_32( int L_var1, int L_var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( L_var1 > L_var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].GT_32++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int LE_32( int L_var1, int L_var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( L_var1 <= L_var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].LE_32++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int GE_32( int L_var1, int L_var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( L_var1 >= L_var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].GE_32++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int EQ_32( int L_var1, int L_var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( L_var1 == L_var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].EQ_32++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int NE_32( int L_var1, int L_var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( L_var1 != L_var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].NE_32++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int LT_64( long long int L64_var1, long long int L64_var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( L64_var1 < L64_var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].LT_64++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int GT_64( long long int L64_var1, long long int L64_var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( L64_var1 > L64_var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].GT_64++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int LE_64( long long int L64_var1, long long int L64_var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( L64_var1 <= L64_var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].LE_64++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"int GE_64( long long int L64_var1, long long int L64_var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( L64_var1 >= L64_var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].GE_64++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"int EQ_64( long long int L64_var1, long long int L64_var2 )\r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( L64_var1 == L64_var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].EQ_64++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"int NE_64( long long int L64_var1, long long int L64_var2 ) \r\n" -"{\r\n" -" int F_ret = 0;\r\n" -"\r\n" -" if ( L64_var1 != L64_var2 )\r\n" -" {\r\n" -" F_ret = 1;\r\n" -" }\r\n" -"#ifdef WMOPS\r\n" -" multiCounter[currCounter].NE_64++;\r\n" -"#endif\r\n" -" return F_ret;\r\n" -"}\r\n" -"\r\n" -"#endif /* #ifdef CONTROL_CODE_OPS */\r\n" -"\r\n" -"#ifdef WMOPS\r\n" -"\r\n" -"void incrIf( const char *func_name )\r\n" -"{\r\n" -" /* Technical note: If the \"IF\" operator comes just after an \"ELSE\", its counter must not be incremented */\r\n" -" /* The following auxiliary variables are used to check if the \"IF\" operator doesn't immediately follow an \"ELSE\" operator */\r\n" -" if ( ( (int) currCounter != funcId_where_last_call_to_else_occurred ) || ( strncmp( func_name, func_name_where_last_call_to_else_occurred, MAX_FUNCTION_NAME_LENGTH ) != 0 ) || ( TotalWeightedOperation( currCounter) != funcid_total_wmops_at_last_call_to_else ) || ( call_occurred == 1 ) )\r\n" -" multiCounter[currCounter].If++;\r\n" -"\r\n" -" call_occurred = 0;\r\n" -" funcId_where_last_call_to_else_occurred = -100;\r\n" -"}\r\n" -"\r\n" -"void incrElse( const char *func_name )\r\n" -"{\r\n" -" multiCounter[currCounter].If++;\r\n" -"\r\n" -" /* Save the BASOP counter Id in the last function in which ELSE() has been called */\r\n" -" funcId_where_last_call_to_else_occurred = currCounter;\r\n" -"\r\n" -" /* Save the BASOP comeplxity in the last call of the ELSE() statement */\r\n" -" funcid_total_wmops_at_last_call_to_else = TotalWeightedOperation( currCounter );\r\n" -"\r\n" -" /* Save the function name in the last call of the ELSE() statement */\r\n" -" strncpy( func_name_where_last_call_to_else_occurred, func_name, MAX_FUNCTION_NAME_LENGTH );\r\n" -" func_name_where_last_call_to_else_occurred[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n" -"\r\n" -" /* Set call_occurred to 0 to prevent counting of complexity of the next \"immediate\" IF statement */\r\n" -" call_occurred = 0;\r\n" -"}\r\n" -"\r\n" -"long TotalWeightedOperation( unsigned int CounterId )\r\n" -"{\r\n" -" int i;\r\n" -" unsigned int *ptr, *ptr2;\r\n" -" long tot;\r\n" -"\r\n" -" tot = 0;\r\n" -" ptr = (unsigned int *) &multiCounter[CounterId];\r\n" -" ptr2 = (unsigned int *) &op_weight;\r\n" -"\r\n" -" for ( i = 0; i < (int) ( sizeof( multiCounter[CounterId] ) / sizeof( unsigned int ) ); i++ )\r\n" -" {\r\n" -" if ( *ptr == UINT_MAX )\r\n" -" {\r\n" -" printf( \"\\nError in BASOP complexity counters: multiCounter[%d][%d] = %d !!!\\n\", CounterId, i, *ptr );\r\n" -" exit( -1 );\r\n" -" }\r\n" -"\r\n" -" tot += ( ( *ptr++ ) * ( *ptr2++ ) );\r\n" -" }\r\n" -"\r\n" -" return ( tot );\r\n" -"}\r\n" -"\r\n" -"long DeltaWeightedOperation( unsigned int CounterId )\r\n" -"{\r\n" -" long NewWOper, delta;\r\n" -"\r\n" -" NewWOper = TotalWeightedOperation( CounterId );\r\n" -"\r\n" -" delta = NewWOper - wmops[CounterId].LastWOper;\r\n" -" wmops[CounterId].LastWOper = NewWOper;\r\n" -"\r\n" -" return ( delta );\r\n" -"}\r\n" -"\r\n" -"/* Resets BASOP operation counter */\r\n" -"void Reset_BASOP_WMOPS_counter( unsigned int counterId )\r\n" -"{\r\n" -" int i;\r\n" -" long *ptr;\r\n" -"\r\n" -" /* reset the current BASOP operation counter */\r\n" -" ptr = (long *) &multiCounter[counterId];\r\n" -" for ( i = 0; i < (int) ( sizeof( multiCounter[counterId] ) / sizeof( long ) ); i++ )\r\n" -" {\r\n" -" *ptr++ = 0;\r\n" -" }\r\n" -"\r\n" -" wmops[counterId].LastWOper = 0;\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"#endif\r\n" \ No newline at end of file +"/*\r\n", +" * (C) 2024 copyright VoiceAge Corporation. All Rights Reserved.\r\n", +" *\r\n", +" * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n", +" * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n", +" * or refer to ITU-T Recommendation G.191 on \"SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS\".\r\n", +" *\r\n", +" * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor\r\n", +" * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software\r\n", +" * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE.\r\n", +" *\r\n", +" * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca)\r\n", +" */\r\n", +"\r\n", +"#include \r\n", +"#include \r\n", +"#include \r\n", +"#include \r\n", +"#include \r\n", +"#include \r\n", +"#include \r\n", +"\r\n", +"#ifndef _MSC_VER\r\n", +"#include \r\n", +"#include \r\n", +"#else\r\n", +"#include \r\n", +"#endif\r\n", +"\r\n", +"#include \"wmc_auto.h\"\r\n", +"\r\n", +"#define WMC_TOOL_SKIP /* Skip the instrumentation of this file, if invoked by accident */\r\n", +"\r\n", +"#ifndef WMOPS\r\n", +"int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_wmops() pairs when WMOPS is not activated */\r\n", +"#endif\r\n", +"\r\n", +"#ifdef WMOPS\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * Complexity counting tool\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"\r\n", +"#define MAX_FUNCTION_NAME_LENGTH 200 /* Maximum length of the function name */\r\n", +"#define MAX_PARAMS_LENGTH 200 /* Maximum length of the function parameter string */\r\n", +"#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> might be increased during runtime, if needed */\r\n", +"#define MAX_NUM_RECORDS_REALLOC_STEP 50 /* When re-allocating the list of records, increase the number of records by this number */\r\n", +"#define MAX_CALL_TREE_DEPTH 100 /* maximum depth of the function call tree */\r\n", +"#define DOUBLE_MAX 0x80000000\r\n", +"#define FAC ( FRAMES_PER_SECOND / 1e6 )\r\n", +"\r\n", +"#define FRAMES_PER_SECOND 50.0\r\n", +"#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */\r\n", +"\r\n", +"typedef struct\r\n", +"{\r\n", +" char label[MAX_FUNCTION_NAME_LENGTH];\r\n", +" long call_number;\r\n", +" long update_cnt;\r\n", +" int call_tree[MAX_CALL_TREE_DEPTH];\r\n", +" long LastWOper;\r\n", +" double start_selfcnt;\r\n", +" double current_selfcnt;\r\n", +" double max_selfcnt;\r\n", +" double min_selfcnt;\r\n", +" double tot_selfcnt;\r\n", +" double start_cnt; /* The following take into account the decendants */\r\n", +" double current_cnt;\r\n", +" double max_cnt;\r\n", +" double min_cnt;\r\n", +" double tot_cnt;\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" int32_t current_call_number;\r\n", +" double wc_cnt;\r\n", +" double wc_selfcnt;\r\n", +" int32_t wc_call_number;\r\n", +"#endif\r\n", +"} wmops_record;\r\n", +"\r\n", +"double ops_cnt;\r\n", +"double inst_cnt[NUM_INST];\r\n", +"\r\n", +"static wmops_record *wmops = NULL;\r\n", +"static int num_wmops_records, max_num_wmops_records;\r\n", +"static int current_record;\r\n", +"static long update_cnt;\r\n", +"static double start_cnt;\r\n", +"static double max_cnt;\r\n", +"static double min_cnt;\r\n", +"static double inst_cnt_wc[NUM_INST];\r\n", +"static long fnum_cnt_wc;\r\n", +"static int *wmops_caller_stack = NULL, wmops_caller_stack_index, max_wmops_caller_stack_index = 0;\r\n", +"static int *heap_allocation_call_tree = NULL, heap_allocation_call_tree_size = 0, heap_allocation_call_tree_max_size = 0;\r\n", +"\r\n", +"static BASIC_OP op_weight = {\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 2, 2, 1,\r\n", +" 1, 1, 1, 2, 1,\r\n", +"\r\n", +" 1, 1, 1, 2, 1,\r\n", +" 1, 1, 18, 1, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 2, 2, 2, 2, 1,\r\n", +"\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 1, 2,\r\n", +" 1, 2, 2, 2, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +"\r\n", +" 1, 1, 1, 1, 3,\r\n", +" 3, 3, 3, 1, 1,\r\n", +" 1, 1, 1, 1, 1,\r\n", +" 1, 1, 1, 3, 2,\r\n", +" 2, 6, 3, 3, 2,\r\n", +"\r\n", +" 1, 32, 1\r\n", +"\r\n", +"/* New complex basops */\r\n", +"#ifdef COMPLEX_OPERATOR\r\n", +" ,\r\n", +" 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1\r\n", +"\r\n", +" ,\r\n", +" 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1\r\n", +"\r\n", +"#endif /* #ifdef COMPLEX_OPERATOR */\r\n", +"\r\n", +"#ifdef ENH_64_BIT_OPERATOR\r\n", +" /* Weights of new 64 bit basops */\r\n", +" ,\r\n", +" 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\r\n", +"#endif /* #ifdef ENH_64_BIT_OPERATOR */\r\n", +"\r\n", +"#ifdef ENH_32_BIT_OPERATOR\r\n", +" ,\r\n", +" 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\r\n", +"#endif /* #ifdef ENH_32_BIT_OPERATOR */\r\n", +"\r\n", +"#ifdef ENH_U_32_BIT_OPERATOR\r\n", +" ,\r\n", +" 1, 1, 1, 2, 2, 1, 1\r\n", +"#endif /* #ifdef ENH_U_32_BIT_OPERATOR */\r\n", +"\r\n", +"#ifdef CONTROL_CODE_OPS\r\n", +" ,\r\n", +" 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1\r\n", +"#endif /* #ifdef CONTROL_CODE_OPS */\r\n", +"};\r\n", +"\r\n", +"BASIC_OP *multiCounter = NULL;\r\n", +"unsigned int currCounter = 0;\r\n", +"int funcId_where_last_call_to_else_occurred;\r\n", +"long funcid_total_wmops_at_last_call_to_else;\r\n", +"int call_occurred = 1;\r\n", +"char func_name_where_last_call_to_else_occurred[MAX_FUNCTION_NAME_LENGTH + 1];\r\n", +"\r\n", +"void reset_wmops( void )\r\n", +"{\r\n", +" int i, j;\r\n", +"\r\n", +" num_wmops_records = 0;\r\n", +" max_num_wmops_records = MAX_NUM_RECORDS;\r\n", +" current_record = -1;\r\n", +" update_cnt = 0;\r\n", +"\r\n", +" max_cnt = 0.0;\r\n", +" min_cnt = DOUBLE_MAX;\r\n", +" start_cnt = 0.0;\r\n", +" ops_cnt = 0.0;\r\n", +"\r\n", +" /* allocate the list of WMOPS records */\r\n", +" if ( wmops == NULL )\r\n", +" {\r\n", +" wmops = (wmops_record *) malloc( max_num_wmops_records * sizeof( wmops_record ) );\r\n", +" }\r\n", +"\r\n", +" if ( wmops == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Records!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* allocate the list of BASOP WMOPS records */\r\n", +" if ( multiCounter == NULL )\r\n", +" {\r\n", +" multiCounter = (BASIC_OP *) malloc( max_num_wmops_records * sizeof( BASIC_OP ) );\r\n", +" }\r\n", +"\r\n", +" if ( multiCounter == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Unable to Allocate the BASOP WMOPS counter!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* initilize the list of WMOPS records */\r\n", +" /* initilize BASOP operation counters */\r\n", +" for ( i = 0; i < max_num_wmops_records; i++ )\r\n", +" {\r\n", +" strcpy( &wmops[i].label[0], \"\\0\" );\r\n", +" wmops[i].call_number = 0;\r\n", +" wmops[i].update_cnt = 0;\r\n", +" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n", +" {\r\n", +" wmops[i].call_tree[j] = -1;\r\n", +" }\r\n", +" wmops[i].start_selfcnt = 0.0;\r\n", +" wmops[i].current_selfcnt = 0.0;\r\n", +" wmops[i].max_selfcnt = 0.0;\r\n", +" wmops[i].min_selfcnt = DOUBLE_MAX;\r\n", +" wmops[i].tot_selfcnt = 0.0;\r\n", +" wmops[i].start_cnt = 0.0;\r\n", +" wmops[i].current_cnt = 0.0;\r\n", +" wmops[i].max_cnt = 0.0;\r\n", +" wmops[i].min_cnt = DOUBLE_MAX;\r\n", +" wmops[i].tot_cnt = 0.0;\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" wmops[i].wc_cnt = 0.0;\r\n", +" wmops[i].wc_selfcnt = 0.0;\r\n", +" wmops[i].current_call_number = 0;\r\n", +" wmops[i].wc_call_number = -1;\r\n", +"#endif\r\n", +"\r\n", +" /* Reset BASOP operation counter */\r\n", +" Reset_BASOP_WMOPS_counter( i );\r\n", +" }\r\n", +"\r\n", +" /* allocate the list of wmops callers to track the sequence of function calls */\r\n", +" wmops_caller_stack_index = 0;\r\n", +" max_wmops_caller_stack_index = MAX_NUM_RECORDS;\r\n", +" if ( wmops_caller_stack == NULL )\r\n", +" {\r\n", +" wmops_caller_stack = malloc( max_wmops_caller_stack_index * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" if ( wmops_caller_stack == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Unable to Allocate List of WMOPS Callers!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" for ( i = 0; i < max_wmops_caller_stack_index; i++ )\r\n", +" {\r\n", +" wmops_caller_stack[i] = -1;\r\n", +" }\r\n", +"\r\n", +" /* initialize auxiliary BASOP counter variables */\r\n", +" currCounter = 0; /* Note: currCounter cannot be set to -1 because it's defined as unsigned int ! */\r\n", +" call_occurred = 1;\r\n", +" funcId_where_last_call_to_else_occurred = -100;\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"void push_wmops_fct( const char *label, ... )\r\n", +"{\r\n", +" int new_flag;\r\n", +" int i, j, index_record;\r\n", +" long tot;\r\n", +" va_list arg;\r\n", +" char func_name[MAX_FUNCTION_NAME_LENGTH] = \"\";\r\n", +"\r\n", +" /* concatenate all function name labels into a single string */\r\n", +" va_start( arg, label );\r\n", +" while ( label )\r\n", +" {\r\n", +" strcat( func_name, label );\r\n", +" label = va_arg( arg, const char * );\r\n", +" }\r\n", +" va_end( arg );\r\n", +"\r\n", +" /* Check, if this is a new function label */\r\n", +" new_flag = 1;\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" if ( strcmp( wmops[i].label, func_name ) == 0 )\r\n", +" {\r\n", +" new_flag = 0;\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +" index_record = i;\r\n", +"\r\n", +" /* Create a new WMOPS record in the list */\r\n", +" if ( new_flag )\r\n", +" {\r\n", +" if ( num_wmops_records >= max_num_wmops_records )\r\n", +" {\r\n", +" /* There is no room for a new WMOPS record -> reallocate the list */\r\n", +" max_num_wmops_records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" wmops = realloc( wmops, max_num_wmops_records * sizeof( wmops_record ) );\r\n", +" multiCounter = realloc( multiCounter, max_num_wmops_records * sizeof( BASIC_OP ) );\r\n", +" }\r\n", +"\r\n", +" /* initilize the new WMOPS record */\r\n", +" strcpy( &wmops[index_record].label[0], \"\\0\" );\r\n", +" wmops[index_record].call_number = 0;\r\n", +" wmops[index_record].update_cnt = 0;\r\n", +" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n", +" {\r\n", +" wmops[index_record].call_tree[j] = -1;\r\n", +" }\r\n", +" wmops[index_record].start_selfcnt = 0.0;\r\n", +" wmops[index_record].current_selfcnt = 0.0;\r\n", +" wmops[index_record].max_selfcnt = 0.0;\r\n", +" wmops[index_record].min_selfcnt = DOUBLE_MAX;\r\n", +" wmops[index_record].tot_selfcnt = 0.0;\r\n", +" wmops[index_record].start_cnt = 0.0;\r\n", +" wmops[index_record].current_cnt = 0.0;\r\n", +" wmops[index_record].max_cnt = 0.0;\r\n", +" wmops[index_record].min_cnt = DOUBLE_MAX;\r\n", +" wmops[index_record].tot_cnt = 0.0;\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" wmops[index_record].wc_cnt = 0.0;\r\n", +" wmops[index_record].wc_selfcnt = 0.0;\r\n", +" wmops[index_record].current_call_number = 0;\r\n", +" wmops[index_record].wc_call_number = -1;\r\n", +"#endif\r\n", +"\r\n", +" /* Reset BASOP operation counter */\r\n", +" Reset_BASOP_WMOPS_counter( index_record );\r\n", +"\r\n", +" strcpy( wmops[index_record].label, func_name );\r\n", +"\r\n", +" num_wmops_records++;\r\n", +" }\r\n", +"\r\n", +" /* Update the WMOPS context info of the old record before switching to the new one */\r\n", +" if ( current_record >= 0 )\r\n", +" {\r\n", +" if ( wmops_caller_stack_index >= max_wmops_caller_stack_index )\r\n", +" {\r\n", +" /* There is no room for a new record -> reallocate the list */\r\n", +" max_wmops_caller_stack_index += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" wmops_caller_stack = realloc( wmops_caller_stack, max_wmops_caller_stack_index * sizeof( int ) );\r\n", +" }\r\n", +" wmops_caller_stack[wmops_caller_stack_index++] = current_record;\r\n", +"\r\n", +" /* add the BASOP complexity to the counter and update the old WMOPS counter */\r\n", +" tot = DeltaWeightedOperation( current_record );\r\n", +" ops_cnt += tot;\r\n", +" wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n", +"\r\n", +" /* update call tree */\r\n", +" for ( j = 0; j < MAX_CALL_TREE_DEPTH; j++ )\r\n", +" {\r\n", +" if ( wmops[index_record].call_tree[j] == current_record )\r\n", +" {\r\n", +" break;\r\n", +" }\r\n", +" else if ( wmops[index_record].call_tree[j] == -1 )\r\n", +" {\r\n", +" wmops[index_record].call_tree[j] = current_record;\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Need to reset the BASOP operation counter of the 0th record in every push_wmops() */\r\n", +" /* because currCounter can never be -1 */\r\n", +" if ( current_record == -1 && index_record == 0 )\r\n", +" {\r\n", +" wmops[index_record].LastWOper = TotalWeightedOperation( index_record );\r\n", +" }\r\n", +"\r\n", +" /* switch to the new record */\r\n", +" current_record = index_record;\r\n", +" wmops[index_record].start_selfcnt = ops_cnt;\r\n", +" wmops[index_record].start_cnt = ops_cnt;\r\n", +" wmops[index_record].call_number++;\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" wmops[index_record].current_call_number++;\r\n", +"#endif\r\n", +"\r\n", +" /* set the ID of the current BASOP operations counter */\r\n", +" currCounter = index_record;\r\n", +" call_occurred = 1;\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"void pop_wmops( void )\r\n", +"{\r\n", +" long tot;\r\n", +"\r\n", +" /* Check for underflow */\r\n", +" if ( current_record < 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"\\r pop_wmops(): stack underflow, too many calls to pop_wmops()\\n\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* add the BASOP complexity to the counter */\r\n", +" tot = DeltaWeightedOperation( currCounter );\r\n", +" ops_cnt += tot;\r\n", +"\r\n", +" /* update count of current record */\r\n", +" wmops[current_record].current_selfcnt += ops_cnt - wmops[current_record].start_selfcnt;\r\n", +" wmops[current_record].current_cnt += ops_cnt - wmops[current_record].start_cnt;\r\n", +"\r\n", +" /* Get back previous context from stack */\r\n", +" if ( wmops_caller_stack_index > 0 )\r\n", +" {\r\n", +" current_record = wmops_caller_stack[--wmops_caller_stack_index];\r\n", +" wmops[current_record].start_selfcnt = ops_cnt;\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" current_record = -1;\r\n", +" }\r\n", +"\r\n", +" /* set the ID of the previous BASOP operations counter */\r\n", +" if ( current_record == -1 )\r\n", +" {\r\n", +" currCounter = 0; /* Note: currCounter cannot be set to -1 because it's defined as unsigned int ! */\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" currCounter = current_record;\r\n", +" }\r\n", +" call_occurred = 1;\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"\r\n", +"void update_wmops( void )\r\n", +"{\r\n", +" int i;\r\n", +" double current_cnt;\r\n", +"#ifdef WMOPS_PER_FRAME\r\n", +" static FILE *fid = NULL;\r\n", +" const char filename[] = \"wmops_analysis\";\r\n", +" float tmpF;\r\n", +"#endif\r\n", +"\r\n", +" if ( wmops_caller_stack_index != 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"update_wmops(): WMOPS caller stack corrupted - check that all push_wmops() are matched with pop_wmops()!\\n\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +"#ifdef WMOPS_PER_FRAME\r\n", +" /* Check, if the output file has already been opened */\r\n", +" if ( fid == NULL )\r\n", +" {\r\n", +" fid = fopen( filename, \"wb\" );\r\n", +"\r\n", +" if ( fid == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", filename );\r\n", +" exit( -1 );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Write current complexity to the external file */\r\n", +" tmpF = (float) ( FAC * wmops[0].current_cnt );\r\n", +" fwrite( &tmpF, sizeof( float ), 1, fid );\r\n", +"#endif\r\n", +"\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" if ( ops_cnt - start_cnt > max_cnt )\r\n", +" {\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" wmops[i].wc_cnt = wmops[i].current_cnt;\r\n", +" wmops[i].wc_selfcnt = wmops[i].current_selfcnt;\r\n", +" wmops[i].wc_call_number = wmops[i].current_call_number;\r\n", +" }\r\n", +" }\r\n", +"#endif\r\n", +"\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" wmops[i].tot_selfcnt += wmops[i].current_selfcnt;\r\n", +" wmops[i].tot_cnt += wmops[i].current_cnt;\r\n", +"\r\n", +" if ( wmops[i].current_selfcnt > 0 )\r\n", +" {\r\n", +" if ( wmops[i].current_selfcnt > wmops[i].max_selfcnt )\r\n", +" {\r\n", +" wmops[i].max_selfcnt = wmops[i].current_selfcnt;\r\n", +" }\r\n", +"\r\n", +" if ( wmops[i].current_selfcnt < wmops[i].min_selfcnt )\r\n", +" {\r\n", +" wmops[i].min_selfcnt = wmops[i].current_selfcnt;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" wmops[i].current_selfcnt = 0;\r\n", +"\r\n", +" if ( wmops[i].current_cnt > 0 )\r\n", +" {\r\n", +" if ( wmops[i].current_cnt > wmops[i].max_cnt )\r\n", +" {\r\n", +" wmops[i].max_cnt = wmops[i].current_cnt;\r\n", +" }\r\n", +"\r\n", +"\r\n", +" if ( wmops[i].current_cnt < wmops[i].min_cnt )\r\n", +" {\r\n", +" wmops[i].min_cnt = wmops[i].current_cnt;\r\n", +" }\r\n", +"\r\n", +" wmops[i].update_cnt++;\r\n", +" }\r\n", +"\r\n", +" wmops[i].current_cnt = 0;\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" wmops[i].current_call_number = 0;\r\n", +"#endif\r\n", +"\r\n", +" /* reset the BASOP operations counter */\r\n", +" call_occurred = 1;\r\n", +" Reset_BASOP_WMOPS_counter( i );\r\n", +" }\r\n", +"\r\n", +" current_cnt = ops_cnt - start_cnt;\r\n", +" if ( current_cnt > max_cnt )\r\n", +" {\r\n", +" max_cnt = current_cnt;\r\n", +"\r\n", +" for ( i = 0; i < NUM_INST; i++ )\r\n", +" {\r\n", +" inst_cnt_wc[i] = inst_cnt[i];\r\n", +" }\r\n", +"\r\n", +" fnum_cnt_wc = update_cnt + 1;\r\n", +" }\r\n", +"\r\n", +" if ( current_cnt < min_cnt )\r\n", +" {\r\n", +" min_cnt = current_cnt;\r\n", +" }\r\n", +"\r\n", +" for ( i = 0; i < NUM_INST; i++ )\r\n", +" {\r\n", +" inst_cnt[i] = 0.0;\r\n", +" }\r\n", +"\r\n", +" start_cnt = ops_cnt;\r\n", +"\r\n", +" /* increment frame counter */\r\n", +" update_cnt++;\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"void print_wmops( void )\r\n", +"{\r\n", +" int i, label_len, max_label_len;\r\n", +"\r\n", +" char *sfmts = \"%*s %8s %8s %7s %7s\\n\";\r\n", +" char *dfmts = \"%*s %8.2f %8.3f %7.3f %7.3f\\n\";\r\n", +" char *sfmt = \"%*s %8s %8s %7s %7s %7s %7s %7s\\n\";\r\n", +" char *dfmt = \"%*s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\\n\";\r\n", +"\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" int j;\r\n", +" char *sfmtt = \"%20s %4s %15s\\n\";\r\n", +" char *dfmtt = \"%20s %4d \";\r\n", +"#endif\r\n", +"\r\n", +" /* calculate maximum label length for compact prinout */\r\n", +" max_label_len = 0;\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" label_len = strlen( wmops[i].label );\r\n", +" if ( label_len > max_label_len )\r\n", +" {\r\n", +" max_label_len = label_len;\r\n", +" }\r\n", +" }\r\n", +" max_label_len += 4;\r\n", +"\r\n", +" fprintf( stdout, \"\\n\\n --- Complexity analysis [WMOPS] --- \\n\\n\" );\r\n", +"\r\n", +" fprintf( stdout, \"%*s %33s %23s\\n\", max_label_len, \"\", \"|------ SELF ------|\", \"|--- CUMULATIVE ---|\" );\r\n", +" fprintf( stdout, sfmt, max_label_len, \" routine\", \" calls\", \" min \", \" max \", \" avg \", \" min \", \" max \", \" avg \" );\r\n", +" fprintf( stdout, sfmt, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\", \"------\" );\r\n", +"\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" fprintf( stdout, dfmt, max_label_len, wmops[i].label, update_cnt == 0 ? 0 : (float) wmops[i].call_number / update_cnt,\r\n", +" wmops[i].min_selfcnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_selfcnt,\r\n", +" FAC * wmops[i].max_selfcnt,\r\n", +" wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_selfcnt / wmops[i].update_cnt,\r\n", +" wmops[i].min_cnt == DOUBLE_MAX ? 0 : FAC * wmops[i].min_cnt,\r\n", +" FAC * wmops[i].max_cnt,\r\n", +" wmops[i].update_cnt == 0 ? 0 : FAC * wmops[i].tot_cnt / wmops[i].update_cnt );\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, sfmts, max_label_len, \"---------------\", \"------\", \"------\", \"------\", \"------\" );\r\n", +" fprintf( stdout, dfmts, max_label_len, \"total\", (float) update_cnt, update_cnt == 0 ? 0 : FAC * min_cnt, FAC * max_cnt, update_cnt == 0 ? 0 : FAC * ops_cnt / update_cnt );\r\n", +" fprintf( stdout, \"\\n\" );\r\n", +"\r\n", +"#ifdef WMOPS_WC_FRAME_ANALYSIS\r\n", +" fprintf( stdout, \"\\nComplexity analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n", +" fprintf( stdout, \"%*s %8s %10s %12s\\n\", max_label_len, \" routine\", \" calls\", \" SELF\", \" CUMULATIVE\" );\r\n", +" fprintf( stdout, \"%*s %8s %10s %10s\\n\", max_label_len, \"---------------\", \"------\", \"------\", \"----------\" );\r\n", +"\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" if ( wmops[i].wc_call_number > 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"%*s %8d %10.3f %12.3f\\n\", max_label_len, wmops[i].label, wmops[i].wc_call_number, FAC * wmops[i].wc_selfcnt, FAC * wmops[i].wc_cnt );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, \"\\nCall tree for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n", +" fprintf( stdout, sfmtt, \" function\", \"num\", \"called by \" );\r\n", +" fprintf( stdout, sfmtt, \"---------------\", \"---\", \"--------------\" );\r\n", +"\r\n", +" for ( i = 0; i < num_wmops_records; i++ )\r\n", +" {\r\n", +" if ( wmops[i].wc_call_number > 0 )\r\n", +" {\r\n", +" fprintf( stdout, dfmtt, wmops[i].label, i );\r\n", +" for ( j = 0; wmops[i].call_tree[j] != -1 && j < MAX_CALL_TREE_DEPTH; j++ )\r\n", +" {\r\n", +" if ( j != 0 )\r\n", +" {\r\n", +" fprintf( stdout, \", \" );\r\n", +" }\r\n", +" fprintf( stdout, \"%d\", wmops[i].call_tree[j] );\r\n", +" }\r\n", +" fprintf( stdout, \"\\n\" );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, \"\\n\\n\" );\r\n", +"\r\n", +" fprintf( stdout, \"\\nInstruction type analysis for the worst-case frame %ld:\\n\\n\", fnum_cnt_wc );\r\n", +" for ( i = 0; i < NUM_INST; i++ )\r\n", +" {\r\n", +" switch ( (enum instructions) i )\r\n", +" {\r\n", +" case _ADD:\r\n", +" fprintf( stdout, \"\\tAdds: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _ABS:\r\n", +" fprintf( stdout, \"\\tAbsolutes: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _MULT:\r\n", +" fprintf( stdout, \"\\tMultiplies: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _MAC:\r\n", +" fprintf( stdout, \"\\tMACs: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _MOVE:\r\n", +" fprintf( stdout, \"\\tMoves: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _STORE:\r\n", +" fprintf( stdout, \"\\tStores: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _LOGIC:\r\n", +" fprintf( stdout, \"\\tLogicals: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _SHIFT:\r\n", +" fprintf( stdout, \"\\tShifts: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _BRANCH:\r\n", +" fprintf( stdout, \"\\tBranches: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _DIV:\r\n", +" fprintf( stdout, \"\\tDivisions: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _SQRT:\r\n", +" fprintf( stdout, \"\\tSquare Root: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _TRANS:\r\n", +" fprintf( stdout, \"\\tTrans: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _FUNC:\r\n", +" fprintf( stdout, \"\\tFunc Call: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _LOOP:\r\n", +" fprintf( stdout, \"\\tLoop Init: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _INDIRECT:\r\n", +" fprintf( stdout, \"\\tIndirect Addr: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _PTR_INIT:\r\n", +" fprintf( stdout, \"\\tPointer Init: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _TEST:\r\n", +" fprintf( stdout, \"\\tExtra condit.: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _POWER:\r\n", +" fprintf( stdout, \"\\tExponential: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _LOG:\r\n", +" fprintf( stdout, \"\\tLogarithm: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" case _MISC:\r\n", +" fprintf( stdout, \"\\tAll other op.: %12.1f\\n\", inst_cnt_wc[i] );\r\n", +" break;\r\n", +" default:\r\n", +" fprintf( stdout, \"\\tERROR: Invalid instruction type: %d\\n\\n\", i );\r\n", +" }\r\n", +" }\r\n", +"#endif\r\n", +"\r\n", +" /* De-allocate the list of wmops record */\r\n", +" if ( wmops != NULL )\r\n", +" {\r\n", +" free( wmops );\r\n", +" }\r\n", +"\r\n", +" /* De-allocate the list of wmops caller functions */\r\n", +" if ( wmops_caller_stack != NULL )\r\n", +" {\r\n", +" free( wmops_caller_stack );\r\n", +" }\r\n", +"\r\n", +" /* De-allocate the BASOP WMOPS counter */\r\n", +" if ( multiCounter != NULL )\r\n", +" {\r\n", +" free( multiCounter );\r\n", +" }\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * Memory counting tool measuring RAM usage (stack and heap)\r\n", +" *\r\n", +" * Maximum RAM is measured by monitoring the total allocated memory (stack and heap) in each frame.\r\n", +" *\r\n", +" * Maximum stack is measured by monitoring the difference between the 'top' and 'bottom' of the stack. The 'bottom' of the stack is updated in each function\r\n", +" * with a macro 'func_start_' which is inserted automatically to all functions during the instrumentation process.\r\n", +" *\r\n", +" * Maximum heap is measured by summing the sizes of all memory blocks allocated by malloc() or calloc() and deallocated by free(). The maximum heap size is\r\n", +" * updated each time when the macros malloc_() or calloc_() is invoked. The macros 'malloc_ and calloc_' are inserted automatically during the instrumentation process.\r\n", +" * As part of heap measurements, intra-frame heap and inter-frame heap are measured separately. Intra-frame heap refers to heap memory which is allocated and deallocated\r\n", +" * within a single frame. Inter-frame heap, on the contrary, refers to heap memory which is reserved for more than one frame.\r\n", +" *\r\n", +" * In order to run the memory counting tool the function reset_mem(cnt_size) must be called at the beginning of the encoding/decoding process.\r\n", +" * The unit in which memory consumption is reported is set via the parameter 'cnt_size'. It can be set to 0 (bytes), 1 (32b words) or 2 (64b words).\r\n", +" * At the end of the encoding/decoding process, 'print_mem()' function may be called to print basic information about memory consumption. If the macro 'MEM_COUNT_DETAILS'\r\n", +" * is activated, detailed information is printed\r\n", +" *\r\n", +" * The macro 'WMOPS' needs to be activated to enable memory counting. To avoid the instrumentation of malloc()/calloc()/free() calls, use\r\n", +" * #define WMC_TOOL_SKIP ... #undef WMC_TOOL_SKIP macro pair around the malloc(), calloc() and free().\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"\r\n", +"/* This is the value (in bytes) towards which the block size is rounded. For example, a block of 123 bytes, when using\r\n", +" a 32 bits system, will end up taking 124 bytes since the last unused byte cannot be used for another block. */\r\n", +"#ifdef MEM_ALIGN_64BITS\r\n", +"#define BLOCK_ROUNDING 8 /* Align on 64 Bits */\r\n", +"#else\r\n", +"#define BLOCK_ROUNDING 4 /* Align on 32 Bits */\r\n", +"#endif\r\n", +"\r\n", +"#define N_32BITS_BLOCKS ( BLOCK_ROUNDING / sizeof( int32_t ) )\r\n", +"\r\n", +"#define MAGIC_VALUE_OOB 0x12A534F0 /* Signature value which is inserted before and after each allocated memory block, used to detect out-of-bound access */\r\n", +"#define MAGIC_VALUE_USED ( ~MAGIC_VALUE_OOB ) /* Value used to pre-fill allocated memory blocks, used to calculate actual memory usage */\r\n", +"#define OOB_START 0x1 /* int indicating out-of-bounds access before memory block */\r\n", +"#define OOB_END 0x2 /* int indicating out-of-bounds access after memory block */\r\n", +"\r\n", +"#define ROUND_BLOCK_SIZE( n ) ( ( ( n ) + BLOCK_ROUNDING - 1 ) & ~( BLOCK_ROUNDING - 1 ) )\r\n", +"#define IS_CALLOC( str ) ( str[0] == 'c' )\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +"const char *csv_filename = \"mem_analysis.csv\";\r\n", +"static FILE *fid_csv_filename = NULL;\r\n", +"#endif\r\n", +"\r\n", +"typedef struct\r\n", +"{\r\n", +" char function_name[MAX_FUNCTION_NAME_LENGTH + 1];\r\n", +" int16_t *stack_ptr;\r\n", +"} caller_info;\r\n", +"\r\n", +"static caller_info *stack_callers[2] = { NULL, NULL };\r\n", +"\r\n", +"static int16_t *ptr_base_stack = 0; /* Pointer to the bottom of stack (base pointer). Stack grows up. */\r\n", +"static int16_t *ptr_current_stack = 0; /* Pointer to the current stack pointer */\r\n", +"static int16_t *ptr_max_stack = 0; /* Pointer to the maximum stack pointer (the farest point from the bottom of stack) */\r\n", +"static int32_t wc_stack_frame = 0; /* Frame corresponding to the worst-case stack usage */\r\n", +"static int current_calls = 0, max_num_calls = MAX_NUM_RECORDS;\r\n", +"static char location_max_stack[256] = \"undefined\";\r\n", +"\r\n", +"typedef struct\r\n", +"{\r\n", +" char name[MAX_FUNCTION_NAME_LENGTH + 1]; /* +1 for NUL */\r\n", +" char params[1 + MAX_PARAMS_LENGTH + 1]; /* +1 for 'm'/'c' alloc & +1 for NUL */\r\n", +" unsigned long hash;\r\n", +" int lineno;\r\n", +" void *block_ptr;\r\n", +" int block_size;\r\n", +" unsigned long total_block_size; /* Cumulative sum of the allocated size in the session */\r\n", +" unsigned long total_used_size; /* Cumulative sum of the used size in the session */\r\n", +" int wc_heap_size_intra_frame; /* Worst-Case Intra-Frame Heap Size */\r\n", +" int wc_heap_size_inter_frame; /* Worst-Case Inter-Frame Heap Size */\r\n", +" int frame_allocated; /* Frame number in which the Memory Block has been allocated (-1 if not allocated at the moment) */\r\n", +" int OOB_Flag;\r\n", +" int noccurances; /* Number of times that the memory block has been allocated in a frame */\r\n", +"} allocator_record;\r\n", +"\r\n", +"allocator_record *allocation_list = NULL;\r\n", +"\r\n", +"static int Num_Records, Max_Num_Records;\r\n", +"static size_t Stat_Cnt_Size = USE_BYTES;\r\n", +"static const char *Count_Unit[] = { \"bytes\", \"words\", \"words\", \"words\" };\r\n", +"\r\n", +"static int32_t wc_ram_size, wc_ram_frame;\r\n", +"static int32_t current_heap_size;\r\n", +"static int *list_wc_intra_frame_heap, n_items_wc_intra_frame_heap, max_items_wc_intra_frame_heap, size_wc_intra_frame_heap, location_wc_intra_frame_heap;\r\n", +"static int *list_current_inter_frame_heap, n_items_current_inter_frame_heap, max_items_current_inter_frame_heap, size_current_inter_frame_heap;\r\n", +"static int *list_wc_inter_frame_heap, n_items_wc_inter_frame_heap, max_items_wc_inter_frame_heap, size_wc_inter_frame_heap, location_wc_inter_frame_heap;\r\n", +"\r\n", +"/* Local Functions */\r\n", +"static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str );\r\n", +"allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record );\r\n", +"static void *mem_alloc_block( size_t size, const char *size_str );\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * reset_mem()\r\n", +" *\r\n", +" * Initialize/reset memory counting tool (stack and heap)\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"void reset_mem( Counting_Size cnt_size )\r\n", +"{\r\n", +" int16_t something;\r\n", +" size_t tmp_size;\r\n", +"\r\n", +" /* initialize list of stack records */\r\n", +" if ( stack_callers[0] == NULL )\r\n", +" {\r\n", +" stack_callers[0] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n", +" stack_callers[1] = malloc( MAX_NUM_RECORDS * sizeof( caller_info ) );\r\n", +" }\r\n", +"\r\n", +" if ( stack_callers[0] == NULL || stack_callers[1] == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Unable to Allocate List of Stack Records!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" current_calls = 0;\r\n", +" max_num_calls = MAX_NUM_RECORDS;\r\n", +"\r\n", +" /* initialize stack pointers */\r\n", +" ptr_base_stack = &something;\r\n", +" ptr_max_stack = ptr_base_stack;\r\n", +" ptr_current_stack = ptr_base_stack;\r\n", +"\r\n", +" /* initialize the unit of memory block size */\r\n", +" Stat_Cnt_Size = cnt_size;\r\n", +"\r\n", +" /* Check, if sizeof(int32_t) is 4 bytes */\r\n", +" tmp_size = sizeof( int32_t );\r\n", +" if ( tmp_size != 4 )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Expecting 'int32_t' to be a 32 Bits Integer!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* create allocation list for malloc() memory blocks */\r\n", +" if ( allocation_list == NULL )\r\n", +" {\r\n", +" allocation_list = malloc( MAX_NUM_RECORDS * sizeof( allocator_record ) );\r\n", +" }\r\n", +"\r\n", +" if ( allocation_list == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Unable to Create List of Memory Blocks!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" Num_Records = 0;\r\n", +" Max_Num_Records = MAX_NUM_RECORDS;\r\n", +"\r\n", +" wc_ram_size = 0;\r\n", +" wc_ram_frame = -1;\r\n", +" current_heap_size = 0;\r\n", +"\r\n", +" /* heap allocation tree */\r\n", +" heap_allocation_call_tree_max_size = MAX_NUM_RECORDS;\r\n", +" if ( heap_allocation_call_tree == NULL )\r\n", +" {\r\n", +" heap_allocation_call_tree = (int *) malloc( heap_allocation_call_tree_max_size * sizeof( int ) );\r\n", +" memset( heap_allocation_call_tree, -1, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n", +" }\r\n", +" heap_allocation_call_tree_size = 0;\r\n", +"\r\n", +" /* wc intra-frame heap */\r\n", +" max_items_wc_intra_frame_heap = MAX_NUM_RECORDS;\r\n", +" if ( list_wc_intra_frame_heap == NULL )\r\n", +" {\r\n", +" list_wc_intra_frame_heap = (int *) malloc( max_items_wc_intra_frame_heap * sizeof( int ) );\r\n", +" memset( list_wc_intra_frame_heap, -1, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n", +" }\r\n", +" n_items_wc_intra_frame_heap = 0;\r\n", +" size_wc_intra_frame_heap = 0;\r\n", +" location_wc_intra_frame_heap = -1;\r\n", +"\r\n", +" /* current inter-frame heap */\r\n", +" max_items_current_inter_frame_heap = MAX_NUM_RECORDS;\r\n", +" if ( list_current_inter_frame_heap == NULL )\r\n", +" {\r\n", +" list_current_inter_frame_heap = (int *) malloc( max_items_current_inter_frame_heap * sizeof( int ) );\r\n", +" memset( list_current_inter_frame_heap, -1, max_items_current_inter_frame_heap * sizeof( int ) );\r\n", +" }\r\n", +" n_items_current_inter_frame_heap = 0;\r\n", +" size_current_inter_frame_heap = 0;\r\n", +"\r\n", +" /* wc inter-frame heap */\r\n", +" max_items_wc_inter_frame_heap = MAX_NUM_RECORDS;\r\n", +" if ( list_wc_inter_frame_heap == NULL )\r\n", +" {\r\n", +" list_wc_inter_frame_heap = (int *) malloc( max_items_wc_inter_frame_heap * sizeof( int ) );\r\n", +" memset( list_wc_inter_frame_heap, -1, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n", +" }\r\n", +" n_items_wc_inter_frame_heap = 0;\r\n", +" size_wc_inter_frame_heap = 0;\r\n", +" location_wc_inter_frame_heap = -1;\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +" /* Check, if the .csv file has already been opened */\r\n", +" if ( fid_csv_filename == NULL )\r\n", +" {\r\n", +" fid_csv_filename = fopen( csv_filename, \"wb\" );\r\n", +"\r\n", +" if ( fid_csv_filename == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"\\nCannot open %s!\\n\\n\", csv_filename );\r\n", +" exit( -1 );\r\n", +" }\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" /* reset file */\r\n", +" rewind( fid_csv_filename );\r\n", +" }\r\n", +"#endif\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * reset_stack()\r\n", +" *\r\n", +" * Reset stack pointer\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"void reset_stack( void )\r\n", +"{\r\n", +" int16_t something;\r\n", +"\r\n", +" /* initialize/reset stack pointers */\r\n", +" ptr_base_stack = &something;\r\n", +" ptr_max_stack = ptr_base_stack;\r\n", +" ptr_current_stack = ptr_base_stack;\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * push_stack()\r\n", +" *\r\n", +" * Check the current stack pointer and update the maximum stack pointer, if new maximum found.\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"int push_stack( const char *filename, const char *fctname )\r\n", +"{\r\n", +" int16_t something;\r\n", +" int32_t current_stack_size;\r\n", +"\r\n", +" ptr_current_stack = &something;\r\n", +"\r\n", +" (void) *filename; /* to avoid compilation warning */\r\n", +"\r\n", +" if ( current_calls >= max_num_calls )\r\n", +" {\r\n", +" /* There is no room for a new record -> reallocate the list */\r\n", +" max_num_calls += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" stack_callers[0] = realloc( stack_callers[0], max_num_calls * sizeof( caller_info ) );\r\n", +" stack_callers[1] = realloc( stack_callers[1], max_num_calls * sizeof( caller_info ) );\r\n", +" }\r\n", +"\r\n", +" /* Valid Function Name? */\r\n", +" if ( fctname[0] == 0 )\r\n", +" { /* No */\r\n", +" fprintf( stderr, \"Invalid function name for call stack info.\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* Save the Name of the Calling Function in the Table */\r\n", +" strncpy( stack_callers[0][current_calls].function_name, fctname, MAX_FUNCTION_NAME_LENGTH );\r\n", +" stack_callers[0][current_calls].function_name[MAX_FUNCTION_NAME_LENGTH] = 0; /* Nul Terminate */\r\n", +"\r\n", +" /* Save the Stack Pointer */\r\n", +" stack_callers[0][current_calls].stack_ptr = ptr_current_stack;\r\n", +"\r\n", +" /* Increase the Number of Calls in the List */\r\n", +" current_calls++;\r\n", +"\r\n", +" /* Is this the First Time or the Worst Case? */\r\n", +" if ( ptr_current_stack < ptr_max_stack || ptr_max_stack == NULL )\r\n", +" { /* Yes */\r\n", +" /* Save Info about it */\r\n", +" ptr_max_stack = ptr_current_stack;\r\n", +"\r\n", +" /* save the worst-case frame number */\r\n", +" /* current frame number is stored in the variable update_cnt and updated in the function update_wmops() */\r\n", +" wc_stack_frame = update_cnt;\r\n", +" strncpy( location_max_stack, fctname, sizeof( location_max_stack ) - 1 );\r\n", +" location_max_stack[sizeof( location_max_stack ) - 1] = '\\0';\r\n", +"\r\n", +" /* Save Call Tree */\r\n", +" memmove( stack_callers[1], stack_callers[0], sizeof( caller_info ) * current_calls );\r\n", +"\r\n", +" /* Terminate the List with 0 (for printing purposes) */\r\n", +" if ( current_calls < max_num_calls )\r\n", +" {\r\n", +" stack_callers[1][current_calls].function_name[0] = 0;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Check, if This is the New Worst-Case RAM (stack + heap) */\r\n", +" current_stack_size = ( int32_t )( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) );\r\n", +"\r\n", +" if ( current_stack_size < 0 )\r\n", +" {\r\n", +" /* prevent negative stack size */\r\n", +" current_stack_size = 0;\r\n", +" }\r\n", +"\r\n", +" if ( current_stack_size + current_heap_size > wc_ram_size )\r\n", +" {\r\n", +" wc_ram_size = current_stack_size + current_heap_size;\r\n", +" wc_ram_frame = update_cnt;\r\n", +" }\r\n", +"\r\n", +" return 0 /* for Now */;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * pop_stack()\r\n", +" *\r\n", +" * Remove stack caller entry from the list\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"int pop_stack( const char *filename, const char *fctname )\r\n", +"{\r\n", +" caller_info *caller_info_ptr;\r\n", +"\r\n", +" (void) *filename; /* to avoid compilation warning */\r\n", +"\r\n", +" /* Decrease the Number of Records */\r\n", +" current_calls--;\r\n", +"\r\n", +" /* Get Pointer to Caller Information */\r\n", +" caller_info_ptr = &stack_callers[0][current_calls];\r\n", +"\r\n", +" /* Check, if the Function Names Match */\r\n", +" if ( strncmp( caller_info_ptr->function_name, fctname, MAX_FUNCTION_NAME_LENGTH ) != 0 )\r\n", +" {\r\n", +" fprintf( stderr, \"Invalid usage of pop_stack()\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* Erase Entry */\r\n", +" caller_info_ptr->function_name[0] = 0;\r\n", +"\r\n", +" /* Retrieve previous stack pointer */\r\n", +" if ( current_calls == 0 )\r\n", +" {\r\n", +" ptr_current_stack = ptr_base_stack;\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" ptr_current_stack = stack_callers[0][current_calls - 1].stack_ptr;\r\n", +" }\r\n", +"\r\n", +" return 0 /* for Now */;\r\n", +"}\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * print_stack_call_tree()\r\n", +" *\r\n", +" * Print detailed information about worst-case stack usage\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static void print_stack_call_tree( void )\r\n", +"{\r\n", +" caller_info *caller_info_ptr;\r\n", +" int call_level;\r\n", +" char fctname[MAX_FUNCTION_NAME_LENGTH + 1];\r\n", +"\r\n", +" fprintf( stdout, \"\\nList of functions when maximum stack size is reached:\\n\\n\" );\r\n", +"\r\n", +" caller_info_ptr = &stack_callers[1][0];\r\n", +" for ( call_level = 0; call_level < max_num_calls; call_level++ )\r\n", +" {\r\n", +" /* Done? */\r\n", +" if ( caller_info_ptr->function_name[0] == 0 )\r\n", +" {\r\n", +" break;\r\n", +" }\r\n", +"\r\n", +" /* Print Name */\r\n", +" strncpy( fctname, caller_info_ptr->function_name, MAX_FUNCTION_NAME_LENGTH );\r\n", +" strcat( fctname, \"()\" );\r\n", +" fprintf( stdout, \"%-42s\", fctname );\r\n", +"\r\n", +" /* Print Stack Usage (Based on Difference) */\r\n", +" if ( call_level != 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"%lu %s\\n\", ( ( ( caller_info_ptr - 1 )->stack_ptr - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" fprintf( stdout, \"%lu %s\\n\", ( ( ptr_base_stack - caller_info_ptr->stack_ptr ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +"\r\n", +" /* Advance */\r\n", +" caller_info_ptr++;\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, \"\\n\" );\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"#endif\r\n", +"\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * mem_alloc()\r\n", +" *\r\n", +" * Creates new record, stores auxiliary information about which function allocated the memory, line number, parameters, etc.\r\n", +" * Finally, it allocates physical memory using malloc()\r\n", +" * The function also updates worst-case heap size and worst-case RAM size\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"void *mem_alloc(\r\n", +" const char *func_name,\r\n", +" int func_lineno,\r\n", +" size_t size,\r\n", +" char *size_str /* the first char indicates m-alloc or c-alloc */ )\r\n", +"{\r\n", +" int index_record;\r\n", +" int32_t current_stack_size;\r\n", +" unsigned long hash;\r\n", +" allocator_record *ptr_record;\r\n", +"\r\n", +" if ( size == 0 )\r\n", +" {\r\n", +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Size of Zero not Supported\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* Search for an existing record (that has been de-allocated before) */\r\n", +" index_record = 0;\r\n", +" while ( ( ptr_record = get_mem_record( &hash, func_name, func_lineno, size_str, &index_record ) ) != NULL )\r\n", +" {\r\n", +" if ( ptr_record->frame_allocated == -1 )\r\n", +" {\r\n", +" break;\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" index_record++;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Create new record */\r\n", +" if ( ptr_record == NULL )\r\n", +" {\r\n", +" if ( Num_Records >= Max_Num_Records )\r\n", +" {\r\n", +" /* There is no room for a new record -> reallocate memory */\r\n", +" Max_Num_Records += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" allocation_list = realloc( allocation_list, Max_Num_Records * sizeof( allocator_record ) );\r\n", +" }\r\n", +"\r\n", +" ptr_record = &( allocation_list[Num_Records] );\r\n", +"\r\n", +" /* Initialize new record */\r\n", +" ptr_record->hash = hash;\r\n", +" ptr_record->noccurances = 0;\r\n", +" ptr_record->total_block_size = 0;\r\n", +" ptr_record->total_used_size = 0;\r\n", +" ptr_record->frame_allocated = -1;\r\n", +" ptr_record->OOB_Flag = 0;\r\n", +" ptr_record->wc_heap_size_intra_frame = -1;\r\n", +" ptr_record->wc_heap_size_inter_frame = -1;\r\n", +"\r\n", +" index_record = Num_Records;\r\n", +" Num_Records++;\r\n", +" }\r\n", +"\r\n", +" /* Allocate memory block for the new record, add signature before the beginning and after the memory block and fill it with magic value */\r\n", +" ptr_record->block_ptr = mem_alloc_block( size, size_str );\r\n", +"\r\n", +" if ( ptr_record->block_ptr == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Cannot Allocate Memory!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* Save all auxiliary information about the memory block */\r\n", +" strncpy( ptr_record->name, func_name, MAX_FUNCTION_NAME_LENGTH );\r\n", +" ptr_record->name[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n", +" strncpy( ptr_record->params, size_str, MAX_PARAMS_LENGTH ); /* Note: The size string starts with either 'm' or 'c' to indicate 'm'alloc or 'c'alloc */\r\n", +" ptr_record->params[MAX_PARAMS_LENGTH] = '\\0';\r\n", +" ptr_record->lineno = func_lineno;\r\n", +" ptr_record->block_size = size;\r\n", +" ptr_record->total_block_size += size;\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +" /* Export heap memory allocation record to the .csv file */\r\n", +" fprintf( fid_csv_filename, \"A,%ld,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n", +"#endif\r\n", +"\r\n", +" if ( ptr_record->frame_allocated != -1 )\r\n", +" {\r\n", +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Attempt to Allocate the Same Memory Block with Freeing it First!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" ptr_record->frame_allocated = update_cnt; /* Store the current frame number -> later it will be used to determine the total duration */\r\n", +"\r\n", +" /* Update Heap Size in the current frame */\r\n", +" current_heap_size += ptr_record->block_size;\r\n", +"\r\n", +" /* Check, if this is the new Worst-Case RAM (stack + heap) */\r\n", +" current_stack_size = ( int32_t )( ( ( ptr_base_stack - ptr_current_stack ) * sizeof( int16_t ) ) );\r\n", +" if ( current_stack_size + current_heap_size > wc_ram_size )\r\n", +" {\r\n", +" wc_ram_size = current_stack_size + current_heap_size;\r\n", +" wc_ram_frame = update_cnt;\r\n", +" }\r\n", +"\r\n", +" /* Add new entry to the heap allocation call tree */\r\n", +" if ( heap_allocation_call_tree == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Heap allocation call tree not created!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* check, if the maximum size of the call tree has been reached -> resize if so */\r\n", +" if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size )\r\n", +" {\r\n", +" heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" /* push new entry (positive number means push op, neagtive number means pop op; zero index must be converted to 0.01 :-) */\r\n", +" heap_allocation_call_tree[heap_allocation_call_tree_size++] = index_record;\r\n", +"\r\n", +" return ptr_record->block_ptr;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * mem_alloc_block()\r\n", +" *\r\n", +" * Physical allocation of memory using malloc(). Appends 'signature' before and after the block,\r\n", +" * pre-fills memory block with magic value\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static void *mem_alloc_block( size_t size, const char *size_str )\r\n", +"{\r\n", +" size_t rounded_size;\r\n", +" void *block_ptr;\r\n", +" char *tmp_ptr;\r\n", +" size_t n, f;\r\n", +" int32_t fill_value;\r\n", +" int32_t *ptr32;\r\n", +" int32_t mask, temp;\r\n", +"\r\n", +" /* Round Up Block Size */\r\n", +" rounded_size = ROUND_BLOCK_SIZE( size );\r\n", +"\r\n", +" /* Allocate memory using the standard malloc() by adding room for Signature Values */\r\n", +" block_ptr = malloc( rounded_size + BLOCK_ROUNDING * 2 );\r\n", +"\r\n", +" if ( block_ptr == NULL )\r\n", +" {\r\n", +" return NULL;\r\n", +" }\r\n", +"\r\n", +" /* Add Signature Before the Start of the Block */\r\n", +" ptr32 = (int32_t *) block_ptr;\r\n", +" n = N_32BITS_BLOCKS;\r\n", +" do\r\n", +" {\r\n", +" *ptr32++ = MAGIC_VALUE_OOB;\r\n", +" } while ( --n );\r\n", +"\r\n", +" /* Fill Memory Block with Magic Value or 0 */\r\n", +" fill_value = MAGIC_VALUE_USED;\r\n", +" if ( size_str[0] == 'c' )\r\n", +" {\r\n", +" fill_value = 0x00000000;\r\n", +" }\r\n", +" n = size / sizeof( int32_t );\r\n", +" while ( n-- )\r\n", +" {\r\n", +" *ptr32++ = fill_value;\r\n", +" }\r\n", +"\r\n", +" /* Fill the Reminder of the Memory Block - After Rounding */\r\n", +" n = rounded_size - size;\r\n", +" f = n % sizeof( int32_t );\r\n", +" if ( f != 0 )\r\n", +" {\r\n", +" /* when filling with '0' need to adapt the magic value */\r\n", +" /* shift by [1->24, 2->16, 3->8] */\r\n", +" mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 ); /* (1) */\r\n", +" temp = MAGIC_VALUE_OOB & mask;\r\n", +" if ( fill_value != 0x0 )\r\n", +" { /* for malloc merge fill value */\r\n", +" temp += ( ~mask ) & MAGIC_VALUE_USED;\r\n", +" } /* for calloc the code in (1) above already introduces zeros */\r\n", +" *ptr32++ = temp;\r\n", +" }\r\n", +" n /= sizeof( int32_t );\r\n", +" n += N_32BITS_BLOCKS;\r\n", +"\r\n", +" /* Add Signature After the End of Block */\r\n", +" do\r\n", +" {\r\n", +" *ptr32++ = MAGIC_VALUE_OOB;\r\n", +" } while ( --n );\r\n", +"\r\n", +" /* Adjust the Memory Block Pointer (Magic Value Before and After the Memory Block Requested) */\r\n", +" tmp_ptr = (char *) block_ptr;\r\n", +" tmp_ptr += BLOCK_ROUNDING;\r\n", +" block_ptr = (void *) tmp_ptr;\r\n", +"\r\n", +" return block_ptr;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * mem_set_usage()\r\n", +" *\r\n", +" * Calculates actual usage of memory block by checking the magic value that was used to pre-fill\r\n", +" * each memory block during its allocation\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static int mem_set_usage( allocator_record *record_ptr )\r\n", +"{\r\n", +" int total_bytes_used;\r\n", +"\r\n", +" size_t n;\r\n", +" int32_t *ptr32;\r\n", +" char *ptr8;\r\n", +" size_t total_bytes;\r\n", +" int32_t fill_value;\r\n", +"\r\n", +" fill_value = MAGIC_VALUE_USED;\r\n", +" if ( ( record_ptr->params[0] ) == 'c' )\r\n", +" {\r\n", +" fill_value = 0x00000000;\r\n", +" }\r\n", +"\r\n", +" total_bytes = record_ptr->block_size;\r\n", +"\r\n", +" /* Check 4 bytes at a time */\r\n", +" ptr32 = (int32_t *) record_ptr->block_ptr;\r\n", +" total_bytes_used = 0;\r\n", +" for ( n = total_bytes / sizeof( int32_t ); n > 0; n-- )\r\n", +" {\r\n", +" if ( *ptr32++ != fill_value )\r\n", +" {\r\n", +" total_bytes_used += sizeof( int32_t );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Check remaining bytes (If Applicable) 1 byte at a time */\r\n", +" ptr8 = (char *) ptr32;\r\n", +" for ( n = total_bytes % sizeof( int32_t ); n > 0; n-- )\r\n", +" {\r\n", +" if ( *ptr8++ != (char) fill_value )\r\n", +" {\r\n", +" total_bytes_used++;\r\n", +" }\r\n", +"\r\n", +" /* Update Value */\r\n", +" fill_value >>= 8;\r\n", +" }\r\n", +"\r\n", +" return total_bytes_used;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * mem_check_OOB()\r\n", +" *\r\n", +" * Checks, if out-of-bounds access has occured. This is done by inspecting the 'signature' value\r\n", +" * taht has been added before and after the memory block during its allocation\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static unsigned int mem_check_OOB( allocator_record *record_ptr )\r\n", +"{\r\n", +" int32_t *ptr32;\r\n", +" unsigned int OOB_Flag = 0x0;\r\n", +" int32_t mask;\r\n", +" size_t i;\r\n", +" int f;\r\n", +"\r\n", +" ptr32 = (int32_t *) record_ptr->block_ptr - N_32BITS_BLOCKS;\r\n", +"\r\n", +" /* Check the Signature at the Beginning of Memory Block */\r\n", +" i = N_32BITS_BLOCKS;\r\n", +" do\r\n", +" {\r\n", +" if ( *ptr32++ ^ MAGIC_VALUE_OOB )\r\n", +" {\r\n", +" OOB_Flag |= OOB_START;\r\n", +" }\r\n", +" } while ( --i );\r\n", +"\r\n", +" /* Advance to End (Snap to lowest 32 Bits) */\r\n", +" ptr32 += record_ptr->block_size / sizeof( int32_t );\r\n", +"\r\n", +" /* Calculate Unused Space That has been added to get to the rounded Block Size */\r\n", +" i = ROUND_BLOCK_SIZE( record_ptr->block_size ) - record_ptr->block_size;\r\n", +"\r\n", +" /* Partial Check of Signature at the End of Memory Block (for block size that has been rounded) */\r\n", +" f = i % sizeof( int32_t );\r\n", +" if ( f != 0 )\r\n", +" {\r\n", +" mask = 0xFFFFFFFF << ( ( sizeof( int32_t ) - f ) * 8 );\r\n", +" if ( ( *ptr32++ ^ MAGIC_VALUE_OOB ) & mask )\r\n", +" {\r\n", +" OOB_Flag |= OOB_END;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Full Check of Signature at the End of Memory Block, i.e. all 32 Bits (for the remainder after rounding) */\r\n", +" i /= sizeof( int32_t );\r\n", +" i += N_32BITS_BLOCKS;\r\n", +" do\r\n", +" {\r\n", +" if ( *ptr32++ ^ MAGIC_VALUE_OOB )\r\n", +" {\r\n", +" OOB_Flag |= OOB_END;\r\n", +" }\r\n", +" } while ( --i );\r\n", +"\r\n", +" return OOB_Flag;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * malloc_hash()\r\n", +" *\r\n", +" * Calculate hash from function name, line number and malloc size\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static unsigned long malloc_hash( const char *func_name, int func_lineno, char *size_str )\r\n", +"{\r\n", +" unsigned long hash = 5381;\r\n", +" const char *ptr_str;\r\n", +"\r\n", +" ptr_str = func_name;\r\n", +" while ( ptr_str != NULL && *ptr_str != '\\0' )\r\n", +" {\r\n", +" hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */\r\n", +" }\r\n", +"\r\n", +" hash = ( ( hash << 5 ) + hash ) + func_lineno; /* hash * 33 + func_lineno */\r\n", +"\r\n", +" ptr_str = size_str;\r\n", +" while ( ptr_str != NULL && *ptr_str != '\\0' )\r\n", +" {\r\n", +" hash = ( ( hash << 5 ) + hash ) + *ptr_str++; /* hash * 33 + char */\r\n", +" }\r\n", +"\r\n", +" return hash;\r\n", +"}\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * get_mem_record()\r\n", +" *\r\n", +" * Search for memory record in the internal list, return NULL if not found\r\n", +" * Start from index_record\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"allocator_record *get_mem_record( unsigned long *hash, const char *func_name, int func_lineno, char *size_str, int *index_record )\r\n", +"{\r\n", +" int i;\r\n", +"\r\n", +" if ( *index_record < 0 || *index_record > Num_Records )\r\n", +" {\r\n", +" return NULL;\r\n", +" }\r\n", +"\r\n", +" /* calculate hash */\r\n", +" *hash = malloc_hash( func_name, func_lineno, size_str );\r\n", +"\r\n", +" for ( i = *index_record; i < Num_Records; i++ )\r\n", +" {\r\n", +" /* check, if memory block is not allocated at the moment and the hash matches */\r\n", +" if ( allocation_list[i].block_ptr == NULL && *hash == allocation_list[i].hash )\r\n", +" {\r\n", +" *index_record = i;\r\n", +" return &( allocation_list[i] );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* not found */\r\n", +" *index_record = -1;\r\n", +" return NULL;\r\n", +"}\r\n", +"\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * mem_free()\r\n", +" *\r\n", +" * This function de-allocates memory blocks and frees physical memory with free().\r\n", +" * It also updates the actual and average usage of memory blocks.\r\n", +" *\r\n", +" * Note: The record is not removed from the list and may be reused later on in mem_alloc()!\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"void mem_free( const char *func_name, int func_lineno, void *ptr )\r\n", +"{\r\n", +" int i, index_record;\r\n", +" char *tmp_ptr;\r\n", +" allocator_record *ptr_record;\r\n", +"\r\n", +" /* Search for the Block Pointer in the List */\r\n", +" ptr_record = NULL;\r\n", +" index_record = -1;\r\n", +" for ( i = 0; i < Num_Records; i++ )\r\n", +" {\r\n", +" if ( ptr == allocation_list[i].block_ptr )\r\n", +" { /* Yes, Found it */\r\n", +" ptr_record = &( allocation_list[i] );\r\n", +" index_record = i;\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" if ( ptr_record == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", func_name, func_lineno, \"Error: Unable to Find Record Corresponding to the Allocated Memory Block!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* Update the Heap Size */\r\n", +" current_heap_size -= ptr_record->block_size;\r\n", +"\r\n", +" /* Calculate the Actual Usage of the Memory Block (Look for Signature) */\r\n", +" ptr_record->total_used_size += mem_set_usage( ptr_record );\r\n", +"\r\n", +" /* Check, if Out-Of-Bounds Access has been Detected */\r\n", +" ptr_record->OOB_Flag = mem_check_OOB( ptr_record );\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +" /* Export heap memory de-allocation record to the .csv file */\r\n", +" fprintf( fid_csv_filename, \"D,%ld,%s,%d,%d\\n\", update_cnt, ptr_record->name, ptr_record->lineno, ptr_record->block_size );\r\n", +"#endif\r\n", +"\r\n", +" /* De-Allocate Memory Block */\r\n", +" tmp_ptr = (char *) ptr;\r\n", +" tmp_ptr -= BLOCK_ROUNDING;\r\n", +" ptr = (void *) tmp_ptr;\r\n", +" free( ptr );\r\n", +"\r\n", +" /* Add new entry to the heap allocation call tree */\r\n", +" if ( heap_allocation_call_tree == NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Error: Heap allocation call tree not created!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" /* check, if the maximum size of the call tree has been reached -> resize if so */\r\n", +" if ( heap_allocation_call_tree_size >= heap_allocation_call_tree_max_size )\r\n", +" {\r\n", +" heap_allocation_call_tree_max_size += MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" heap_allocation_call_tree = (int *) realloc( heap_allocation_call_tree, heap_allocation_call_tree_max_size * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" heap_allocation_call_tree[heap_allocation_call_tree_size++] = -index_record;\r\n", +"\r\n", +" /* Reset memory block pointer (this is checked when updating wc intra-frame and inter-frame memory) */\r\n", +" ptr_record->block_ptr = NULL;\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * update_mem()\r\n", +" *\r\n", +" * This function updates the worst-case intra-frame memory and the worst-case inter-frame memory.\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"void update_mem( void )\r\n", +"{\r\n", +" int i, j, flag_alloc = -1, i_record;\r\n", +" int size_current_intra_frame_heap;\r\n", +" int *list_current_intra_frame_heap = NULL, n_items_current_intra_frame_heap;\r\n", +" allocator_record *ptr_record;\r\n", +"\r\n", +" /* process the heap allocation call tree and prepare lists of intra-frame and inter-frame heap memory blocks for this frame */\r\n", +" n_items_current_intra_frame_heap = 0;\r\n", +" size_current_intra_frame_heap = 0;\r\n", +" for ( i = 0; i < heap_allocation_call_tree_size; i++ )\r\n", +" {\r\n", +" /* get the record */\r\n", +" i_record = heap_allocation_call_tree[i];\r\n", +"\r\n", +" if ( i_record > 0 )\r\n", +" {\r\n", +" flag_alloc = 1;\r\n", +" }\r\n", +" else if ( i_record < 0 )\r\n", +" {\r\n", +" flag_alloc = 0;\r\n", +" i_record = -i_record;\r\n", +" }\r\n", +" ptr_record = &( allocation_list[i_record] );\r\n", +"\r\n", +" if ( ptr_record->frame_allocated == update_cnt && ptr_record->block_ptr == NULL )\r\n", +" {\r\n", +" /* intra-frame heap memory */\r\n", +" if ( list_current_intra_frame_heap == NULL )\r\n", +" {\r\n", +" list_current_intra_frame_heap = (int *) malloc( heap_allocation_call_tree_size * sizeof( int ) );\r\n", +" memset( list_current_intra_frame_heap, -1, heap_allocation_call_tree_size * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n", +" if ( i_record == 0 )\r\n", +" {\r\n", +" flag_alloc = 1;\r\n", +" for ( j = 0; j < n_items_current_intra_frame_heap; j++ )\r\n", +" {\r\n", +" if ( list_current_intra_frame_heap[j] == i_record )\r\n", +" {\r\n", +" flag_alloc = 0;\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" if ( flag_alloc )\r\n", +" {\r\n", +" /* add to list */\r\n", +" list_current_intra_frame_heap[n_items_current_intra_frame_heap++] = i_record;\r\n", +" size_current_intra_frame_heap += ptr_record->block_size;\r\n", +"\r\n", +" /* no need to re-size the list -> the initially allocated size should be large enough */\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" /* remove from list */\r\n", +" for ( j = 0; j < n_items_current_intra_frame_heap; j++ )\r\n", +" {\r\n", +" if ( list_current_intra_frame_heap[j] == i_record )\r\n", +" {\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +" memmove( &list_current_intra_frame_heap[j], &list_current_intra_frame_heap[j + 1], ( n_items_current_intra_frame_heap - j ) * sizeof( int ) );\r\n", +" n_items_current_intra_frame_heap--;\r\n", +" size_current_intra_frame_heap -= ptr_record->block_size;\r\n", +"\r\n", +" /* reset block size */\r\n", +" ptr_record->frame_allocated = -1;\r\n", +" ptr_record->block_size = 0;\r\n", +" }\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" /* inter-frame heap memory */\r\n", +"\r\n", +" /* zero index doesn't have sign to determine whether it's allocated or de-allocated -> we need to search the list */\r\n", +" if ( i_record == 0 )\r\n", +" {\r\n", +" flag_alloc = 1;\r\n", +" for ( j = 0; j < n_items_current_inter_frame_heap; j++ )\r\n", +" {\r\n", +" if ( list_current_inter_frame_heap[j] == i_record )\r\n", +" {\r\n", +" flag_alloc = 0;\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" if ( flag_alloc )\r\n", +" {\r\n", +" /* add to list */\r\n", +" if ( n_items_current_inter_frame_heap >= max_items_current_inter_frame_heap )\r\n", +" {\r\n", +" /* resize list, if needed */\r\n", +" max_items_current_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" list_current_inter_frame_heap = realloc( list_current_inter_frame_heap, max_items_current_inter_frame_heap * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" list_current_inter_frame_heap[n_items_current_inter_frame_heap++] = i_record;\r\n", +" size_current_inter_frame_heap += ptr_record->block_size;\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" /* remove from list */\r\n", +" for ( j = 0; j < n_items_current_inter_frame_heap; j++ )\r\n", +" {\r\n", +" if ( list_current_inter_frame_heap[j] == i_record )\r\n", +" {\r\n", +" break;\r\n", +" }\r\n", +" }\r\n", +" memmove( &list_current_inter_frame_heap[j], &list_current_inter_frame_heap[j + 1], ( n_items_current_inter_frame_heap - j ) * sizeof( int ) );\r\n", +" n_items_current_inter_frame_heap--;\r\n", +" size_current_inter_frame_heap -= ptr_record->block_size;\r\n", +"\r\n", +" /* reset block size */\r\n", +" ptr_record->frame_allocated = -1;\r\n", +" ptr_record->block_size = 0;\r\n", +" }\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* check, if this is the new worst-case for intra-frame heap memory */\r\n", +" if ( size_current_intra_frame_heap > size_wc_intra_frame_heap )\r\n", +" {\r\n", +" if ( n_items_current_intra_frame_heap >= max_items_wc_intra_frame_heap )\r\n", +" {\r\n", +" /* resize the list, if needed */\r\n", +" max_items_wc_intra_frame_heap = n_items_current_intra_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" list_wc_intra_frame_heap = realloc( list_wc_intra_frame_heap, max_items_wc_intra_frame_heap * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" /* copy current-frame list to worst-case list */\r\n", +" memmove( list_wc_intra_frame_heap, list_current_intra_frame_heap, n_items_current_intra_frame_heap * sizeof( int ) );\r\n", +" n_items_wc_intra_frame_heap = n_items_current_intra_frame_heap;\r\n", +" size_wc_intra_frame_heap = size_current_intra_frame_heap;\r\n", +" location_wc_intra_frame_heap = update_cnt;\r\n", +"\r\n", +" /* update the wc numbers in all individual records */\r\n", +" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n", +" {\r\n", +" i_record = list_wc_intra_frame_heap[i];\r\n", +" ptr_record = &( allocation_list[i_record] );\r\n", +" ptr_record->wc_heap_size_intra_frame = ptr_record->block_size;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* check, if this is the new worst-case for inter-frame heap memory */\r\n", +" if ( size_current_inter_frame_heap > size_wc_inter_frame_heap )\r\n", +" {\r\n", +" if ( n_items_current_inter_frame_heap >= max_items_wc_inter_frame_heap )\r\n", +" {\r\n", +" /* resize list, if needed */\r\n", +" max_items_wc_inter_frame_heap = n_items_current_inter_frame_heap + MAX_NUM_RECORDS_REALLOC_STEP;\r\n", +" list_wc_inter_frame_heap = realloc( list_wc_inter_frame_heap, max_items_wc_inter_frame_heap * sizeof( int ) );\r\n", +" }\r\n", +"\r\n", +" /* copy current-frame list to worst-case list */\r\n", +" memmove( list_wc_inter_frame_heap, list_current_inter_frame_heap, n_items_current_inter_frame_heap * sizeof( int ) );\r\n", +" n_items_wc_inter_frame_heap = n_items_current_inter_frame_heap;\r\n", +" size_wc_inter_frame_heap = size_current_inter_frame_heap;\r\n", +" location_wc_inter_frame_heap = update_cnt;\r\n", +"\r\n", +" /* update the wc numbers in all individual records */\r\n", +" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n", +" {\r\n", +" i_record = list_wc_inter_frame_heap[i];\r\n", +" ptr_record = &( allocation_list[i_record] );\r\n", +" ptr_record->wc_heap_size_inter_frame = ptr_record->block_size;\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* reset heap allocation call tree */\r\n", +" heap_allocation_call_tree_size = 0;\r\n", +"\r\n", +" /* de-allocate list of intra-frame heap memory blocks in the current fraeme - it's needed only inside this function */\r\n", +" if ( list_current_intra_frame_heap )\r\n", +" {\r\n", +" free( list_current_intra_frame_heap );\r\n", +" }\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * subst()\r\n", +" *\r\n", +" * Substitute character in string\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static void subst( char *s, char from, char to )\r\n", +"{\r\n", +" while ( *s == from )\r\n", +" {\r\n", +" *s++ = to;\r\n", +" }\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * mem_count_summary()\r\n", +" *\r\n", +" * Print detailed (per-item) information about heap memory usage\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"static void mem_count_summary( void )\r\n", +"{\r\n", +" int i, j, index, index_record;\r\n", +" size_t length;\r\n", +" char buf[300], format_str[50], name_str[MAX_FUNCTION_NAME_LENGTH + 3], parms_str[MAX_PARAMS_LENGTH + 1], type_str[10], usage_str[20], size_str[20], line_str[10];\r\n", +" allocator_record *ptr_record, *ptr;\r\n", +"\r\n", +" /* Prepare format string */\r\n", +" sprintf( format_str, \"%%-%d.%ds %%5.5s %%6.6s %%-%d.%ds %%20.20s %%6.6s \", 50, 50, 50, 50 );\r\n", +"\r\n", +" if ( n_items_wc_intra_frame_heap > 0 )\r\n", +" {\r\n", +" /* Intra-Frame Heap Size */\r\n", +" fprintf( stdout, \"\\nList of memory blocks when maximum intra-frame heap size is reached:\\n\\n\" );\r\n", +"\r\n", +" /* Find duplicate records (same hash and worst-case heap size) */\r\n", +" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n", +" {\r\n", +" index_record = list_wc_intra_frame_heap[i];\r\n", +" if ( index_record == -1 )\r\n", +" {\r\n", +" continue;\r\n", +" }\r\n", +"\r\n", +" ptr_record = &( allocation_list[index_record] );\r\n", +" for ( j = i + 1; j < n_items_wc_intra_frame_heap; j++ )\r\n", +" {\r\n", +" index = list_wc_intra_frame_heap[j];\r\n", +" if ( index == -1 )\r\n", +" {\r\n", +" continue;\r\n", +" }\r\n", +" ptr = &( allocation_list[index] );\r\n", +"\r\n", +" if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_intra_frame == ptr_record->wc_heap_size_intra_frame )\r\n", +" {\r\n", +" ptr_record->noccurances++;\r\n", +" list_wc_intra_frame_heap[j] = -1;\r\n", +" }\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Print Header */\r\n", +" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Maximum Size\", \"Usage\" );\r\n", +" puts( buf );\r\n", +" length = strlen( buf );\r\n", +" sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n", +" subst( buf, '0', '-' );\r\n", +" puts( buf );\r\n", +"\r\n", +" for ( i = 0; i < n_items_wc_intra_frame_heap; i++ )\r\n", +" {\r\n", +" index_record = list_wc_intra_frame_heap[i];\r\n", +"\r\n", +" if ( index_record != -1 )\r\n", +" {\r\n", +" /* get the record */\r\n", +" ptr_record = &( allocation_list[index_record] );\r\n", +"\r\n", +" /* prepare information strings */\r\n", +" strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH );\r\n", +" strcat( name_str, \"()\" );\r\n", +" name_str[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n", +" strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH );\r\n", +" parms_str[MAX_PARAMS_LENGTH] = '\\0';\r\n", +"\r\n", +" if ( ptr_record->params[0] == 'm' )\r\n", +" {\r\n", +" strcpy( type_str, \"malloc\" );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" strcpy( type_str, \"calloc\" );\r\n", +" }\r\n", +"\r\n", +" sprintf( line_str, \"%d\", ptr_record->lineno );\r\n", +"\r\n", +" /* prepare average usage & memory size strings */\r\n", +" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 1 ) ) * 100.0f ) );\r\n", +"\r\n", +" if ( ptr_record->noccurances > 1 )\r\n", +" {\r\n", +" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" sprintf( size_str, \"%d %s\", (int) ( ptr_record->wc_heap_size_intra_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +"\r\n", +" sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str );\r\n", +" puts( buf );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, \"\\n\" );\r\n", +" }\r\n", +"\r\n", +" if ( n_items_wc_inter_frame_heap > 0 )\r\n", +" {\r\n", +" /* Inter-Frame Heap Size */\r\n", +" fprintf( stdout, \"\\nList of memory blocks when maximum inter-frame heap size is reached:\\n\\n\" );\r\n", +"\r\n", +" /* Find duplicate records (same hash and worst-case heap size) */\r\n", +" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n", +" {\r\n", +" index_record = list_wc_inter_frame_heap[i];\r\n", +" if ( index_record == -1 )\r\n", +" {\r\n", +" continue;\r\n", +" }\r\n", +" ptr_record = &( allocation_list[index_record] );\r\n", +" ptr_record->noccurances = 1; /* reset the counter as some blocks may have been both, intra-frame and inter-frame */\r\n", +" for ( j = i + 1; j < n_items_wc_inter_frame_heap; j++ )\r\n", +" {\r\n", +" index = list_wc_inter_frame_heap[j];\r\n", +" if ( index == -1 )\r\n", +" {\r\n", +" continue;\r\n", +" }\r\n", +" ptr = &( allocation_list[index] );\r\n", +"\r\n", +" if ( ptr->hash == ptr_record->hash && ptr->wc_heap_size_inter_frame == ptr_record->wc_heap_size_inter_frame )\r\n", +" {\r\n", +" ptr_record->noccurances++;\r\n", +" list_wc_inter_frame_heap[j] = -1;\r\n", +" }\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" /* Print Header */\r\n", +" sprintf( buf, format_str, \"Function Name\", \"Line\", \"Type\", \"Function Parameters\", \"Memory Size\", \"Usage\" );\r\n", +" puts( buf );\r\n", +" length = strlen( buf );\r\n", +" sprintf( buf, \"%0*d\\n\", (int) length - 1, 0 );\r\n", +" subst( buf, '0', '-' );\r\n", +" puts( buf );\r\n", +"\r\n", +" for ( i = 0; i < n_items_wc_inter_frame_heap; i++ )\r\n", +" {\r\n", +" index_record = list_wc_inter_frame_heap[i];\r\n", +"\r\n", +" if ( index_record != -1 )\r\n", +" {\r\n", +" /* get the record */\r\n", +" ptr_record = &( allocation_list[index_record] );\r\n", +"\r\n", +" /* prepare information strings */\r\n", +" strncpy( name_str, ptr_record->name, MAX_FUNCTION_NAME_LENGTH );\r\n", +" strcat( name_str, \"()\" );\r\n", +" name_str[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n", +" strncpy( parms_str, &( ptr_record->params[2] ), MAX_PARAMS_LENGTH );\r\n", +" parms_str[MAX_PARAMS_LENGTH] = '\\0';\r\n", +"\r\n", +" if ( ptr_record->params[0] == 'm' )\r\n", +" {\r\n", +" strcpy( type_str, \"malloc\" );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" strcpy( type_str, \"calloc\" );\r\n", +" }\r\n", +"\r\n", +" sprintf( line_str, \"%d\", ptr_record->lineno );\r\n", +"\r\n", +" /* prepare average usage & memory size strings */\r\n", +" sprintf( usage_str, \"%d%%\", (int) ( ( (float) ptr_record->total_used_size / ( ptr_record->total_block_size + 0.1f ) ) * 100.0f + 0.5f ) );\r\n", +"\r\n", +" if ( ptr_record->noccurances > 1 )\r\n", +" {\r\n", +" sprintf( size_str, \"%dx%d %s\", ptr_record->noccurances, (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" sprintf( size_str, \"%d %s\", (int) ( ptr_record->wc_heap_size_inter_frame >> Stat_Cnt_Size ), Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +"\r\n", +" sprintf( buf, format_str, name_str, line_str, type_str, parms_str, size_str, usage_str );\r\n", +" puts( buf );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, \"\\n\" );\r\n", +" }\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * print_mem()\r\n", +" *\r\n", +" * Print information about ROM and RAM memory usage\r\n", +" *--------------------------------------------------------------------*/\r\n", +"\r\n", +"void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] )\r\n", +"{\r\n", +" int i, nElem;\r\n", +"\r\n", +" fprintf( stdout, \"\\n\\n --- Memory usage --- \\n\\n\" );\r\n", +"\r\n", +" if ( Const_Data_PROM_Table != NULL )\r\n", +" {\r\n", +" nElem = 0;\r\n", +" while ( strcmp( Const_Data_PROM_Table[nElem].file_spec, \"\" ) != 0 )\r\n", +" nElem++;\r\n", +"\r\n", +" for ( i = 0; i < nElem; i++ )\r\n", +" {\r\n", +" if ( Stat_Cnt_Size > 0 )\r\n", +" {\r\n", +" /* words */\r\n", +" fprintf( stdout, \"Program ROM size (%s): %d words\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" /* bytes (here, we assume that each instruction takes PROM_INST_SIZE bits of the PROM memory) */\r\n", +" fprintf( stdout, \"Program ROM size (%s): %d bytes\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].PROM_size * ( PROM_INST_SIZE / 8 ) );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" for ( i = 0; i < nElem; i++ )\r\n", +" {\r\n", +" if ( Const_Data_PROM_Table[i].Get_Const_Data_Size_Func == NULL )\r\n", +" {\r\n", +" fprintf( stdout, \"Error: Cannot retrieve or calculate Table ROM size of (%s)!\\n\", Const_Data_PROM_Table[i].file_spec );\r\n", +" }\r\n", +"\r\n", +" fprintf( stdout, \"Table ROM (const data) size (%s): %d %s\\n\", Const_Data_PROM_Table[i].file_spec, Const_Data_PROM_Table[i].Get_Const_Data_Size_Func() >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size] );\r\n", +" }\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" fprintf( stdout, \"Program ROM size: not available\\n\" );\r\n", +" fprintf( stdout, \"Table ROM (const data) size: not available\\n\" );\r\n", +" }\r\n", +"\r\n", +" if ( wc_ram_size > 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum RAM (stack + heap) size: %d %s in frame %d\\n\", wc_ram_size >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], wc_ram_frame );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum RAM (stack + heap) size: not available\\n\" );\r\n", +" }\r\n", +"\r\n", +" /* check, if the stack is empty */\r\n", +" if ( ptr_current_stack != ptr_base_stack )\r\n", +" {\r\n", +" fprintf( stderr, \"Warning: Stack is not empty.\\n\" );\r\n", +" }\r\n", +"\r\n", +" if ( ptr_base_stack - ptr_max_stack > 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum stack size: %lu %s in frame %d\\n\", ( ( ptr_base_stack - ptr_max_stack ) * sizeof( int16_t ) ) >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size],\r\n", +" wc_stack_frame );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum stack size: not available\\n\" );\r\n", +" }\r\n", +"\r\n", +" /* last update of intra-frame memory and inter-frame memory, if needed */\r\n", +" if ( heap_allocation_call_tree_size > 0 )\r\n", +" {\r\n", +" update_mem();\r\n", +" }\r\n", +"\r\n", +" /* check, if all memory blocks have been deallocated (freed) */\r\n", +" for ( i = 0; i < Num_Records; i++ )\r\n", +" {\r\n", +" if ( allocation_list[i].block_ptr != NULL )\r\n", +" {\r\n", +" fprintf( stderr, \"Fct=%s, Ln=%i: %s!\\n\", allocation_list[i].name, allocation_list[i].lineno, \"Error: Memory Block has not been De-Allocated with free()!\" );\r\n", +" exit( -1 );\r\n", +" }\r\n", +" }\r\n", +"\r\n", +" if ( n_items_wc_intra_frame_heap > 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum intra-frame heap size: %d %s in frame %d\\n\", size_wc_intra_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_intra_frame_heap );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum intra-frame heap size: 0\\n\" );\r\n", +" }\r\n", +"\r\n", +" if ( n_items_wc_inter_frame_heap > 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum inter-frame heap size: %d %s in frame %d\\n\", size_wc_inter_frame_heap >> Stat_Cnt_Size, Count_Unit[Stat_Cnt_Size], location_wc_inter_frame_heap );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" fprintf( stdout, \"Maximum inter-frame heap size: 0\\n\" );\r\n", +" }\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +" /* Print detailed information about worst-case stack usage */\r\n", +" if ( ptr_base_stack - ptr_max_stack > 0 )\r\n", +" {\r\n", +" print_stack_call_tree();\r\n", +" }\r\n", +"\r\n", +" /* Print detailed information about worst-case heap usage */\r\n", +" mem_count_summary();\r\n", +"#endif\r\n", +"\r\n", +" if ( Stat_Cnt_Size > 0 )\r\n", +" {\r\n", +" /* words */\r\n", +" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", 8 << Stat_Cnt_Size );\r\n", +" }\r\n", +" else\r\n", +" {\r\n", +" /* bytes */\r\n", +" fprintf( stdout, \"\\nNote: The Program ROM size is calculated under the assumption that 1 instruction word is stored with %d bits\\n\", PROM_INST_SIZE );\r\n", +" }\r\n", +" fprintf( stdout, \"Note: The Data ROM size is calculated using the sizeof(type) built-in function\\n\" );\r\n", +"\r\n", +" if ( n_items_wc_intra_frame_heap > 0 )\r\n", +" {\r\n", +" fprintf( stdout, \"Intra-frame heap memory is allocated and de-allocated in the same frame\\n\" );\r\n", +" }\r\n", +"\r\n", +" /* De-allocate list of heap memory blocks */\r\n", +" if ( allocation_list != NULL )\r\n", +" {\r\n", +" free( allocation_list );\r\n", +" }\r\n", +"\r\n", +" /* De-allocate list of stack records */\r\n", +" if ( stack_callers[0] != NULL )\r\n", +" {\r\n", +" free( stack_callers[0] );\r\n", +" }\r\n", +"\r\n", +" if ( stack_callers[1] != NULL )\r\n", +" {\r\n", +" free( stack_callers[1] );\r\n", +" }\r\n", +"\r\n", +" /* De-allocate heap allocation call tree */\r\n", +" if ( heap_allocation_call_tree != NULL )\r\n", +" {\r\n", +" free( heap_allocation_call_tree );\r\n", +" }\r\n", +"\r\n", +" /* De-allocate intra-frame and inter-frame heap lists */\r\n", +" if ( list_wc_intra_frame_heap != NULL )\r\n", +" {\r\n", +" free( list_wc_intra_frame_heap );\r\n", +" }\r\n", +"\r\n", +" if ( list_current_inter_frame_heap != NULL )\r\n", +" {\r\n", +" free( list_current_inter_frame_heap );\r\n", +" }\r\n", +"\r\n", +" if ( list_wc_inter_frame_heap != NULL )\r\n", +" {\r\n", +" free( list_wc_inter_frame_heap );\r\n", +" }\r\n", +"\r\n", +"#ifdef MEM_COUNT_DETAILS\r\n", +" if ( fid_csv_filename != NULL )\r\n", +" {\r\n", +" fclose( fid_csv_filename );\r\n", +" }\r\n", +"#endif\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"#endif /* WMOPS */\r\n", +"\r\n", +"#ifdef CONTROL_CODE_OPS\r\n", +"\r\n", +"int LT_16( short var1, short var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( var1 < var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].LT_16++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int GT_16( short var1, short var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( var1 > var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].GT_16++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int LE_16( short var1, short var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( var1 <= var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].LE_16++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int GE_16( short var1, short var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( var1 >= var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].GE_16++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int EQ_16( short var1, short var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( var1 == var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].EQ_16++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int NE_16( short var1, short var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( var1 != var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].NE_16++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int LT_32( int L_var1, int L_var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( L_var1 < L_var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].LT_32++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int GT_32( int L_var1, int L_var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( L_var1 > L_var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].GT_32++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int LE_32( int L_var1, int L_var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( L_var1 <= L_var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].LE_32++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int GE_32( int L_var1, int L_var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( L_var1 >= L_var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].GE_32++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int EQ_32( int L_var1, int L_var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( L_var1 == L_var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].EQ_32++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int NE_32( int L_var1, int L_var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( L_var1 != L_var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].NE_32++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int LT_64( long long int L64_var1, long long int L64_var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( L64_var1 < L64_var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].LT_64++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int GT_64( long long int L64_var1, long long int L64_var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( L64_var1 > L64_var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].GT_64++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int LE_64( long long int L64_var1, long long int L64_var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( L64_var1 <= L64_var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].LE_64++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"int GE_64( long long int L64_var1, long long int L64_var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( L64_var1 >= L64_var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].GE_64++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"int EQ_64( long long int L64_var1, long long int L64_var2 )\r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( L64_var1 == L64_var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].EQ_64++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"int NE_64( long long int L64_var1, long long int L64_var2 ) \r\n", +"{\r\n", +" int F_ret = 0;\r\n", +"\r\n", +" if ( L64_var1 != L64_var2 )\r\n", +" {\r\n", +" F_ret = 1;\r\n", +" }\r\n", +"#ifdef WMOPS\r\n", +" multiCounter[currCounter].NE_64++;\r\n", +"#endif\r\n", +" return F_ret;\r\n", +"}\r\n", +"\r\n", +"#endif /* #ifdef CONTROL_CODE_OPS */\r\n", +"\r\n", +"#ifdef WMOPS\r\n", +"\r\n", +"void incrIf( const char *func_name )\r\n", +"{\r\n", +" /* Technical note: If the \"IF\" operator comes just after an \"ELSE\", its counter must not be incremented */\r\n", +" /* The following auxiliary variables are used to check if the \"IF\" operator doesn't immediately follow an \"ELSE\" operator */\r\n", +" if ( ( (int) currCounter != funcId_where_last_call_to_else_occurred ) || ( strncmp( func_name, func_name_where_last_call_to_else_occurred, MAX_FUNCTION_NAME_LENGTH ) != 0 ) || ( TotalWeightedOperation( currCounter) != funcid_total_wmops_at_last_call_to_else ) || ( call_occurred == 1 ) )\r\n", +" multiCounter[currCounter].If++;\r\n", +"\r\n", +" call_occurred = 0;\r\n", +" funcId_where_last_call_to_else_occurred = -100;\r\n", +"}\r\n", +"\r\n", +"void incrElse( const char *func_name )\r\n", +"{\r\n", +" multiCounter[currCounter].If++;\r\n", +"\r\n", +" /* Save the BASOP counter Id in the last function in which ELSE() has been called */\r\n", +" funcId_where_last_call_to_else_occurred = currCounter;\r\n", +"\r\n", +" /* Save the BASOP comeplxity in the last call of the ELSE() statement */\r\n", +" funcid_total_wmops_at_last_call_to_else = TotalWeightedOperation( currCounter );\r\n", +"\r\n", +" /* Save the function name in the last call of the ELSE() statement */\r\n", +" strncpy( func_name_where_last_call_to_else_occurred, func_name, MAX_FUNCTION_NAME_LENGTH );\r\n", +" func_name_where_last_call_to_else_occurred[MAX_FUNCTION_NAME_LENGTH] = '\\0';\r\n", +"\r\n", +" /* Set call_occurred to 0 to prevent counting of complexity of the next \"immediate\" IF statement */\r\n", +" call_occurred = 0;\r\n", +"}\r\n", +"\r\n", +"long TotalWeightedOperation( unsigned int CounterId )\r\n", +"{\r\n", +" int i;\r\n", +" unsigned int *ptr, *ptr2;\r\n", +" long tot;\r\n", +"\r\n", +" tot = 0;\r\n", +" ptr = (unsigned int *) &multiCounter[CounterId];\r\n", +" ptr2 = (unsigned int *) &op_weight;\r\n", +"\r\n", +" for ( i = 0; i < (int) ( sizeof( multiCounter[CounterId] ) / sizeof( unsigned int ) ); i++ )\r\n", +" {\r\n", +" if ( *ptr == UINT_MAX )\r\n", +" {\r\n", +" printf( \"\\nError in BASOP complexity counters: multiCounter[%d][%d] = %d !!!\\n\", CounterId, i, *ptr );\r\n", +" exit( -1 );\r\n", +" }\r\n", +"\r\n", +" tot += ( ( *ptr++ ) * ( *ptr2++ ) );\r\n", +" }\r\n", +"\r\n", +" return ( tot );\r\n", +"}\r\n", +"\r\n", +"long DeltaWeightedOperation( unsigned int CounterId )\r\n", +"{\r\n", +" long NewWOper, delta;\r\n", +"\r\n", +" NewWOper = TotalWeightedOperation( CounterId );\r\n", +"\r\n", +" delta = NewWOper - wmops[CounterId].LastWOper;\r\n", +" wmops[CounterId].LastWOper = NewWOper;\r\n", +"\r\n", +" return ( delta );\r\n", +"}\r\n", +"\r\n", +"/* Resets BASOP operation counter */\r\n", +"void Reset_BASOP_WMOPS_counter( unsigned int counterId )\r\n", +"{\r\n", +" int i;\r\n", +" long *ptr;\r\n", +"\r\n", +" /* reset the current BASOP operation counter */\r\n", +" ptr = (long *) &multiCounter[counterId];\r\n", +" for ( i = 0; i < (int) ( sizeof( multiCounter[counterId] ) / sizeof( long ) ); i++ )\r\n", +" {\r\n", +" *ptr++ = 0;\r\n", +" }\r\n", +"\r\n", +" wmops[counterId].LastWOper = 0;\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"#endif\r\n", \ No newline at end of file diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index 0313dce..fde3701 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -1,1232 +1,1232 @@ -"/*\r\n" -" * (C) 2024 copyright VoiceAge Corporation. All Rights Reserved.\r\n" -" *\r\n" -" * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n" -" * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n" -" * or refer to ITU-T Recommendation G.191 on \"SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS\".\r\n" -" *\r\n" -" * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor\r\n" -" * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software\r\n" -" * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE.\r\n" -" *\r\n" -" * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca)\r\n" -" */\r\n" -"\r\n" -"#ifndef WMOPS_H\r\n" -"#define WMOPS_H\r\n" -"\r\n" -"#ifndef EXIT_FAILURE\r\n" -"#include /* stdlib is needed for exit() */\r\n" -"#endif\r\n" -"\r\n" -"#ifndef EOF\r\n" -"#include /* stdio is needed for fprintf() */\r\n" -"#endif\r\n" -"\r\n" -"/* To Prevent \"warning: '$' in identifier or number\" message under GCC */\r\n" -"#ifdef __GNUC__\r\n" -"#pragma GCC system_header\r\n" -"#endif\r\n" -"\r\n" -"#define ENH_32_BIT_OPERATOR\r\n" -"#define ENH_64_BIT_OPERATOR\r\n" -"#define ENH_U_32_BIT_OPERATOR\r\n" -"#define COMPLEX_OPERATOR\r\n" -"#define CONTROL_CODE_OPS /* enable control code operators such as LT_16, GT_16, ... */\r\n" -"\r\n" -"#ifdef WMOPS\r\n" -"enum instructions\r\n" -"{\r\n" -" _ADD,\r\n" -" _ABS,\r\n" -" _MULT,\r\n" -" _MAC,\r\n" -" _MOVE,\r\n" -" _STORE,\r\n" -" _LOGIC,\r\n" -" _SHIFT,\r\n" -" _BRANCH,\r\n" -" _DIV,\r\n" -" _SQRT,\r\n" -" _TRANS,\r\n" -" _FUNC,\r\n" -" _LOOP,\r\n" -" _INDIRECT,\r\n" -" _PTR_INIT,\r\n" -" _TEST,\r\n" -" _POWER,\r\n" -" _LOG,\r\n" -" _MISC,\r\n" -" NUM_INST\r\n" -"};\r\n" -"\r\n" -"extern double ops_cnt;\r\n" -"extern double inst_cnt[NUM_INST];\r\n" -"\r\n" -"/******************************************************************/\r\n" -"/* NOTES: */\r\n" -"/* The 'wmc_flag_' flag is global to avoid declaration in every */\r\n" -"/* function and 'static' to avoid clashing with other modules */\r\n" -"/* that include this header file. */\r\n" -"/* */\r\n" -"/* The declarations of 'wmc_flag_' and 'wops_' in this header */\r\n" -"/* file prevent the addition of a 'C' file to the Project. */\r\n" -"/******************************************************************/\r\n" -"\r\n" -"/* General Purpose Global int */\r\n" -"static int wmc_flag_ = 0;\r\n" -"\r\n" -"#define push_wmops( ... ) push_wmops_fct( __VA_ARGS__, NULL )\r\n" -"void push_wmops_fct( const char *label, ... );\r\n" -"void pop_wmops( void );\r\n" -"void reset_wmops( void );\r\n" -"void print_wmops( void );\r\n" -"void update_wmops( void );\r\n" -"void update_mem( void );\r\n" -"\r\n" -"#define _ADD_C 1\r\n" -"#define _ABS_C 1\r\n" -"#define _MULT_C 1\r\n" -"#define _MAC_C 1\r\n" -"#define _MOVE_C 1\r\n" -"#define _STORE_C 1\r\n" -"#define _LOGIC_C 1\r\n" -"#define _SHIFT_C 1\r\n" -"#define _BRANCH_C 4\r\n" -"#define _DIV_C 18\r\n" -"#define _SQRT_C 10\r\n" -"#define _TRANS_C 25\r\n" -"#define _FUNC_C 2 /* need to add number of arguments */\r\n" -"#define _LOOP_C 3\r\n" -"#define _INDIRECT_C 2\r\n" -"#define _PTR_INIT_C 1\r\n" -"#define _TEST_C 2\r\n" -"#define _POWER_C 25\r\n" -"#define _LOG_C 25\r\n" -"#define _MISC_C 1\r\n" -"\r\n" -"#define ADD( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _ADD_C * ( x ) ); \\\r\n" -" inst_cnt[_ADD] += ( x ); \\\r\n" -" }\r\n" -"#define ABS( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _ABS_C * ( x ) ); \\\r\n" -" inst_cnt[_ABS] += ( x ); \\\r\n" -" }\r\n" -"#define MULT( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _MULT_C * ( x ) ); \\\r\n" -" inst_cnt[_MULT] += ( x ); \\\r\n" -" }\r\n" -"#define MAC( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _MAC_C * ( x ) ); \\\r\n" -" inst_cnt[_MAC] += ( x ); \\\r\n" -" }\r\n" -"#define MOVE( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _MOVE_C * ( x ) ); \\\r\n" -" inst_cnt[_MOVE] += ( x ); \\\r\n" -" }\r\n" -"#define STORE( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _STORE_C * ( x ) ); \\\r\n" -" inst_cnt[_STORE] += ( x ); \\\r\n" -" }\r\n" -"#define LOGIC( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _LOGIC_C * ( x ) ); \\\r\n" -" inst_cnt[_LOGIC] += ( x ); \\\r\n" -" }\r\n" -"#define SHIFT( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _SHIFT_C * ( x ) ); \\\r\n" -" inst_cnt[_SHIFT] += ( x ); \\\r\n" -" }\r\n" -"#define BRANCH( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _BRANCH_C * ( x ) ); \\\r\n" -" inst_cnt[_BRANCH] += ( x ); \\\r\n" -" }\r\n" -"#define DIV( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _DIV_C * ( x ) ); \\\r\n" -" inst_cnt[_DIV] += ( x ); \\\r\n" -" }\r\n" -"#define SQRT( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _SQRT_C * ( x ) ); \\\r\n" -" inst_cnt[_SQRT] += ( x ); \\\r\n" -" }\r\n" -"#define TRANS( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _TRANS_C * ( x ) ); \\\r\n" -" inst_cnt[_TRANS] += ( x ); \\\r\n" -" }\r\n" -"#define LOOP( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _LOOP_C * ( x ) ); \\\r\n" -" inst_cnt[_LOOP] += ( x ); \\\r\n" -" }\r\n" -"#define INDIRECT( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _INDIRECT_C * ( x ) ); \\\r\n" -" inst_cnt[_INDIRECT] += ( x ); \\\r\n" -" }\r\n" -"#define PTR_INIT( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _PTR_INIT_C * ( x ) ); \\\r\n" -" inst_cnt[_PTR_INIT] += ( x ); \\\r\n" -" }\r\n" -"#define TEST( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _TEST_C * ( x ) ); \\\r\n" -" inst_cnt[_TEST] += ( x ); \\\r\n" -" }\r\n" -"#define POWER( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _POWER_C * ( x ) ); \\\r\n" -" inst_cnt[_POWER] += ( x ); \\\r\n" -" }\r\n" -"#define LOG( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _LOG_C * ( x ) ); \\\r\n" -" inst_cnt[_LOG] += ( x ); \\\r\n" -" }\r\n" -"#define MISC( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _MISC_C * ( x ) ); \\\r\n" -" inst_cnt[_MISC] += ( x ); \\\r\n" -" }\r\n" -"#define FUNC( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( _FUNC_C + _MOVE_C * ( x ) ); \\\r\n" -" inst_cnt[_FUNC]++; \\\r\n" -" inst_cnt[_MOVE] += ( x ); \\\r\n" -" }\r\n" -"#define DADD( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _ADD_C * ( x ) ); \\\r\n" -" inst_cnt[_ADD] += ( x ); \\\r\n" -" }\r\n" -"#define DMULT( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _MULT_C * ( x ) ); \\\r\n" -" inst_cnt[_MULT] += ( x ); \\\r\n" -" }\r\n" -"#define DMAC( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _MAC_C * ( x ) ); \\\r\n" -" inst_cnt[_MAC] += ( x ); \\\r\n" -" }\r\n" -"#define DMOVE( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _MOVE_C * ( x ) ); \\\r\n" -" inst_cnt[_MOVE] += ( x ); \\\r\n" -" }\r\n" -"#define DSTORE( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _STORE_C * ( x ) ); \\\r\n" -" inst_cnt[_STORE] += ( x ); \\\r\n" -" }\r\n" -"#define DLOGIC( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _LOGIC_C * ( x ) ); \\\r\n" -" inst_cnt[_LOGIC] += ( x ); \\\r\n" -" }\r\n" -"#define DSHIFT( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _SHIFT_C * ( x ) ); \\\r\n" -" inst_cnt[_SHIFT] += ( x ); \\\r\n" -" }\r\n" -"#define DDIV( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _DIV_C * ( x ) ); \\\r\n" -" inst_cnt[_DIV] += ( x ); \\\r\n" -" }\r\n" -"#define DSQRT( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _SQRT_C * ( x ) ); \\\r\n" -" inst_cnt[_SQRT] += ( x ); \\\r\n" -" }\r\n" -"#define DTRANS( x ) \\\r\n" -" { \\\r\n" -" ops_cnt += ( 2 * _TRANS_C * ( x ) ); \\\r\n" -" inst_cnt[_TRANS] += ( x ); \\\r\n" -" } \r\n" -"\r\n" -"#else\r\n" -"\r\n" -"extern int cntr_push_pop;\r\n" -"#define push_wmops( x ) ( cntr_push_pop++ )\r\n" -"#define pop_wmops() ( cntr_push_pop-- )\r\n" -"#define reset_wmops()\r\n" -"#define print_wmops()\r\n" -"#define update_wmops() ( assert( cntr_push_pop == 0 ) )\r\n" -"#define update_mem()\r\n" -"\r\n" -"#define ADD( x )\r\n" -"#define ABS( x )\r\n" -"#define MULT( x )\r\n" -"#define MAC( x )\r\n" -"#define MOVE( x )\r\n" -"#define STORE( x )\r\n" -"#define LOGIC( x )\r\n" -"#define SHIFT( x )\r\n" -"#define BRANCH( x )\r\n" -"#define DIV( x )\r\n" -"#define SQRT( x )\r\n" -"#define TRANS( x )\r\n" -"#define FUNC( x )\r\n" -"#define LOOP( x )\r\n" -"#define INDIRECT( x )\r\n" -"#define PTR_INIT( x )\r\n" -"#define TEST( x )\r\n" -"#define POWER( x )\r\n" -"#define LOG( x )\r\n" -"#define MISC( x )\r\n" -"\r\n" -"#define DADD( x )\r\n" -"#define DMULT( x )\r\n" -"#define DMAC( x )\r\n" -"#define DMOVE( x )\r\n" -"#define DSTORE( x )\r\n" -"#define DLOGIC( x )\r\n" -"#define DSHIFT( x )\r\n" -"#define DDIV( x )\r\n" -"#define DSQRT( x )\r\n" -"#define DTRANS( x )\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"#ifndef WMOPS\r\n" -"/* DESACTIVATE the Counting Mechanism */\r\n" -"#define OP_COUNT_( op, n )\r\n" -"\r\n" -"/* DESACTIVATE Operation Counter Wrappers */\r\n" -"#define OP_COUNT_WRAPPER1_( op, val ) ( val )\r\n" -"#define OP_COUNT_WRAPPER2_( expr )\r\n" -"#define OP_COUNT_WRAPPER3_( op, expr ) expr\r\n" -"\r\n" -"/* DESACTIVATE Logical & Ternary Operators */\r\n" -"#define __\r\n" -"#define _\r\n" -"\r\n" -"#else\r\n" -"\r\n" -"/* Operation Counter Wrappers */\r\n" -"#define OP_COUNT_( op, x ) ( ops_cnt += ( op##_C * ( x ) ), inst_cnt[op] += ( x ) )\r\n" -"#define OP_COUNT_WRAPPER1_( op, val ) ( op, val )\r\n" -"#define OP_COUNT_WRAPPER2_( expr ) \\\r\n" -" if ( expr, 0 ) \\\r\n" -" ; \\\r\n" -" else\r\n" -"#define OP_COUNT_WRAPPER3_( op, expr ) \\\r\n" -" if ( op, 0 ) \\\r\n" -" ; \\\r\n" -" else \\\r\n" -" expr\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"/* Define all Macros without '{' & '}' (None of these should be called externally!) */\r\n" -"#define ABS_( x ) OP_COUNT_( _ABS, ( x ) )\r\n" -"#define ADD_( x ) OP_COUNT_( _ADD, ( x ) )\r\n" -"#define MULT_( x ) OP_COUNT_( _MULT, ( x ) )\r\n" -"#define MAC_( x ) OP_COUNT_( _MAC, ( x ) )\r\n" -"#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) )\r\n" -"#define STORE_( x ) OP_COUNT_( _STORE, ( x ) )\r\n" -"#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) )\r\n" -"#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) )\r\n" -"#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) )\r\n" -"#define DIV_( x ) OP_COUNT_( _DIV, ( x ) )\r\n" -"#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) )\r\n" -"#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) )\r\n" -"#define POWER_( x ) TRANS_( x )\r\n" -"#define LOG_( x ) TRANS_( x )\r\n" -"#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) )\r\n" -"#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) )\r\n" -"#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) )\r\n" -"#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) )\r\n" -"#define MISC_( x ) ABS_( x )\r\n" -"\r\n" -"/* Math Operations */\r\n" -"#define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs )\r\n" -"#define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs )\r\n" -"#define fabsf_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabsf )\r\n" -"#define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs )\r\n" -"#define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor )\r\n" -"#define floorf_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floorf )\r\n" -"#define sqrt_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrt )\r\n" -"#define sqrtf_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf )\r\n" -"#define pow_ OP_COUNT_WRAPPER1_( POWER_( 1 ), pow )\r\n" -"#define powf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), powf )\r\n" -"#define exp_ OP_COUNT_WRAPPER1_( POWER_( 1 ), exp )\r\n" -"#define expf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), expf )\r\n" -"#define log_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log )\r\n" -"#define logf_ OP_COUNT_WRAPPER1_( LOG_( 1 ), logf )\r\n" -"#define log10_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10 )\r\n" -"#define log10f_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10f )\r\n" -"#define cos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cos )\r\n" -"#define cosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosf )\r\n" -"#define sin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sin )\r\n" -"#define sinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinf )\r\n" -"#define tan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tan )\r\n" -"#define tanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanf )\r\n" -"#define acos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acos )\r\n" -"#define acosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acosf )\r\n" -"#define asin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asin )\r\n" -"#define asinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asinf )\r\n" -"#define atan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan )\r\n" -"#define atanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atanf )\r\n" -"#define atan2_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2 )\r\n" -"#define atan2f_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2f )\r\n" -"#define cosh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosh )\r\n" -"#define coshf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), coshf )\r\n" -"#define sinh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinh )\r\n" -"#define sinhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinhf )\r\n" -"#define tanh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanh )\r\n" -"#define tanhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanhf )\r\n" -"#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod )\r\n" -"#define fmodf_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmodf )\r\n" -"#define frexp_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexp )\r\n" -"#define frexpf_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexpf )\r\n" -"\r\n" -"/* the macros below are instrumented versions of user-defined macros that might be used in the source code \r\n" -" representing some well-known and recognized mathematical operations (that are not defined in math.h) \r\n" -" Note: the 'wmc_flag_=wmc_flag_' is used to avoid warning: left-hand operand of comma expression has no effect with gcc */\r\n" -"\r\n" -"#define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) )\r\n" -"#define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) )\r\n" -"#define MIN_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MIN( ( a ), ( b ) ) )\r\n" -"#define MAX_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MAX( ( a ), ( b ) ) )\r\n" -"#define Min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Min( ( a ), ( b ) ) )\r\n" -"#define Max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Max( ( a ), ( b ) ) )\r\n" -"#define sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), sqr( ( x ) ) )\r\n" -"#define Sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Sqr( ( x ) ) )\r\n" -"#define SQR_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQR( ( x ) ) )\r\n" -"#define square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), square( ( x ) ) )\r\n" -"#define Square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Square( ( x ) ) )\r\n" -"#define SQUARE_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQUARE( ( x ) ) )\r\n" -"#define sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), sign( ( x ) ) )\r\n" -"#define Sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), Sign( ( x ) ) )\r\n" -"#define SIGN_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), SIGN( ( x ) ) )\r\n" -"#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) )\r\n" -"#define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrtf( ( x ) ) )\r\n" -"#define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) )\r\n" -"#define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) )\r\n" -"#define log2f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2f( ( x ) ) )\r\n" -"#define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) )\r\n" -"#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) )\r\n" -"#define round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round( ( x ) ) )\r\n" -"#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) )\r\n" -"#define roundf_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, roundf( ( x ) ) )\r\n" -"#define set_min_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_min( ( a ), ( b ) ) )\r\n" -"#define set_max_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_max( ( a ), ( b ) ) )\r\n" -"\r\n" -"/* Functions */\r\n" -"#define func_( name, x ) OP_COUNT_WRAPPER1_( FUNC_( x ), name )\r\n" -"\r\n" -"/* Logical Operators */\r\n" -"#ifndef __\r\n" -"#define __ ( BRANCH_( 1 ), 1 ) &&\r\n" -"#endif\r\n" -"\r\n" -"/* Ternary Operators (? and :) */\r\n" -"#ifndef _\r\n" -"#define _ ( BRANCH_( 1 ), 0 ) ? 0:\r\n" -"#endif\r\n" -"\r\n" -"/* Flow Control keywords */\r\n" -"#define if_ \\\r\n" -" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n" -" if\r\n" -"#define for_ OP_COUNT_WRAPPER2_( LOOP_(1)) for\r\n" -"#define while_( c ) \\\r\n" -" while \\\r\n" -" OP_COUNT_WRAPPER1_( BRANCH_( 1 ), ( c ) ) /* needs extra \"()\" if ',' encountered */\r\n" -"#define do_ \\\r\n" -" do \\\r\n" -" {\r\n" -"#define _while \\\r\n" -" BRANCH_( 1 ); \\\r\n" -" } \\\r\n" -" while\r\n" -"\r\n" -"#define goto_ \\\r\n" -" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n" -" goto\r\n" -"#define break_ \\\r\n" -" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n" -" break\r\n" -"#define continue_ \\\r\n" -" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n" -" continue\r\n" -"#define return_ \\\r\n" -" OP_COUNT_WRAPPER2_( ( wmc_flag_ = stack_tree_level_, STACK_DEPTH_FCT_RETURN ) ) \\\r\n" -" return\r\n" -"#define switch_ \\\r\n" -" OP_COUNT_WRAPPER2_( ( BRANCH_( 1 ), wmc_flag_ = 1 ) ) \\\r\n" -" switch\r\n" -"#define cost_( n ) OP_COUNT_WRAPPER2_( wmc_flag_ ? ( ADD_( n ), BRANCH_( n ), wmc_flag_ = 0 ) : 0 );\r\n" -"\r\n" -"#ifdef WMOPS\r\n" -"\r\n" -"#define ACC 2\r\n" -"#define MUL 1\r\n" -"\r\n" -"/* Counting Function (should not be called externally!) */\r\n" -"static void wops_( const char *ops )\r\n" -"{\r\n" -" char lm = 0; /* lm: Last Operation is Math */\r\n" -" static char lo = 0; /* Last Operation */\r\n" -"\r\n" -" void ( *fct )( const char *ops ) = wops_;\r\n" -"\r\n" -"st:\r\n" -" while ( *ops != '\\0' )\r\n" -" {\r\n" -" switch ( *ops++ )\r\n" -" {\r\n" -" int cnt;\r\n" -" case '-':\r\n" -" for ( cnt = 0; ops[cnt] == '>'; cnt++ )\r\n" -" ;\r\n" -" if ( cnt & 1 )\r\n" -" goto ind;\r\n" -" case '+':\r\n" -" lm = 2;\r\n" -" if ( lo & MUL )\r\n" -" {\r\n" -" MULT_( -1 );\r\n" -" MAC_( 1 );\r\n" -" break;\r\n" -" }\r\n" -" lo = ACC << 2;\r\n" -" case 'U':\r\n" -" case 'D':\r\n" -" ADD_( 1 );\r\n" -" break;\r\n" -" case '*':\r\n" -" lm = 2;\r\n" -" if ( lo & ACC )\r\n" -" {\r\n" -" ADD_( -1 );\r\n" -" MAC_( 1 );\r\n" -" break;\r\n" -" }\r\n" -" lo = MUL << 2;\r\n" -" MULT_( 1 );\r\n" -" break;\r\n" -" case '/':\r\n" -" case '%':\r\n" -" lm = 2;\r\n" -" DIV_( 1 );\r\n" -" break;\r\n" -" case '&':\r\n" -" case '|':\r\n" -" case '^':\r\n" -" lm = 2;\r\n" -" case '~':\r\n" -" LOGIC_( 1 );\r\n" -" break;\r\n" -" case '<':\r\n" -" case '>':\r\n" -" if ( *ops != ops[-1] )\r\n" -" goto error;\r\n" -" ops++;\r\n" -" case -85:\r\n" -" case -69:\r\n" -" lm = 2;\r\n" -" SHIFT_( 1 );\r\n" -" break;\r\n" -" case 'L':\r\n" -" case 'G':\r\n" -" if ( *ops == 't' )\r\n" -" goto comp;\r\n" -" case 'E':\r\n" -" case 'N':\r\n" -" if ( *ops != 'e' )\r\n" -" goto error;\r\n" -" comp:\r\n" -" ops++;\r\n" -" ADD_( 1 );\r\n" -" break;\r\n" -" case '!':\r\n" -" MISC_( 2 );\r\n" -" break;\r\n" -" case 'M':\r\n" -" MOVE_( 1 );\r\n" -" break;\r\n" -" case 'S':\r\n" -" STORE_( 1 );\r\n" -" break;\r\n" -" case 'P':\r\n" -" PTR_INIT_( 1 );\r\n" -" break;\r\n" -" case '[':\r\n" -" case ']':\r\n" -" goto st;\r\n" -" ind:\r\n" -" ops++;\r\n" -" case 'I':\r\n" -" case '.':\r\n" -" INDIRECT_( 1 );\r\n" -" break;\r\n" -" case '=':\r\n" -" if ( lm )\r\n" -" goto st;\r\n" -" case '\\0':\r\n" -" /* This Shouldn't Happen */\r\n" -" /* These are Used to Avoid: \"warning: 'name' defined but not used\" with Cygwin gcc Compiler */\r\n" -" wmc_flag_ = wmc_flag_;\r\n" -" fct( \"\" );\r\n" -" error:\r\n" -" default:\r\n" -" fprintf( stderr, \"\\r wops: Invalid Counting Operation '%s'\\n\", ops - 1 );\r\n" -" exit( -1 );\r\n" -" }\r\n" -" lm >>= 1;\r\n" -" lo >>= 2;\r\n" -" }\r\n" -"\r\n" -" return;\r\n" -"}\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"/* All Other Operations */\r\n" -"#define $( str ) OP_COUNT_WRAPPER2_( wops_( str ) )\r\n" -"\r\n" -"\r\n" -"/*-------------------------------------------------------------------*\r\n" -" * Memory counting tool\r\n" -" *-------------------------------------------------------------------*/\r\n" -"\r\n" -"/* Enhanced Const Data Size Counting (Rounding Up to the Nearest 'Integer' Size) */\r\n" -"#define rsize( item ) ( ( sizeof( item ) + sizeof( int ) - 1 ) / sizeof( int ) * sizeof( int ) )\r\n" -"\r\n" -"#ifdef _MSC_VER\r\n" -"/* Disable \"warning C4210: nonstandard extension used : function given file scope\" with Visual Studio Compiler */\r\n" -"#pragma warning( disable : 4210 )\r\n" -"#endif\r\n" -"\r\n" -"/* Const Data Size and PROM Size Wrapper Functions */\r\n" -"#define Const_Data_Size_Func( file ) Const_Data_Size_##file( void )\r\n" -"#define Get_Const_Data_Size( file, val_ptr ) \\\r\n" -" { \\\r\n" -" extern int Const_Data_Size_##file( void ); \\\r\n" -" *( val_ptr ) = Const_Data_Size_##file(); \\\r\n" -" }\r\n" -"#define PROM_Size_Func( file ) PROM_Size_##file( void )\r\n" -"#define Get_PROM_Size( file, val_ptr ) \\\r\n" -" { \\\r\n" -" int PROM_Size_##file( void ); \\\r\n" -" *( val_ptr ) = PROM_Size_##file(); \\\r\n" -" }\r\n" -"\r\n" -"/* ROM Size Lookup Table - contains information about PROM size and Const Data Size in all source files */\r\n" -"/* The print_mem() function looks for this table to print the results of Const Data usage and PROM usage */\r\n" -"typedef struct ROM_Size_Lookup_Table\r\n" -"{\r\n" -" const char file_spec[255];\r\n" -" int PROM_size;\r\n" -" int ( *Get_Const_Data_Size_Func )( void );\r\n" -"} ROM_Size_Lookup_Table;\r\n" -"\r\n" -"/* The WMC tool inserts the following declaration during the innstrumentation process in the .c file where the function print_mem() is located */\r\n" -"/* and modifies it to print_mem(Const_Data_PROM_Table) */\r\n" -"\r\n" -"/* #ifdef WMOPS\r\n" -" * ROM_Size_Lookup_Table Const_Data_PROM_Table[] =\r\n" -" * {\r\n" -" * {\"../lib_enc/rom_enc.c\", 0, NULL},\r\n" -" * {\"../lib_com/[star].c\", 0, NULL},\r\n" -" * {\"\", -1, NULL}\r\n" -" * };\r\n" -" * #endif\r\n" -" */\r\n" -"\r\n" -"/*#define MEM_ALIGN_64BITS */ /* Define this when using 64 Bits values in the code (ex: double), otherwise it will align on 32 Bits */\r\n" -"/*#define MEM_COUNT_DETAILS*/\r\n" -"\r\n" -"typedef enum\r\n" -"{\r\n" -" USE_BYTES = 0,\r\n" -" USE_16BITS = 1,\r\n" -" USE_32BITS = 2\r\n" -"} Counting_Size;\r\n" -"\r\n" -"\r\n" -"#ifdef WMOPS\r\n" -"\r\n" -"void *mem_alloc( const char *func_name, int func_lineno, size_t size, char *alloc_str );\r\n" -"void mem_free( const char *func_name, int func_lineno, void *ptr );\r\n" -"\r\n" -"#define malloc_( size ) mem_alloc( __func__, __LINE__, size, \"m:\" #size )\r\n" -"#define calloc_( n, size ) mem_alloc( __func__, __LINE__, ( n ) * ( size ), \"c:\" #n \", \" #size )\r\n" -"#define free_( ptr ) mem_free( __func__, __LINE__, ptr )\r\n" -"\r\n" -"void reset_mem( Counting_Size cnt_size );\r\n" -"void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] );\r\n" -"\r\n" -"int push_stack( const char *filename, const char *fctname );\r\n" -"int pop_stack( const char *filename, const char *fctname );\r\n" -"\r\n" -"#ifdef WMOPS_DETAIL\r\n" -"#define STACK_DEPTH_FCT_CALL ( push_wmops( __func__, \"[WMC_AUTO]\" ), push_stack( __FILE__, __func__ ) ) /* add push_wmops() in all function calls */\r\n" -"#define STACK_DEPTH_FCT_RETURN ( pop_wmops(), pop_stack( __FILE__, __func__ ) ) /* add pop_wmops() in all function returns */\r\n" -"#else\r\n" -"#define STACK_DEPTH_FCT_CALL push_stack( __FILE__, __func__ )\r\n" -"#define STACK_DEPTH_FCT_RETURN pop_stack( __FILE__, __func__ )\r\n" -"#endif\r\n" -"\r\n" -"void reset_stack( void );\r\n" -"#define func_start_ int stack_tree_level_ = STACK_DEPTH_FCT_CALL;\r\n" -"\r\n" -"#else\r\n" -"#define malloc_( n1 ) malloc( n1 )\r\n" -"#define calloc_( n1, n2 ) calloc( n1, n2 )\r\n" -"#define free_( ptr ) free( ptr )\r\n" -"#define reset_mem( cnt_size )\r\n" -"#define print_mem( Const_Data_PROM_Table )\r\n" -"\r\n" -"#define push_stack( file, fct )\r\n" -"#define pop_stack( file, fct )\r\n" -"#define reset_stack()\r\n" -"#define func_start_\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"/* Global counter variable for calculation of complexity weight */\r\n" -"typedef struct\r\n" -"{\r\n" -" unsigned int add; /* Complexity Weight of 1 */\r\n" -" unsigned int sub; /* Complexity Weight of 1 */\r\n" -" unsigned int abs_s; /* Complexity Weight of 1 */\r\n" -" unsigned int shl; /* Complexity Weight of 1 */\r\n" -" unsigned int shr; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int extract_h; /* Complexity Weight of 1 */\r\n" -" unsigned int extract_l; /* Complexity Weight of 1 */\r\n" -" unsigned int mult; /* Complexity Weight of 1 */\r\n" -" unsigned int L_mult; /* Complexity Weight of 1 */\r\n" -" unsigned int negate; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int round; /* Complexity Weight of 1 */\r\n" -" unsigned int L_mac; /* Complexity Weight of 1 */\r\n" -" unsigned int L_msu; /* Complexity Weight of 1 */\r\n" -" unsigned int L_macNs; /* Complexity Weight of 1 */\r\n" -" unsigned int L_msuNs; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L_add; /* Complexity Weight of 1 */\r\n" -" unsigned int L_sub; /* Complexity Weight of 1 */\r\n" -" unsigned int L_add_c; /* Complexity Weight of 2 */\r\n" -" unsigned int L_sub_c; /* Complexity Weight of 2 */\r\n" -" unsigned int L_negate; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L_shl; /* Complexity Weight of 1 */\r\n" -" unsigned int L_shr; /* Complexity Weight of 1 */\r\n" -" unsigned int mult_r; /* Complexity Weight of 1 */\r\n" -" unsigned int shr_r; /* Complexity Weight of 3 */\r\n" -" unsigned int mac_r; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int msu_r; /* Complexity Weight of 1 */\r\n" -" unsigned int L_deposit_h; /* Complexity Weight of 1 */\r\n" -" unsigned int L_deposit_l; /* Complexity Weight of 1 */\r\n" -" unsigned int L_shr_r; /* Complexity Weight of 3 */\r\n" -" unsigned int L_abs; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L_sat; /* Complexity Weight of 4 */\r\n" -" unsigned int norm_s; /* Complexity Weight of 1 */\r\n" -" unsigned int div_s; /* Complexity Weight of 18 */\r\n" -" unsigned int norm_l; /* Complexity Weight of 1 */\r\n" -" unsigned int move16; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int move32; /* Complexity Weight of 2 */\r\n" -" unsigned int Logic16; /* Complexity Weight of 1 */\r\n" -" unsigned int Logic32; /* Complexity Weight of 2 */\r\n" -" unsigned int Test; /* Complexity Weight of 2 */\r\n" -" unsigned int s_max; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int s_min; /* Complexity Weight of 1 */\r\n" -" unsigned int L_max; /* Complexity Weight of 1 */\r\n" -" unsigned int L_min; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_max; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_min; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int shl_r; /* Complexity Weight of 2 */\r\n" -" unsigned int L_shl_r; /* Complexity Weight of 2 */\r\n" -" unsigned int L40_shr_r; /* Complexity Weight of 2 */\r\n" -" unsigned int L40_shl_r; /* Complexity Weight of 2 */\r\n" -" unsigned int norm_L40; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L40_shl; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_shr; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_negate; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_add; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_sub; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L40_abs; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_mult; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_mac; /* Complexity Weight of 1 */\r\n" -" unsigned int mac_r40; /* Complexity Weight of 2 */\r\n" -"\r\n" -" unsigned int L40_msu; /* Complexity Weight of 1 */\r\n" -" unsigned int msu_r40; /* Complexity Weight of 2 */\r\n" -" unsigned int Mpy_32_16_ss; /* Complexity Weight of 2 */\r\n" -" unsigned int Mpy_32_32_ss; /* Complexity Weight of 2 */\r\n" -" unsigned int L_mult0; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L_mac0; /* Complexity Weight of 1 */\r\n" -" unsigned int L_msu0; /* Complexity Weight of 1 */\r\n" -" unsigned int lshl; /* Complexity Weight of 1 */\r\n" -" unsigned int lshr; /* Complexity Weight of 1 */\r\n" -" unsigned int L_lshl; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L_lshr; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_lshl; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_lshr; /* Complexity Weight of 1 */\r\n" -" unsigned int s_and; /* Complexity Weight of 1 */\r\n" -" unsigned int s_or; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int s_xor; /* Complexity Weight of 1 */\r\n" -" unsigned int L_and; /* Complexity Weight of 1 */\r\n" -" unsigned int L_or; /* Complexity Weight of 1 */\r\n" -" unsigned int L_xor; /* Complexity Weight of 1 */\r\n" -" unsigned int rotl; /* Complexity Weight of 3 */\r\n" -"\r\n" -" unsigned int rotr; /* Complexity Weight of 3 */\r\n" -" unsigned int L_rotl; /* Complexity Weight of 3 */\r\n" -" unsigned int L_rotr; /* Complexity Weight of 3 */\r\n" -" unsigned int L40_set; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_deposit_h; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L40_deposit_l; /* Complexity Weight of 1 */\r\n" -" unsigned int L40_deposit32; /* Complexity Weight of 1 */\r\n" -" unsigned int Extract40_H; /* Complexity Weight of 1 */\r\n" -" unsigned int Extract40_L; /* Complexity Weight of 1 */\r\n" -" unsigned int L_Extract40; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int L40_round; /* Complexity Weight of 1 */\r\n" -" unsigned int L_saturate40; /* Complexity Weight of 1 */\r\n" -" unsigned int round40; /* Complexity Weight of 1 */\r\n" -" unsigned int If; /* Complexity Weight of 3 */\r\n" -" unsigned int Goto; /* Complexity Weight of 2 */\r\n" -"\r\n" -" unsigned int Break; /* Complexity Weight of 2 */\r\n" -" unsigned int Switch; /* Complexity Weight of 6 */\r\n" -" unsigned int For; /* Complexity Weight of 3 */\r\n" -" unsigned int While; /* Complexity Weight of 3 */\r\n" -" unsigned int Continue; /* Complexity Weight of 2 */\r\n" -"\r\n" -" unsigned int L_mls; /* Complexity Weight of 1 */\r\n" -" unsigned int div_l; /* Complexity Weight of 32 */\r\n" -" unsigned int i_mult; /* Complexity Weight of 1 */\r\n" -"\r\n" -"/* New complex basic operators */\r\n" -"#ifdef COMPLEX_OPERATOR\r\n" -" unsigned int CL_shr; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_shl; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_add; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_sub; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_scale; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_dscale; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_msu_j; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_mac_j; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_move; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_Extract_real; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_Extract_imag; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_form; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_multr_32x16; /* Complexity Weight of 2 */\r\n" -" unsigned int CL_negate; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_conjugate; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_mul_j; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_swap_real_imag; /* Complexity Weight of 1 */\r\n" -" unsigned int C_add; /* Complexity Weight of 1 */\r\n" -" unsigned int C_sub; /* Complexity Weight of 1 */\r\n" -" unsigned int C_mul_j; /* Complexity Weight of 1 */\r\n" -" unsigned int C_multr; /* Complexity Weight of 2 */\r\n" -" unsigned int C_form; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int C_scale; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_round32_16; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_scale_32; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_dscale_32; /* Complexity Weight of 1 */\r\n" -" unsigned int CL_multr_32x32; /* Complexity Weight of 2 */\r\n" -" unsigned int C_mac_r; /* Complexity Weight of 2 */\r\n" -" unsigned int C_msu_r; /* Complexity Weight of 2 */\r\n" -" unsigned int C_Extract_real; /* Complexity Weight of 1 */\r\n" -" unsigned int C_Extract_imag; /* Complexity Weight of 1 */\r\n" -" unsigned int C_negate; /* Complexity Weight of 1 */\r\n" -" unsigned int C_conjugate; /* Complexity Weight of 1 */\r\n" -" unsigned int C_shr; /* Complexity Weight of 1 */\r\n" -" unsigned int C_shl; /* Complexity Weight of 1 */\r\n" -"\r\n" -"#endif /* #ifdef COMPLEX_OPERATOR */\r\n" -"\r\n" -"/* New 64 bit basops */\r\n" -"#ifdef ENH_64_BIT_OPERATOR\r\n" -" unsigned int move64; /* Complexity Weight of 1 */\r\n" -" unsigned int W_add_nosat; /* Complexity Weight of 1 */\r\n" -" unsigned int W_sub_nosat; /* Complexity Weight of 1 */\r\n" -" unsigned int W_shl; /* Complexity Weight of 1 */\r\n" -" unsigned int W_shr; /* Complexity Weight of 1 */\r\n" -" unsigned int W_shl_nosat; /* Complexity Weight of 1 */\r\n" -" unsigned int W_shr_nosat; /* Complexity Weight of 1 */\r\n" -" unsigned int W_mac_32_16; /* Complexity Weight of 1 */\r\n" -" unsigned int W_msu_32_16; /* Complexity Weight of 1 */\r\n" -" unsigned int W_mult_32_16; /* Complexity Weight of 1 */\r\n" -" unsigned int W_mult0_16_16; /* Complexity Weight of 1 */\r\n" -" unsigned int W_mac0_16_16; /* Complexity Weight of 1 */\r\n" -" unsigned int W_msu0_16_16; /* Complexity Weight of 1 */\r\n" -" unsigned int W_mult_16_16; /* Complexity Weight of 1 */\r\n" -" unsigned int W_mac_16_16; /* Complexity Weight of 1 */\r\n" -" unsigned int W_msu_16_16; /* Complexity Weight of 1 */\r\n" -" unsigned int W_shl_sat_l; /* Complexity Weight of 1 */\r\n" -" unsigned int W_sat_l; /* Complexity Weight of 1 */\r\n" -" unsigned int W_sat_m; /* Complexity Weight of 1 */\r\n" -" unsigned int W_deposit32_l; /* Complexity Weight of 1 */\r\n" -" unsigned int W_deposit32_h; /* Complexity Weight of 1 */\r\n" -" unsigned int W_extract_l; /* Complexity Weight of 1 */\r\n" -" unsigned int W_extract_h; /* Complexity Weight of 1 */\r\n" -" unsigned int W_round48_L; /* Complexity Weight of 1 */\r\n" -" unsigned int W_round32_s; /* Complexity Weight of 1 */\r\n" -" unsigned int W_norm; /* Complexity Weight of 1 */\r\n" -"\r\n" -" unsigned int W_add; /* Complexity Weight of 1 */\r\n" -" unsigned int W_sub; /* Complexity Weight of 1 */\r\n" -" unsigned int W_neg; /* Complexity Weight of 1 */\r\n" -" unsigned int W_abs; /* Complexity Weight of 1 */\r\n" -" unsigned int W_mult_32_32; /* Complexity Weight of 1 */\r\n" -" unsigned int W_mult0_32_32; /* Complexity Weight of 1 */\r\n" -" unsigned int W_lshl; /* Complexity Weight of 1 */\r\n" -" unsigned int W_lshr; /* Complexity Weight of 1 */\r\n" -" unsigned int W_round64_L; /* Complexity Weight of 1 */\r\n" -"\r\n" -"#endif /* #ifdef ENH_64_BIT_OPERATOR */\r\n" -"\r\n" -"#ifdef ENH_32_BIT_OPERATOR\r\n" -" unsigned int Mpy_32_16_1; /* Complexity Weight of 1 */\r\n" -" unsigned int Mpy_32_16_r; /* Complexity Weight of 1 */\r\n" -" unsigned int Mpy_32_32; /* Complexity Weight of 1 */\r\n" -" unsigned int Mpy_32_32_r; /* Complexity Weight of 1 */\r\n" -" unsigned int Madd_32_16; /* Complexity Weight of 1 */\r\n" -" unsigned int Madd_32_16_r; /* Complexity Weight of 1 */\r\n" -" unsigned int Msub_32_16; /* Complexity Weight of 1 */\r\n" -" unsigned int Msub_32_16_r; /* Complexity Weight of 1 */\r\n" -" unsigned int Madd_32_32; /* Complexity Weight of 1 */\r\n" -" unsigned int Madd_32_32_r; /* Complexity Weight of 1 */\r\n" -" unsigned int Msub_32_32; /* Complexity Weight of 1 */\r\n" -" unsigned int Msub_32_32_r; /* Complexity Weight of 1 */\r\n" -"#endif /* #ifdef ENH_32_BIT_OPERATOR */\r\n" -"\r\n" -"#ifdef ENH_U_32_BIT_OPERATOR\r\n" -" unsigned int UL_addNs; /* Complexity Weight of 1 */\r\n" -" unsigned int UL_subNs; /* Complexity Weight of 1 */\r\n" -" unsigned int UL_Mpy_32_32; /* Complexity Weight of 1 */\r\n" -" unsigned int Mpy_32_32_uu; /* Complexity Weight of 2 */\r\n" -" unsigned int Mpy_32_16_uu; /* Complexity Weight of 2 */\r\n" -" unsigned int norm_ul_float; /* Complexity Weight of 1 */\r\n" -" unsigned int UL_deposit_l; /* Complexity Weight of 1 */\r\n" -"#endif /* #ifdef ENH_U_32_BIT_OPERATOR */\r\n" -"\r\n" -"#ifdef CONTROL_CODE_OPS\r\n" -" unsigned int LT_16; /* Complexity Weight of 1 */\r\n" -" unsigned int GT_16; /* Complexity Weight of 1 */\r\n" -" unsigned int LE_16; /* Complexity Weight of 1 */\r\n" -" unsigned int GE_16; /* Complexity Weight of 1 */\r\n" -" unsigned int EQ_16; /* Complexity Weight of 1 */\r\n" -" unsigned int NE_16; /* Complexity Weight of 1 */\r\n" -" unsigned int LT_32; /* Complexity Weight of 1 */\r\n" -" unsigned int GT_32; /* Complexity Weight of 1 */\r\n" -" unsigned int LE_32; /* Complexity Weight of 1 */\r\n" -" unsigned int GE_32; /* Complexity Weight of 1 */\r\n" -" unsigned int EQ_32; /* Complexity Weight of 1 */\r\n" -" unsigned int NE_32; /* Complexity Weight of 1 */\r\n" -" unsigned int LT_64; /* Complexity Weight of 1 */\r\n" -" unsigned int GT_64; /* Complexity Weight of 1 */\r\n" -" unsigned int LE_64; /* Complexity Weight of 1 */\r\n" -" unsigned int GE_64; /* Complexity Weight of 1 */\r\n" -" unsigned int EQ_64; /* Complexity Weight of 1 */\r\n" -" unsigned int NE_64; /* Complexity Weight of 1 */\r\n" -"\r\n" -"#endif /* #ifdef CONTROL_CODE_OPS */\r\n" -"} BASIC_OP;\r\n" -"\r\n" -"#ifdef WMOPS\r\n" -"extern BASIC_OP *multiCounter;\r\n" -"extern unsigned int currCounter;\r\n" -"extern int funcId_where_last_call_to_else_occurred;\r\n" -"extern long funcid_total_wmops_at_last_call_to_else;\r\n" -"extern int call_occurred;\r\n" -"\r\n" -"long TotalWeightedOperation( unsigned int counterId );\r\n" -"long DeltaWeightedOperation( unsigned int counterId );\r\n" -"void Reset_BASOP_WMOPS_counter( unsigned int counterId );\r\n" -"\r\n" -"#endif\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : FOR\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro FOR should be used instead of the 'for' C statement.\r\n" -" * The complexity is independent of the number of loop iterations that are\r\n" -" * performed.\r\n" -" *\r\n" -" * Complexity weight : 3 (regardless of number of iterations).\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define FOR( a ) for ( a )\r\n" -"\r\n" -"#else /* ifndef WMOPS */\r\n" -"#define FOR( a ) \\\r\n" -" if ( incrFor(), 0 ) \\\r\n" -" ; \\\r\n" -" else \\\r\n" -" for ( a )\r\n" -"\r\n" -"static __inline void incrFor( void )\r\n" -"{\r\n" -" multiCounter[currCounter].For++;\r\n" -"}\r\n" -"#endif /* ifndef WMOPS */\r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : WHILE\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro WHILE should be used instead of the 'while' C statement.\r\n" -" * The complexity is proportional to the number of loop iterations that\r\n" -" * are performed.\r\n" -" *\r\n" -" * Complexity weight : 4 x 'number of loop iterations'.\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define WHILE( a ) while ( a )\r\n" -"\r\n" -"#else /* ifndef WMOPS */\r\n" -"#define WHILE( a ) while ( incrWhile(), a )\r\n" -"\r\n" -"static __inline void incrWhile( void )\r\n" -"{\r\n" -" multiCounter[currCounter].While++;\r\n" -"}\r\n" -"#endif /* ifndef WMOPS */\r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : DO\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro DO should be used instead of the 'do' C statement.\r\n" -" *\r\n" -" * Complexity weight : 0 (complexity counted by WHILE macro).\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define DO do\r\n" -"\r\n" -"#else /* ifndef WMOPS */\r\n" -"#define DO do\r\n" -"\r\n" -"#endif /* ifndef WMOPS */\r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : IF\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro IF should :\r\n" -" *\r\n" -" * - not be used when :\r\n" -" * - the 'if' structure does not have any 'else if' nor 'else' statement\r\n" -" * - and it conditions only one DSP basic operations.\r\n" -" *\r\n" -" * - be used instead of the 'if' C statement in every other case :\r\n" -" * - when there is an 'else' or 'else if' statement,\r\n" -" * - or when the 'if' conditions several DSP basic operations,\r\n" -" * - or when the 'if' conditions a function call.\r\n" -" *\r\n" -" * Complexity weight : 3\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"\r\n" -"#ifndef WMOPS\r\n" -"#define IF( a ) if ( a )\r\n" -"#else /* ifndef WMOPS */\r\n" -"#define IF( a ) if ( incrIf( __func__ ), a )\r\n" -"void incrIf( const char *func_name );\r\n" -"#endif /* ifndef WMOPS */\r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : ELSE\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro ELSE should be used instead of the 'else' C statement.\r\n" -" *\r\n" -" * Complexity weight : 3\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"\r\n" -"#ifndef WMOPS\r\n" -"#define ELSE else\r\n" -"#else /* ifndef WMOPS */\r\n" -"#define ELSE else if ( incrElse( __func__ ), 0 ); else\r\n" -"void incrElse( const char *func_name );\r\n" -"#endif /* ifndef WMOPS */\r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : SWITCH\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro SWITCH should be used instead of the 'switch' C statement.\r\n" -" *\r\n" -" * Complexity weight : 6\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define SWITCH( a ) switch ( a )\r\n" -"\r\n" -"#else /* ifndef WMOPS */\r\n" -"#define SWITCH( a ) switch ( incrSwitch(), a )\r\n" -"\r\n" -"static __inline void incrSwitch( void )\r\n" -"{\r\n" -" multiCounter[currCounter].Switch++;\r\n" -"}\r\n" -"#endif /* ifndef WMOPS */\r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : CONTINUE\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro CONTINUE should be used instead of the 'continue' C statement.\r\n" -" *\r\n" -" * Complexity weight : 2\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define CONTINUE continue\r\n" -"\r\n" -"#else /* ifndef WMOPS */\r\n" -"#define CONTINUE \\\r\n" -" if ( incrContinue(), 0 ) \\\r\n" -" ; \\\r\n" -" else \\\r\n" -" continue\r\n" -"\r\n" -"static __inline void incrContinue( void )\r\n" -"{\r\n" -" multiCounter[currCounter].Continue++;\r\n" -"}\r\n" -"#endif /* ifndef WMOPS */\r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : BREAK\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro BREAK should be used instead of the 'break' C statement.\r\n" -" *\r\n" -" * Complexity weight : 2\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define BREAK break\r\n" -"\r\n" -"#else /* ifndef WMOPS */\r\n" -"#define BREAK \\\r\n" -" if ( incrBreak(), 0 ) \\\r\n" -" ; \\\r\n" -" else \\\r\n" -" break\r\n" -"\r\n" -"static __inline void incrBreak( void )\r\n" -"{\r\n" -" multiCounter[currCounter].Break++;\r\n" -"}\r\n" -"#endif /* ifndef WMOPS */\r\n" -"\r\n" -"\r\n" -"/*****************************************************************************\r\n" -" *\r\n" -" * Function Name : GOTO\r\n" -" *\r\n" -" * Purpose :\r\n" -" *\r\n" -" * The macro GOTO should be used instead of the 'goto' C statement.\r\n" -" *\r\n" -" * Complexity weight : 2\r\n" -" *\r\n" -" *****************************************************************************/\r\n" -"#ifndef WMOPS\r\n" -"#define GOTO goto\r\n" -"\r\n" -"#else /* ifndef WMOPS */\r\n" -"#define GOTO \\\r\n" -" if ( incrGoto(), 0 ) \\\r\n" -" ; \\\r\n" -" else \\\r\n" -" goto\r\n" -"\r\n" -"static __inline void incrGoto( void )\r\n" -"{\r\n" -" multiCounter[currCounter].Goto++;\r\n" -"}\r\n" -"#endif /* ifndef WMOPS */\r\n" -"\r\n" -"\r\n" -"#ifdef CONTROL_CODE_OPS\r\n" -"\r\n" -"extern int LT_16( short var1, short var2 );\r\n" -"extern int GT_16( short var1, short var2 );\r\n" -"extern int LE_16( short var1, short var2 );\r\n" -"extern int GE_16( short var1, short var2 );\r\n" -"extern int EQ_16( short var1, short var2 );\r\n" -"extern int NE_16( short var1, short var2 );\r\n" -"\r\n" -"extern int LT_32( int L_var1, int L_var2 );\r\n" -"extern int GT_32( int L_var1, int L_var2 );\r\n" -"extern int LE_32( int L_var1, int L_var2 );\r\n" -"extern int GE_32( int L_var1, int L_var2 );\r\n" -"extern int EQ_32( int L_var1, int L_var2 );\r\n" -"extern int NE_32( int L_var1, int L_var2 );\r\n" -"\r\n" -"extern int LT_64( long long int L64_var1, long long int L64_var2 );\r\n" -"extern int GT_64( long long int L64_var1, long long int L64_var2 );\r\n" -"extern int LE_64( long long int L64_var1, long long int L64_var2 );\r\n" -"extern int GE_64( long long int L64_var1, long long int L64_var2 );\r\n" -"extern int EQ_64( long long int L64_var1, long long int L64_var2 );\r\n" -"extern int NE_64( long long int L64_var1, long long int L64_var2 );\r\n" -"\r\n" -"#endif /* #ifdef CONTROL_CODE_OPS */\r\n" -"\r\n" -"\r\n" -"#endif /* WMOPS_H */\r\n" -"\r\n" \ No newline at end of file +"/*\r\n", +" * (C) 2024 copyright VoiceAge Corporation. All Rights Reserved.\r\n", +" *\r\n", +" * This software is protected by copyright law and by international treaties. The source code, and all of its derivations,\r\n", +" * is provided by VoiceAge Corporation under the \"ITU-T Software Tools' General Public License\". Please, read the license file\r\n", +" * or refer to ITU-T Recommendation G.191 on \"SOFTWARE TOOLS FOR SPEECH AND AUDIO CODING STANDARDS\".\r\n", +" *\r\n", +" * Any use of this software is permitted provided that this notice is not removed and that neither the authors nor\r\n", +" * VoiceAge Corporation are deemed to have made any representations as to the suitability of this software\r\n", +" * for any purpose nor are held responsible for any defects of this software. THERE IS NO WARRANTY FOR THIS SOFTWARE.\r\n", +" *\r\n", +" * Authors: Guy Richard, Vladimir Malenovsky (Vladimir.Malenovsky@USherbrooke.ca)\r\n", +" */\r\n", +"\r\n", +"#ifndef WMOPS_H\r\n", +"#define WMOPS_H\r\n", +"\r\n", +"#ifndef EXIT_FAILURE\r\n", +"#include /* stdlib is needed for exit() */\r\n", +"#endif\r\n", +"\r\n", +"#ifndef EOF\r\n", +"#include /* stdio is needed for fprintf() */\r\n", +"#endif\r\n", +"\r\n", +"/* To Prevent \"warning: '$' in identifier or number\" message under GCC */\r\n", +"#ifdef __GNUC__\r\n", +"#pragma GCC system_header\r\n", +"#endif\r\n", +"\r\n", +"#define ENH_32_BIT_OPERATOR\r\n", +"#define ENH_64_BIT_OPERATOR\r\n", +"#define ENH_U_32_BIT_OPERATOR\r\n", +"#define COMPLEX_OPERATOR\r\n", +"#define CONTROL_CODE_OPS /* enable control code operators such as LT_16, GT_16, ... */\r\n", +"\r\n", +"#ifdef WMOPS\r\n", +"enum instructions\r\n", +"{\r\n", +" _ADD,\r\n", +" _ABS,\r\n", +" _MULT,\r\n", +" _MAC,\r\n", +" _MOVE,\r\n", +" _STORE,\r\n", +" _LOGIC,\r\n", +" _SHIFT,\r\n", +" _BRANCH,\r\n", +" _DIV,\r\n", +" _SQRT,\r\n", +" _TRANS,\r\n", +" _FUNC,\r\n", +" _LOOP,\r\n", +" _INDIRECT,\r\n", +" _PTR_INIT,\r\n", +" _TEST,\r\n", +" _POWER,\r\n", +" _LOG,\r\n", +" _MISC,\r\n", +" NUM_INST\r\n", +"};\r\n", +"\r\n", +"extern double ops_cnt;\r\n", +"extern double inst_cnt[NUM_INST];\r\n", +"\r\n", +"/******************************************************************/\r\n", +"/* NOTES: */\r\n", +"/* The 'wmc_flag_' flag is global to avoid declaration in every */\r\n", +"/* function and 'static' to avoid clashing with other modules */\r\n", +"/* that include this header file. */\r\n", +"/* */\r\n", +"/* The declarations of 'wmc_flag_' and 'wops_' in this header */\r\n", +"/* file prevent the addition of a 'C' file to the Project. */\r\n", +"/******************************************************************/\r\n", +"\r\n", +"/* General Purpose Global int */\r\n", +"static int wmc_flag_ = 0;\r\n", +"\r\n", +"#define push_wmops( ... ) push_wmops_fct( __VA_ARGS__, NULL )\r\n", +"void push_wmops_fct( const char *label, ... );\r\n", +"void pop_wmops( void );\r\n", +"void reset_wmops( void );\r\n", +"void print_wmops( void );\r\n", +"void update_wmops( void );\r\n", +"void update_mem( void );\r\n", +"\r\n", +"#define _ADD_C 1\r\n", +"#define _ABS_C 1\r\n", +"#define _MULT_C 1\r\n", +"#define _MAC_C 1\r\n", +"#define _MOVE_C 1\r\n", +"#define _STORE_C 1\r\n", +"#define _LOGIC_C 1\r\n", +"#define _SHIFT_C 1\r\n", +"#define _BRANCH_C 4\r\n", +"#define _DIV_C 18\r\n", +"#define _SQRT_C 10\r\n", +"#define _TRANS_C 25\r\n", +"#define _FUNC_C 2 /* need to add number of arguments */\r\n", +"#define _LOOP_C 3\r\n", +"#define _INDIRECT_C 2\r\n", +"#define _PTR_INIT_C 1\r\n", +"#define _TEST_C 2\r\n", +"#define _POWER_C 25\r\n", +"#define _LOG_C 25\r\n", +"#define _MISC_C 1\r\n", +"\r\n", +"#define ADD( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _ADD_C * ( x ) ); \\\r\n", +" inst_cnt[_ADD] += ( x ); \\\r\n", +" }\r\n", +"#define ABS( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _ABS_C * ( x ) ); \\\r\n", +" inst_cnt[_ABS] += ( x ); \\\r\n", +" }\r\n", +"#define MULT( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _MULT_C * ( x ) ); \\\r\n", +" inst_cnt[_MULT] += ( x ); \\\r\n", +" }\r\n", +"#define MAC( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _MAC_C * ( x ) ); \\\r\n", +" inst_cnt[_MAC] += ( x ); \\\r\n", +" }\r\n", +"#define MOVE( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _MOVE_C * ( x ) ); \\\r\n", +" inst_cnt[_MOVE] += ( x ); \\\r\n", +" }\r\n", +"#define STORE( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _STORE_C * ( x ) ); \\\r\n", +" inst_cnt[_STORE] += ( x ); \\\r\n", +" }\r\n", +"#define LOGIC( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _LOGIC_C * ( x ) ); \\\r\n", +" inst_cnt[_LOGIC] += ( x ); \\\r\n", +" }\r\n", +"#define SHIFT( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _SHIFT_C * ( x ) ); \\\r\n", +" inst_cnt[_SHIFT] += ( x ); \\\r\n", +" }\r\n", +"#define BRANCH( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _BRANCH_C * ( x ) ); \\\r\n", +" inst_cnt[_BRANCH] += ( x ); \\\r\n", +" }\r\n", +"#define DIV( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _DIV_C * ( x ) ); \\\r\n", +" inst_cnt[_DIV] += ( x ); \\\r\n", +" }\r\n", +"#define SQRT( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _SQRT_C * ( x ) ); \\\r\n", +" inst_cnt[_SQRT] += ( x ); \\\r\n", +" }\r\n", +"#define TRANS( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _TRANS_C * ( x ) ); \\\r\n", +" inst_cnt[_TRANS] += ( x ); \\\r\n", +" }\r\n", +"#define LOOP( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _LOOP_C * ( x ) ); \\\r\n", +" inst_cnt[_LOOP] += ( x ); \\\r\n", +" }\r\n", +"#define INDIRECT( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _INDIRECT_C * ( x ) ); \\\r\n", +" inst_cnt[_INDIRECT] += ( x ); \\\r\n", +" }\r\n", +"#define PTR_INIT( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _PTR_INIT_C * ( x ) ); \\\r\n", +" inst_cnt[_PTR_INIT] += ( x ); \\\r\n", +" }\r\n", +"#define TEST( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _TEST_C * ( x ) ); \\\r\n", +" inst_cnt[_TEST] += ( x ); \\\r\n", +" }\r\n", +"#define POWER( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _POWER_C * ( x ) ); \\\r\n", +" inst_cnt[_POWER] += ( x ); \\\r\n", +" }\r\n", +"#define LOG( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _LOG_C * ( x ) ); \\\r\n", +" inst_cnt[_LOG] += ( x ); \\\r\n", +" }\r\n", +"#define MISC( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _MISC_C * ( x ) ); \\\r\n", +" inst_cnt[_MISC] += ( x ); \\\r\n", +" }\r\n", +"#define FUNC( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( _FUNC_C + _MOVE_C * ( x ) ); \\\r\n", +" inst_cnt[_FUNC]++; \\\r\n", +" inst_cnt[_MOVE] += ( x ); \\\r\n", +" }\r\n", +"#define DADD( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _ADD_C * ( x ) ); \\\r\n", +" inst_cnt[_ADD] += ( x ); \\\r\n", +" }\r\n", +"#define DMULT( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _MULT_C * ( x ) ); \\\r\n", +" inst_cnt[_MULT] += ( x ); \\\r\n", +" }\r\n", +"#define DMAC( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _MAC_C * ( x ) ); \\\r\n", +" inst_cnt[_MAC] += ( x ); \\\r\n", +" }\r\n", +"#define DMOVE( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _MOVE_C * ( x ) ); \\\r\n", +" inst_cnt[_MOVE] += ( x ); \\\r\n", +" }\r\n", +"#define DSTORE( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _STORE_C * ( x ) ); \\\r\n", +" inst_cnt[_STORE] += ( x ); \\\r\n", +" }\r\n", +"#define DLOGIC( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _LOGIC_C * ( x ) ); \\\r\n", +" inst_cnt[_LOGIC] += ( x ); \\\r\n", +" }\r\n", +"#define DSHIFT( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _SHIFT_C * ( x ) ); \\\r\n", +" inst_cnt[_SHIFT] += ( x ); \\\r\n", +" }\r\n", +"#define DDIV( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _DIV_C * ( x ) ); \\\r\n", +" inst_cnt[_DIV] += ( x ); \\\r\n", +" }\r\n", +"#define DSQRT( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _SQRT_C * ( x ) ); \\\r\n", +" inst_cnt[_SQRT] += ( x ); \\\r\n", +" }\r\n", +"#define DTRANS( x ) \\\r\n", +" { \\\r\n", +" ops_cnt += ( 2 * _TRANS_C * ( x ) ); \\\r\n", +" inst_cnt[_TRANS] += ( x ); \\\r\n", +" } \r\n", +"\r\n", +"#else\r\n", +"\r\n", +"extern int cntr_push_pop;\r\n", +"#define push_wmops( x ) ( cntr_push_pop++ )\r\n", +"#define pop_wmops() ( cntr_push_pop-- )\r\n", +"#define reset_wmops()\r\n", +"#define print_wmops()\r\n", +"#define update_wmops() ( assert( cntr_push_pop == 0 ) )\r\n", +"#define update_mem()\r\n", +"\r\n", +"#define ADD( x )\r\n", +"#define ABS( x )\r\n", +"#define MULT( x )\r\n", +"#define MAC( x )\r\n", +"#define MOVE( x )\r\n", +"#define STORE( x )\r\n", +"#define LOGIC( x )\r\n", +"#define SHIFT( x )\r\n", +"#define BRANCH( x )\r\n", +"#define DIV( x )\r\n", +"#define SQRT( x )\r\n", +"#define TRANS( x )\r\n", +"#define FUNC( x )\r\n", +"#define LOOP( x )\r\n", +"#define INDIRECT( x )\r\n", +"#define PTR_INIT( x )\r\n", +"#define TEST( x )\r\n", +"#define POWER( x )\r\n", +"#define LOG( x )\r\n", +"#define MISC( x )\r\n", +"\r\n", +"#define DADD( x )\r\n", +"#define DMULT( x )\r\n", +"#define DMAC( x )\r\n", +"#define DMOVE( x )\r\n", +"#define DSTORE( x )\r\n", +"#define DLOGIC( x )\r\n", +"#define DSHIFT( x )\r\n", +"#define DDIV( x )\r\n", +"#define DSQRT( x )\r\n", +"#define DTRANS( x )\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"#ifndef WMOPS\r\n", +"/* DESACTIVATE the Counting Mechanism */\r\n", +"#define OP_COUNT_( op, n )\r\n", +"\r\n", +"/* DESACTIVATE Operation Counter Wrappers */\r\n", +"#define OP_COUNT_WRAPPER1_( op, val ) ( val )\r\n", +"#define OP_COUNT_WRAPPER2_( expr )\r\n", +"#define OP_COUNT_WRAPPER3_( op, expr ) expr\r\n", +"\r\n", +"/* DESACTIVATE Logical & Ternary Operators */\r\n", +"#define __\r\n", +"#define _\r\n", +"\r\n", +"#else\r\n", +"\r\n", +"/* Operation Counter Wrappers */\r\n", +"#define OP_COUNT_( op, x ) ( ops_cnt += ( op##_C * ( x ) ), inst_cnt[op] += ( x ) )\r\n", +"#define OP_COUNT_WRAPPER1_( op, val ) ( op, val )\r\n", +"#define OP_COUNT_WRAPPER2_( expr ) \\\r\n", +" if ( expr, 0 ) \\\r\n", +" ; \\\r\n", +" else\r\n", +"#define OP_COUNT_WRAPPER3_( op, expr ) \\\r\n", +" if ( op, 0 ) \\\r\n", +" ; \\\r\n", +" else \\\r\n", +" expr\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"/* Define all Macros without '{' & '}' (None of these should be called externally!) */\r\n", +"#define ABS_( x ) OP_COUNT_( _ABS, ( x ) )\r\n", +"#define ADD_( x ) OP_COUNT_( _ADD, ( x ) )\r\n", +"#define MULT_( x ) OP_COUNT_( _MULT, ( x ) )\r\n", +"#define MAC_( x ) OP_COUNT_( _MAC, ( x ) )\r\n", +"#define MOVE_( x ) OP_COUNT_( _MOVE, ( x ) )\r\n", +"#define STORE_( x ) OP_COUNT_( _STORE, ( x ) )\r\n", +"#define LOGIC_( x ) OP_COUNT_( _LOGIC, ( x ) )\r\n", +"#define SHIFT_( x ) OP_COUNT_( _SHIFT, ( x ) )\r\n", +"#define BRANCH_( x ) OP_COUNT_( _BRANCH, ( x ) )\r\n", +"#define DIV_( x ) OP_COUNT_( _DIV, ( x ) )\r\n", +"#define SQRT_( x ) OP_COUNT_( _SQRT, ( x ) )\r\n", +"#define TRANS_( x ) OP_COUNT_( _TRANS, ( x ) )\r\n", +"#define POWER_( x ) TRANS_( x )\r\n", +"#define LOG_( x ) TRANS_( x )\r\n", +"#define LOOP_( x ) OP_COUNT_( _LOOP, ( x ) )\r\n", +"#define INDIRECT_( x ) OP_COUNT_( _INDIRECT, ( x ) )\r\n", +"#define PTR_INIT_( x ) OP_COUNT_( _PTR_INIT, ( x ) )\r\n", +"#define FUNC_( x ) ( OP_COUNT_( _MOVE, ( x ) ), OP_COUNT_( _FUNC, 1 ) )\r\n", +"#define MISC_( x ) ABS_( x )\r\n", +"\r\n", +"/* Math Operations */\r\n", +"#define abs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), abs )\r\n", +"#define fabs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabs )\r\n", +"#define fabsf_ OP_COUNT_WRAPPER1_( ABS_( 1 ), fabsf )\r\n", +"#define labs_ OP_COUNT_WRAPPER1_( ABS_( 1 ), labs )\r\n", +"#define floor_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floor )\r\n", +"#define floorf_ OP_COUNT_WRAPPER1_( MISC_( 1 ), floorf )\r\n", +"#define sqrt_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrt )\r\n", +"#define sqrtf_ OP_COUNT_WRAPPER1_( SQRT_( 1 ), sqrtf )\r\n", +"#define pow_ OP_COUNT_WRAPPER1_( POWER_( 1 ), pow )\r\n", +"#define powf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), powf )\r\n", +"#define exp_ OP_COUNT_WRAPPER1_( POWER_( 1 ), exp )\r\n", +"#define expf_ OP_COUNT_WRAPPER1_( POWER_( 1 ), expf )\r\n", +"#define log_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log )\r\n", +"#define logf_ OP_COUNT_WRAPPER1_( LOG_( 1 ), logf )\r\n", +"#define log10_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10 )\r\n", +"#define log10f_ OP_COUNT_WRAPPER1_( LOG_( 1 ), log10f )\r\n", +"#define cos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cos )\r\n", +"#define cosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosf )\r\n", +"#define sin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sin )\r\n", +"#define sinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinf )\r\n", +"#define tan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tan )\r\n", +"#define tanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanf )\r\n", +"#define acos_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acos )\r\n", +"#define acosf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), acosf )\r\n", +"#define asin_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asin )\r\n", +"#define asinf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), asinf )\r\n", +"#define atan_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan )\r\n", +"#define atanf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atanf )\r\n", +"#define atan2_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2 )\r\n", +"#define atan2f_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), atan2f )\r\n", +"#define cosh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), cosh )\r\n", +"#define coshf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), coshf )\r\n", +"#define sinh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinh )\r\n", +"#define sinhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), sinhf )\r\n", +"#define tanh_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanh )\r\n", +"#define tanhf_ OP_COUNT_WRAPPER1_( TRANS_( 1 ), tanhf )\r\n", +"#define fmod_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmod )\r\n", +"#define fmodf_ OP_COUNT_WRAPPER1_( DIV_( 1 ), fmodf )\r\n", +"#define frexp_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexp )\r\n", +"#define frexpf_ OP_COUNT_WRAPPER1_( MISC_( 2 ), frexpf )\r\n", +"\r\n", +"/* the macros below are instrumented versions of user-defined macros that might be used in the source code \r\n", +" representing some well-known and recognized mathematical operations (that are not defined in math.h) \r\n", +" Note: the 'wmc_flag_=wmc_flag_' is used to avoid warning: left-hand operand of comma expression has no effect with gcc */\r\n", +"\r\n", +"#define min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), min( ( a ), ( b ) ) )\r\n", +"#define max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), max( ( a ), ( b ) ) )\r\n", +"#define MIN_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MIN( ( a ), ( b ) ) )\r\n", +"#define MAX_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), MAX( ( a ), ( b ) ) )\r\n", +"#define Min_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Min( ( a ), ( b ) ) )\r\n", +"#define Max_( a, b ) OP_COUNT_WRAPPER1_( MISC_( 1 ), Max( ( a ), ( b ) ) )\r\n", +"#define sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), sqr( ( x ) ) )\r\n", +"#define Sqr_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Sqr( ( x ) ) )\r\n", +"#define SQR_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQR( ( x ) ) )\r\n", +"#define square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), square( ( x ) ) )\r\n", +"#define Square_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), Square( ( x ) ) )\r\n", +"#define SQUARE_( x ) OP_COUNT_WRAPPER1_( MULT_( 1 ), SQUARE( ( x ) ) )\r\n", +"#define sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), sign( ( x ) ) )\r\n", +"#define Sign_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), Sign( ( x ) ) )\r\n", +"#define SIGN_( x ) OP_COUNT_WRAPPER1_( MOVE_( 1 ), SIGN( ( x ) ) )\r\n", +"#define inv_sqrt_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrt( ( x ) ) )\r\n", +"#define inv_sqrtf_( x ) OP_COUNT_WRAPPER1_( SQRT_( 1 ), inv_sqrtf( ( x ) ) )\r\n", +"#define log_base_2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log_base_2( ( x ) ) )\r\n", +"#define log2_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2( ( x ) ) )\r\n", +"#define log2f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2f( ( x ) ) )\r\n", +"#define log2_f_( x ) OP_COUNT_WRAPPER1_( ( LOG_( 1 ), MULT_( 1 ) ), log2_f( ( x ) ) )\r\n", +"#define _round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, _round( ( x ) ) )\r\n", +"#define round_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round( ( x ) ) )\r\n", +"#define round_f_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, round_f( ( x ) ) )\r\n", +"#define roundf_( x ) OP_COUNT_WRAPPER1_( wmc_flag_ = wmc_flag_, roundf( ( x ) ) )\r\n", +"#define set_min_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_min( ( a ), ( b ) ) )\r\n", +"#define set_max_( a, b ) OP_COUNT_WRAPPER3_( ( ADD_( 1 ), BRANCH_( 1 ), MOVE_( 1 ) ), set_max( ( a ), ( b ) ) )\r\n", +"\r\n", +"/* Functions */\r\n", +"#define func_( name, x ) OP_COUNT_WRAPPER1_( FUNC_( x ), name )\r\n", +"\r\n", +"/* Logical Operators */\r\n", +"#ifndef __\r\n", +"#define __ ( BRANCH_( 1 ), 1 ) &&\r\n", +"#endif\r\n", +"\r\n", +"/* Ternary Operators (? and :) */\r\n", +"#ifndef _\r\n", +"#define _ ( BRANCH_( 1 ), 0 ) ? 0:\r\n", +"#endif\r\n", +"\r\n", +"/* Flow Control keywords */\r\n", +"#define if_ \\\r\n", +" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n", +" if\r\n", +"#define for_ OP_COUNT_WRAPPER2_( LOOP_(1)) for\r\n", +"#define while_( c ) \\\r\n", +" while \\\r\n", +" OP_COUNT_WRAPPER1_( BRANCH_( 1 ), ( c ) ) /* needs extra \"()\" if ',' encountered */\r\n", +"#define do_ \\\r\n", +" do \\\r\n", +" {\r\n", +"#define _while \\\r\n", +" BRANCH_( 1 ); \\\r\n", +" } \\\r\n", +" while\r\n", +"\r\n", +"#define goto_ \\\r\n", +" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n", +" goto\r\n", +"#define break_ \\\r\n", +" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n", +" break\r\n", +"#define continue_ \\\r\n", +" OP_COUNT_WRAPPER2_( BRANCH_( 1 ) ) \\\r\n", +" continue\r\n", +"#define return_ \\\r\n", +" OP_COUNT_WRAPPER2_( ( wmc_flag_ = stack_tree_level_, STACK_DEPTH_FCT_RETURN ) ) \\\r\n", +" return\r\n", +"#define switch_ \\\r\n", +" OP_COUNT_WRAPPER2_( ( BRANCH_( 1 ), wmc_flag_ = 1 ) ) \\\r\n", +" switch\r\n", +"#define cost_( n ) OP_COUNT_WRAPPER2_( wmc_flag_ ? ( ADD_( n ), BRANCH_( n ), wmc_flag_ = 0 ) : 0 );\r\n", +"\r\n", +"#ifdef WMOPS\r\n", +"\r\n", +"#define ACC 2\r\n", +"#define MUL 1\r\n", +"\r\n", +"/* Counting Function (should not be called externally!) */\r\n", +"static void wops_( const char *ops )\r\n", +"{\r\n", +" char lm = 0; /* lm: Last Operation is Math */\r\n", +" static char lo = 0; /* Last Operation */\r\n", +"\r\n", +" void ( *fct )( const char *ops ) = wops_;\r\n", +"\r\n", +"st:\r\n", +" while ( *ops != '\\0' )\r\n", +" {\r\n", +" switch ( *ops++ )\r\n", +" {\r\n", +" int cnt;\r\n", +" case '-':\r\n", +" for ( cnt = 0; ops[cnt] == '>'; cnt++ )\r\n", +" ;\r\n", +" if ( cnt & 1 )\r\n", +" goto ind;\r\n", +" case '+':\r\n", +" lm = 2;\r\n", +" if ( lo & MUL )\r\n", +" {\r\n", +" MULT_( -1 );\r\n", +" MAC_( 1 );\r\n", +" break;\r\n", +" }\r\n", +" lo = ACC << 2;\r\n", +" case 'U':\r\n", +" case 'D':\r\n", +" ADD_( 1 );\r\n", +" break;\r\n", +" case '*':\r\n", +" lm = 2;\r\n", +" if ( lo & ACC )\r\n", +" {\r\n", +" ADD_( -1 );\r\n", +" MAC_( 1 );\r\n", +" break;\r\n", +" }\r\n", +" lo = MUL << 2;\r\n", +" MULT_( 1 );\r\n", +" break;\r\n", +" case '/':\r\n", +" case '%':\r\n", +" lm = 2;\r\n", +" DIV_( 1 );\r\n", +" break;\r\n", +" case '&':\r\n", +" case '|':\r\n", +" case '^':\r\n", +" lm = 2;\r\n", +" case '~':\r\n", +" LOGIC_( 1 );\r\n", +" break;\r\n", +" case '<':\r\n", +" case '>':\r\n", +" if ( *ops != ops[-1] )\r\n", +" goto error;\r\n", +" ops++;\r\n", +" case -85:\r\n", +" case -69:\r\n", +" lm = 2;\r\n", +" SHIFT_( 1 );\r\n", +" break;\r\n", +" case 'L':\r\n", +" case 'G':\r\n", +" if ( *ops == 't' )\r\n", +" goto comp;\r\n", +" case 'E':\r\n", +" case 'N':\r\n", +" if ( *ops != 'e' )\r\n", +" goto error;\r\n", +" comp:\r\n", +" ops++;\r\n", +" ADD_( 1 );\r\n", +" break;\r\n", +" case '!':\r\n", +" MISC_( 2 );\r\n", +" break;\r\n", +" case 'M':\r\n", +" MOVE_( 1 );\r\n", +" break;\r\n", +" case 'S':\r\n", +" STORE_( 1 );\r\n", +" break;\r\n", +" case 'P':\r\n", +" PTR_INIT_( 1 );\r\n", +" break;\r\n", +" case '[':\r\n", +" case ']':\r\n", +" goto st;\r\n", +" ind:\r\n", +" ops++;\r\n", +" case 'I':\r\n", +" case '.':\r\n", +" INDIRECT_( 1 );\r\n", +" break;\r\n", +" case '=':\r\n", +" if ( lm )\r\n", +" goto st;\r\n", +" case '\\0':\r\n", +" /* This Shouldn't Happen */\r\n", +" /* These are Used to Avoid: \"warning: 'name' defined but not used\" with Cygwin gcc Compiler */\r\n", +" wmc_flag_ = wmc_flag_;\r\n", +" fct( \"\" );\r\n", +" error:\r\n", +" default:\r\n", +" fprintf( stderr, \"\\r wops: Invalid Counting Operation '%s'\\n\", ops - 1 );\r\n", +" exit( -1 );\r\n", +" }\r\n", +" lm >>= 1;\r\n", +" lo >>= 2;\r\n", +" }\r\n", +"\r\n", +" return;\r\n", +"}\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"/* All Other Operations */\r\n", +"#define $( str ) OP_COUNT_WRAPPER2_( wops_( str ) )\r\n", +"\r\n", +"\r\n", +"/*-------------------------------------------------------------------*\r\n", +" * Memory counting tool\r\n", +" *-------------------------------------------------------------------*/\r\n", +"\r\n", +"/* Enhanced Const Data Size Counting (Rounding Up to the Nearest 'Integer' Size) */\r\n", +"#define rsize( item ) ( ( sizeof( item ) + sizeof( int ) - 1 ) / sizeof( int ) * sizeof( int ) )\r\n", +"\r\n", +"#ifdef _MSC_VER\r\n", +"/* Disable \"warning C4210: nonstandard extension used : function given file scope\" with Visual Studio Compiler */\r\n", +"#pragma warning( disable : 4210 )\r\n", +"#endif\r\n", +"\r\n", +"/* Const Data Size and PROM Size Wrapper Functions */\r\n", +"#define Const_Data_Size_Func( file ) Const_Data_Size_##file( void )\r\n", +"#define Get_Const_Data_Size( file, val_ptr ) \\\r\n", +" { \\\r\n", +" extern int Const_Data_Size_##file( void ); \\\r\n", +" *( val_ptr ) = Const_Data_Size_##file(); \\\r\n", +" }\r\n", +"#define PROM_Size_Func( file ) PROM_Size_##file( void )\r\n", +"#define Get_PROM_Size( file, val_ptr ) \\\r\n", +" { \\\r\n", +" int PROM_Size_##file( void ); \\\r\n", +" *( val_ptr ) = PROM_Size_##file(); \\\r\n", +" }\r\n", +"\r\n", +"/* ROM Size Lookup Table - contains information about PROM size and Const Data Size in all source files */\r\n", +"/* The print_mem() function looks for this table to print the results of Const Data usage and PROM usage */\r\n", +"typedef struct ROM_Size_Lookup_Table\r\n", +"{\r\n", +" const char file_spec[255];\r\n", +" int PROM_size;\r\n", +" int ( *Get_Const_Data_Size_Func )( void );\r\n", +"} ROM_Size_Lookup_Table;\r\n", +"\r\n", +"/* The WMC tool inserts the following declaration during the innstrumentation process in the .c file where the function print_mem() is located */\r\n", +"/* and modifies it to print_mem(Const_Data_PROM_Table) */\r\n", +"\r\n", +"/* #ifdef WMOPS\r\n", +" * ROM_Size_Lookup_Table Const_Data_PROM_Table[] =\r\n", +" * {\r\n", +" * {\"../lib_enc/rom_enc.c\", 0, NULL},\r\n", +" * {\"../lib_com/[star].c\", 0, NULL},\r\n", +" * {\"\", -1, NULL}\r\n", +" * };\r\n", +" * #endif\r\n", +" */\r\n", +"\r\n", +"/*#define MEM_ALIGN_64BITS */ /* Define this when using 64 Bits values in the code (ex: double), otherwise it will align on 32 Bits */\r\n", +"/*#define MEM_COUNT_DETAILS*/\r\n", +"\r\n", +"typedef enum\r\n", +"{\r\n", +" USE_BYTES = 0,\r\n", +" USE_16BITS = 1,\r\n", +" USE_32BITS = 2\r\n", +"} Counting_Size;\r\n", +"\r\n", +"\r\n", +"#ifdef WMOPS\r\n", +"\r\n", +"void *mem_alloc( const char *func_name, int func_lineno, size_t size, char *alloc_str );\r\n", +"void mem_free( const char *func_name, int func_lineno, void *ptr );\r\n", +"\r\n", +"#define malloc_( size ) mem_alloc( __func__, __LINE__, size, \"m:\" #size )\r\n", +"#define calloc_( n, size ) mem_alloc( __func__, __LINE__, ( n ) * ( size ), \"c:\" #n \", \" #size )\r\n", +"#define free_( ptr ) mem_free( __func__, __LINE__, ptr )\r\n", +"\r\n", +"void reset_mem( Counting_Size cnt_size );\r\n", +"void print_mem( ROM_Size_Lookup_Table Const_Data_PROM_Table[] );\r\n", +"\r\n", +"int push_stack( const char *filename, const char *fctname );\r\n", +"int pop_stack( const char *filename, const char *fctname );\r\n", +"\r\n", +"#ifdef WMOPS_DETAIL\r\n", +"#define STACK_DEPTH_FCT_CALL ( push_wmops( __func__, \"[WMC_AUTO]\" ), push_stack( __FILE__, __func__ ) ) /* add push_wmops() in all function calls */\r\n", +"#define STACK_DEPTH_FCT_RETURN ( pop_wmops(), pop_stack( __FILE__, __func__ ) ) /* add pop_wmops() in all function returns */\r\n", +"#else\r\n", +"#define STACK_DEPTH_FCT_CALL push_stack( __FILE__, __func__ )\r\n", +"#define STACK_DEPTH_FCT_RETURN pop_stack( __FILE__, __func__ )\r\n", +"#endif\r\n", +"\r\n", +"void reset_stack( void );\r\n", +"#define func_start_ int stack_tree_level_ = STACK_DEPTH_FCT_CALL;\r\n", +"\r\n", +"#else\r\n", +"#define malloc_( n1 ) malloc( n1 )\r\n", +"#define calloc_( n1, n2 ) calloc( n1, n2 )\r\n", +"#define free_( ptr ) free( ptr )\r\n", +"#define reset_mem( cnt_size )\r\n", +"#define print_mem( Const_Data_PROM_Table )\r\n", +"\r\n", +"#define push_stack( file, fct )\r\n", +"#define pop_stack( file, fct )\r\n", +"#define reset_stack()\r\n", +"#define func_start_\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"/* Global counter variable for calculation of complexity weight */\r\n", +"typedef struct\r\n", +"{\r\n", +" unsigned int add; /* Complexity Weight of 1 */\r\n", +" unsigned int sub; /* Complexity Weight of 1 */\r\n", +" unsigned int abs_s; /* Complexity Weight of 1 */\r\n", +" unsigned int shl; /* Complexity Weight of 1 */\r\n", +" unsigned int shr; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int extract_h; /* Complexity Weight of 1 */\r\n", +" unsigned int extract_l; /* Complexity Weight of 1 */\r\n", +" unsigned int mult; /* Complexity Weight of 1 */\r\n", +" unsigned int L_mult; /* Complexity Weight of 1 */\r\n", +" unsigned int negate; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int round; /* Complexity Weight of 1 */\r\n", +" unsigned int L_mac; /* Complexity Weight of 1 */\r\n", +" unsigned int L_msu; /* Complexity Weight of 1 */\r\n", +" unsigned int L_macNs; /* Complexity Weight of 1 */\r\n", +" unsigned int L_msuNs; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L_add; /* Complexity Weight of 1 */\r\n", +" unsigned int L_sub; /* Complexity Weight of 1 */\r\n", +" unsigned int L_add_c; /* Complexity Weight of 2 */\r\n", +" unsigned int L_sub_c; /* Complexity Weight of 2 */\r\n", +" unsigned int L_negate; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L_shl; /* Complexity Weight of 1 */\r\n", +" unsigned int L_shr; /* Complexity Weight of 1 */\r\n", +" unsigned int mult_r; /* Complexity Weight of 1 */\r\n", +" unsigned int shr_r; /* Complexity Weight of 3 */\r\n", +" unsigned int mac_r; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int msu_r; /* Complexity Weight of 1 */\r\n", +" unsigned int L_deposit_h; /* Complexity Weight of 1 */\r\n", +" unsigned int L_deposit_l; /* Complexity Weight of 1 */\r\n", +" unsigned int L_shr_r; /* Complexity Weight of 3 */\r\n", +" unsigned int L_abs; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L_sat; /* Complexity Weight of 4 */\r\n", +" unsigned int norm_s; /* Complexity Weight of 1 */\r\n", +" unsigned int div_s; /* Complexity Weight of 18 */\r\n", +" unsigned int norm_l; /* Complexity Weight of 1 */\r\n", +" unsigned int move16; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int move32; /* Complexity Weight of 2 */\r\n", +" unsigned int Logic16; /* Complexity Weight of 1 */\r\n", +" unsigned int Logic32; /* Complexity Weight of 2 */\r\n", +" unsigned int Test; /* Complexity Weight of 2 */\r\n", +" unsigned int s_max; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int s_min; /* Complexity Weight of 1 */\r\n", +" unsigned int L_max; /* Complexity Weight of 1 */\r\n", +" unsigned int L_min; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_max; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_min; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int shl_r; /* Complexity Weight of 2 */\r\n", +" unsigned int L_shl_r; /* Complexity Weight of 2 */\r\n", +" unsigned int L40_shr_r; /* Complexity Weight of 2 */\r\n", +" unsigned int L40_shl_r; /* Complexity Weight of 2 */\r\n", +" unsigned int norm_L40; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L40_shl; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_shr; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_negate; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_add; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_sub; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L40_abs; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_mult; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_mac; /* Complexity Weight of 1 */\r\n", +" unsigned int mac_r40; /* Complexity Weight of 2 */\r\n", +"\r\n", +" unsigned int L40_msu; /* Complexity Weight of 1 */\r\n", +" unsigned int msu_r40; /* Complexity Weight of 2 */\r\n", +" unsigned int Mpy_32_16_ss; /* Complexity Weight of 2 */\r\n", +" unsigned int Mpy_32_32_ss; /* Complexity Weight of 2 */\r\n", +" unsigned int L_mult0; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L_mac0; /* Complexity Weight of 1 */\r\n", +" unsigned int L_msu0; /* Complexity Weight of 1 */\r\n", +" unsigned int lshl; /* Complexity Weight of 1 */\r\n", +" unsigned int lshr; /* Complexity Weight of 1 */\r\n", +" unsigned int L_lshl; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L_lshr; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_lshl; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_lshr; /* Complexity Weight of 1 */\r\n", +" unsigned int s_and; /* Complexity Weight of 1 */\r\n", +" unsigned int s_or; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int s_xor; /* Complexity Weight of 1 */\r\n", +" unsigned int L_and; /* Complexity Weight of 1 */\r\n", +" unsigned int L_or; /* Complexity Weight of 1 */\r\n", +" unsigned int L_xor; /* Complexity Weight of 1 */\r\n", +" unsigned int rotl; /* Complexity Weight of 3 */\r\n", +"\r\n", +" unsigned int rotr; /* Complexity Weight of 3 */\r\n", +" unsigned int L_rotl; /* Complexity Weight of 3 */\r\n", +" unsigned int L_rotr; /* Complexity Weight of 3 */\r\n", +" unsigned int L40_set; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_deposit_h; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L40_deposit_l; /* Complexity Weight of 1 */\r\n", +" unsigned int L40_deposit32; /* Complexity Weight of 1 */\r\n", +" unsigned int Extract40_H; /* Complexity Weight of 1 */\r\n", +" unsigned int Extract40_L; /* Complexity Weight of 1 */\r\n", +" unsigned int L_Extract40; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int L40_round; /* Complexity Weight of 1 */\r\n", +" unsigned int L_saturate40; /* Complexity Weight of 1 */\r\n", +" unsigned int round40; /* Complexity Weight of 1 */\r\n", +" unsigned int If; /* Complexity Weight of 3 */\r\n", +" unsigned int Goto; /* Complexity Weight of 2 */\r\n", +"\r\n", +" unsigned int Break; /* Complexity Weight of 2 */\r\n", +" unsigned int Switch; /* Complexity Weight of 6 */\r\n", +" unsigned int For; /* Complexity Weight of 3 */\r\n", +" unsigned int While; /* Complexity Weight of 3 */\r\n", +" unsigned int Continue; /* Complexity Weight of 2 */\r\n", +"\r\n", +" unsigned int L_mls; /* Complexity Weight of 1 */\r\n", +" unsigned int div_l; /* Complexity Weight of 32 */\r\n", +" unsigned int i_mult; /* Complexity Weight of 1 */\r\n", +"\r\n", +"/* New complex basic operators */\r\n", +"#ifdef COMPLEX_OPERATOR\r\n", +" unsigned int CL_shr; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_shl; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_add; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_sub; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_scale; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_dscale; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_msu_j; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_mac_j; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_move; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_Extract_real; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_Extract_imag; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_form; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_multr_32x16; /* Complexity Weight of 2 */\r\n", +" unsigned int CL_negate; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_conjugate; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_mul_j; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_swap_real_imag; /* Complexity Weight of 1 */\r\n", +" unsigned int C_add; /* Complexity Weight of 1 */\r\n", +" unsigned int C_sub; /* Complexity Weight of 1 */\r\n", +" unsigned int C_mul_j; /* Complexity Weight of 1 */\r\n", +" unsigned int C_multr; /* Complexity Weight of 2 */\r\n", +" unsigned int C_form; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int C_scale; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_round32_16; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_scale_32; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_dscale_32; /* Complexity Weight of 1 */\r\n", +" unsigned int CL_multr_32x32; /* Complexity Weight of 2 */\r\n", +" unsigned int C_mac_r; /* Complexity Weight of 2 */\r\n", +" unsigned int C_msu_r; /* Complexity Weight of 2 */\r\n", +" unsigned int C_Extract_real; /* Complexity Weight of 1 */\r\n", +" unsigned int C_Extract_imag; /* Complexity Weight of 1 */\r\n", +" unsigned int C_negate; /* Complexity Weight of 1 */\r\n", +" unsigned int C_conjugate; /* Complexity Weight of 1 */\r\n", +" unsigned int C_shr; /* Complexity Weight of 1 */\r\n", +" unsigned int C_shl; /* Complexity Weight of 1 */\r\n", +"\r\n", +"#endif /* #ifdef COMPLEX_OPERATOR */\r\n", +"\r\n", +"/* New 64 bit basops */\r\n", +"#ifdef ENH_64_BIT_OPERATOR\r\n", +" unsigned int move64; /* Complexity Weight of 1 */\r\n", +" unsigned int W_add_nosat; /* Complexity Weight of 1 */\r\n", +" unsigned int W_sub_nosat; /* Complexity Weight of 1 */\r\n", +" unsigned int W_shl; /* Complexity Weight of 1 */\r\n", +" unsigned int W_shr; /* Complexity Weight of 1 */\r\n", +" unsigned int W_shl_nosat; /* Complexity Weight of 1 */\r\n", +" unsigned int W_shr_nosat; /* Complexity Weight of 1 */\r\n", +" unsigned int W_mac_32_16; /* Complexity Weight of 1 */\r\n", +" unsigned int W_msu_32_16; /* Complexity Weight of 1 */\r\n", +" unsigned int W_mult_32_16; /* Complexity Weight of 1 */\r\n", +" unsigned int W_mult0_16_16; /* Complexity Weight of 1 */\r\n", +" unsigned int W_mac0_16_16; /* Complexity Weight of 1 */\r\n", +" unsigned int W_msu0_16_16; /* Complexity Weight of 1 */\r\n", +" unsigned int W_mult_16_16; /* Complexity Weight of 1 */\r\n", +" unsigned int W_mac_16_16; /* Complexity Weight of 1 */\r\n", +" unsigned int W_msu_16_16; /* Complexity Weight of 1 */\r\n", +" unsigned int W_shl_sat_l; /* Complexity Weight of 1 */\r\n", +" unsigned int W_sat_l; /* Complexity Weight of 1 */\r\n", +" unsigned int W_sat_m; /* Complexity Weight of 1 */\r\n", +" unsigned int W_deposit32_l; /* Complexity Weight of 1 */\r\n", +" unsigned int W_deposit32_h; /* Complexity Weight of 1 */\r\n", +" unsigned int W_extract_l; /* Complexity Weight of 1 */\r\n", +" unsigned int W_extract_h; /* Complexity Weight of 1 */\r\n", +" unsigned int W_round48_L; /* Complexity Weight of 1 */\r\n", +" unsigned int W_round32_s; /* Complexity Weight of 1 */\r\n", +" unsigned int W_norm; /* Complexity Weight of 1 */\r\n", +"\r\n", +" unsigned int W_add; /* Complexity Weight of 1 */\r\n", +" unsigned int W_sub; /* Complexity Weight of 1 */\r\n", +" unsigned int W_neg; /* Complexity Weight of 1 */\r\n", +" unsigned int W_abs; /* Complexity Weight of 1 */\r\n", +" unsigned int W_mult_32_32; /* Complexity Weight of 1 */\r\n", +" unsigned int W_mult0_32_32; /* Complexity Weight of 1 */\r\n", +" unsigned int W_lshl; /* Complexity Weight of 1 */\r\n", +" unsigned int W_lshr; /* Complexity Weight of 1 */\r\n", +" unsigned int W_round64_L; /* Complexity Weight of 1 */\r\n", +"\r\n", +"#endif /* #ifdef ENH_64_BIT_OPERATOR */\r\n", +"\r\n", +"#ifdef ENH_32_BIT_OPERATOR\r\n", +" unsigned int Mpy_32_16_1; /* Complexity Weight of 1 */\r\n", +" unsigned int Mpy_32_16_r; /* Complexity Weight of 1 */\r\n", +" unsigned int Mpy_32_32; /* Complexity Weight of 1 */\r\n", +" unsigned int Mpy_32_32_r; /* Complexity Weight of 1 */\r\n", +" unsigned int Madd_32_16; /* Complexity Weight of 1 */\r\n", +" unsigned int Madd_32_16_r; /* Complexity Weight of 1 */\r\n", +" unsigned int Msub_32_16; /* Complexity Weight of 1 */\r\n", +" unsigned int Msub_32_16_r; /* Complexity Weight of 1 */\r\n", +" unsigned int Madd_32_32; /* Complexity Weight of 1 */\r\n", +" unsigned int Madd_32_32_r; /* Complexity Weight of 1 */\r\n", +" unsigned int Msub_32_32; /* Complexity Weight of 1 */\r\n", +" unsigned int Msub_32_32_r; /* Complexity Weight of 1 */\r\n", +"#endif /* #ifdef ENH_32_BIT_OPERATOR */\r\n", +"\r\n", +"#ifdef ENH_U_32_BIT_OPERATOR\r\n", +" unsigned int UL_addNs; /* Complexity Weight of 1 */\r\n", +" unsigned int UL_subNs; /* Complexity Weight of 1 */\r\n", +" unsigned int UL_Mpy_32_32; /* Complexity Weight of 1 */\r\n", +" unsigned int Mpy_32_32_uu; /* Complexity Weight of 2 */\r\n", +" unsigned int Mpy_32_16_uu; /* Complexity Weight of 2 */\r\n", +" unsigned int norm_ul_float; /* Complexity Weight of 1 */\r\n", +" unsigned int UL_deposit_l; /* Complexity Weight of 1 */\r\n", +"#endif /* #ifdef ENH_U_32_BIT_OPERATOR */\r\n", +"\r\n", +"#ifdef CONTROL_CODE_OPS\r\n", +" unsigned int LT_16; /* Complexity Weight of 1 */\r\n", +" unsigned int GT_16; /* Complexity Weight of 1 */\r\n", +" unsigned int LE_16; /* Complexity Weight of 1 */\r\n", +" unsigned int GE_16; /* Complexity Weight of 1 */\r\n", +" unsigned int EQ_16; /* Complexity Weight of 1 */\r\n", +" unsigned int NE_16; /* Complexity Weight of 1 */\r\n", +" unsigned int LT_32; /* Complexity Weight of 1 */\r\n", +" unsigned int GT_32; /* Complexity Weight of 1 */\r\n", +" unsigned int LE_32; /* Complexity Weight of 1 */\r\n", +" unsigned int GE_32; /* Complexity Weight of 1 */\r\n", +" unsigned int EQ_32; /* Complexity Weight of 1 */\r\n", +" unsigned int NE_32; /* Complexity Weight of 1 */\r\n", +" unsigned int LT_64; /* Complexity Weight of 1 */\r\n", +" unsigned int GT_64; /* Complexity Weight of 1 */\r\n", +" unsigned int LE_64; /* Complexity Weight of 1 */\r\n", +" unsigned int GE_64; /* Complexity Weight of 1 */\r\n", +" unsigned int EQ_64; /* Complexity Weight of 1 */\r\n", +" unsigned int NE_64; /* Complexity Weight of 1 */\r\n", +"\r\n", +"#endif /* #ifdef CONTROL_CODE_OPS */\r\n", +"} BASIC_OP;\r\n", +"\r\n", +"#ifdef WMOPS\r\n", +"extern BASIC_OP *multiCounter;\r\n", +"extern unsigned int currCounter;\r\n", +"extern int funcId_where_last_call_to_else_occurred;\r\n", +"extern long funcid_total_wmops_at_last_call_to_else;\r\n", +"extern int call_occurred;\r\n", +"\r\n", +"long TotalWeightedOperation( unsigned int counterId );\r\n", +"long DeltaWeightedOperation( unsigned int counterId );\r\n", +"void Reset_BASOP_WMOPS_counter( unsigned int counterId );\r\n", +"\r\n", +"#endif\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : FOR\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro FOR should be used instead of the 'for' C statement.\r\n", +" * The complexity is independent of the number of loop iterations that are\r\n", +" * performed.\r\n", +" *\r\n", +" * Complexity weight : 3 (regardless of number of iterations).\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define FOR( a ) for ( a )\r\n", +"\r\n", +"#else /* ifndef WMOPS */\r\n", +"#define FOR( a ) \\\r\n", +" if ( incrFor(), 0 ) \\\r\n", +" ; \\\r\n", +" else \\\r\n", +" for ( a )\r\n", +"\r\n", +"static __inline void incrFor( void )\r\n", +"{\r\n", +" multiCounter[currCounter].For++;\r\n", +"}\r\n", +"#endif /* ifndef WMOPS */\r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : WHILE\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro WHILE should be used instead of the 'while' C statement.\r\n", +" * The complexity is proportional to the number of loop iterations that\r\n", +" * are performed.\r\n", +" *\r\n", +" * Complexity weight : 4 x 'number of loop iterations'.\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define WHILE( a ) while ( a )\r\n", +"\r\n", +"#else /* ifndef WMOPS */\r\n", +"#define WHILE( a ) while ( incrWhile(), a )\r\n", +"\r\n", +"static __inline void incrWhile( void )\r\n", +"{\r\n", +" multiCounter[currCounter].While++;\r\n", +"}\r\n", +"#endif /* ifndef WMOPS */\r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : DO\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro DO should be used instead of the 'do' C statement.\r\n", +" *\r\n", +" * Complexity weight : 0 (complexity counted by WHILE macro).\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define DO do\r\n", +"\r\n", +"#else /* ifndef WMOPS */\r\n", +"#define DO do\r\n", +"\r\n", +"#endif /* ifndef WMOPS */\r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : IF\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro IF should :\r\n", +" *\r\n", +" * - not be used when :\r\n", +" * - the 'if' structure does not have any 'else if' nor 'else' statement\r\n", +" * - and it conditions only one DSP basic operations.\r\n", +" *\r\n", +" * - be used instead of the 'if' C statement in every other case :\r\n", +" * - when there is an 'else' or 'else if' statement,\r\n", +" * - or when the 'if' conditions several DSP basic operations,\r\n", +" * - or when the 'if' conditions a function call.\r\n", +" *\r\n", +" * Complexity weight : 3\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"\r\n", +"#ifndef WMOPS\r\n", +"#define IF( a ) if ( a )\r\n", +"#else /* ifndef WMOPS */\r\n", +"#define IF( a ) if ( incrIf( __func__ ), a )\r\n", +"void incrIf( const char *func_name );\r\n", +"#endif /* ifndef WMOPS */\r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : ELSE\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro ELSE should be used instead of the 'else' C statement.\r\n", +" *\r\n", +" * Complexity weight : 3\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"\r\n", +"#ifndef WMOPS\r\n", +"#define ELSE else\r\n", +"#else /* ifndef WMOPS */\r\n", +"#define ELSE else if ( incrElse( __func__ ), 0 ); else\r\n", +"void incrElse( const char *func_name );\r\n", +"#endif /* ifndef WMOPS */\r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : SWITCH\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro SWITCH should be used instead of the 'switch' C statement.\r\n", +" *\r\n", +" * Complexity weight : 6\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define SWITCH( a ) switch ( a )\r\n", +"\r\n", +"#else /* ifndef WMOPS */\r\n", +"#define SWITCH( a ) switch ( incrSwitch(), a )\r\n", +"\r\n", +"static __inline void incrSwitch( void )\r\n", +"{\r\n", +" multiCounter[currCounter].Switch++;\r\n", +"}\r\n", +"#endif /* ifndef WMOPS */\r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : CONTINUE\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro CONTINUE should be used instead of the 'continue' C statement.\r\n", +" *\r\n", +" * Complexity weight : 2\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define CONTINUE continue\r\n", +"\r\n", +"#else /* ifndef WMOPS */\r\n", +"#define CONTINUE \\\r\n", +" if ( incrContinue(), 0 ) \\\r\n", +" ; \\\r\n", +" else \\\r\n", +" continue\r\n", +"\r\n", +"static __inline void incrContinue( void )\r\n", +"{\r\n", +" multiCounter[currCounter].Continue++;\r\n", +"}\r\n", +"#endif /* ifndef WMOPS */\r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : BREAK\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro BREAK should be used instead of the 'break' C statement.\r\n", +" *\r\n", +" * Complexity weight : 2\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define BREAK break\r\n", +"\r\n", +"#else /* ifndef WMOPS */\r\n", +"#define BREAK \\\r\n", +" if ( incrBreak(), 0 ) \\\r\n", +" ; \\\r\n", +" else \\\r\n", +" break\r\n", +"\r\n", +"static __inline void incrBreak( void )\r\n", +"{\r\n", +" multiCounter[currCounter].Break++;\r\n", +"}\r\n", +"#endif /* ifndef WMOPS */\r\n", +"\r\n", +"\r\n", +"/*****************************************************************************\r\n", +" *\r\n", +" * Function Name : GOTO\r\n", +" *\r\n", +" * Purpose :\r\n", +" *\r\n", +" * The macro GOTO should be used instead of the 'goto' C statement.\r\n", +" *\r\n", +" * Complexity weight : 2\r\n", +" *\r\n", +" *****************************************************************************/\r\n", +"#ifndef WMOPS\r\n", +"#define GOTO goto\r\n", +"\r\n", +"#else /* ifndef WMOPS */\r\n", +"#define GOTO \\\r\n", +" if ( incrGoto(), 0 ) \\\r\n", +" ; \\\r\n", +" else \\\r\n", +" goto\r\n", +"\r\n", +"static __inline void incrGoto( void )\r\n", +"{\r\n", +" multiCounter[currCounter].Goto++;\r\n", +"}\r\n", +"#endif /* ifndef WMOPS */\r\n", +"\r\n", +"\r\n", +"#ifdef CONTROL_CODE_OPS\r\n", +"\r\n", +"extern int LT_16( short var1, short var2 );\r\n", +"extern int GT_16( short var1, short var2 );\r\n", +"extern int LE_16( short var1, short var2 );\r\n", +"extern int GE_16( short var1, short var2 );\r\n", +"extern int EQ_16( short var1, short var2 );\r\n", +"extern int NE_16( short var1, short var2 );\r\n", +"\r\n", +"extern int LT_32( int L_var1, int L_var2 );\r\n", +"extern int GT_32( int L_var1, int L_var2 );\r\n", +"extern int LE_32( int L_var1, int L_var2 );\r\n", +"extern int GE_32( int L_var1, int L_var2 );\r\n", +"extern int EQ_32( int L_var1, int L_var2 );\r\n", +"extern int NE_32( int L_var1, int L_var2 );\r\n", +"\r\n", +"extern int LT_64( long long int L64_var1, long long int L64_var2 );\r\n", +"extern int GT_64( long long int L64_var1, long long int L64_var2 );\r\n", +"extern int LE_64( long long int L64_var1, long long int L64_var2 );\r\n", +"extern int GE_64( long long int L64_var1, long long int L64_var2 );\r\n", +"extern int EQ_64( long long int L64_var1, long long int L64_var2 );\r\n", +"extern int NE_64( long long int L64_var1, long long int L64_var2 );\r\n", +"\r\n", +"#endif /* #ifdef CONTROL_CODE_OPS */\r\n", +"\r\n", +"\r\n", +"#endif /* WMOPS_H */\r\n", +"\r\n", \ No newline at end of file From 7ecb20cdc796a1394d66fd883f50a81b04a855db Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Fri, 6 Dec 2024 09:42:17 +0100 Subject: [PATCH 67/67] fix the defition of FRAMES_PER_SECOND --- src/wmc_tool/test_data/ref/wmc_auto.c | 4 +--- src/wmc_tool/test_data/ref/wmc_auto.h | 1 + src/wmc_tool/wmc_auto_c.txt | 5 +---- src/wmc_tool/wmc_auto_h.txt | 1 + 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/wmc_tool/test_data/ref/wmc_auto.c b/src/wmc_tool/test_data/ref/wmc_auto.c index e9b7f86..3e66b79 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.c +++ b/src/wmc_tool/test_data/ref/wmc_auto.c @@ -40,7 +40,7 @@ int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_ * Complexity counting tool *--------------------------------------------------------------------*/ - +#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */ #define MAX_FUNCTION_NAME_LENGTH 200 /* Maximum length of the function name */ #define MAX_PARAMS_LENGTH 200 /* Maximum length of the function parameter string */ #define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> might be increased during runtime, if needed */ @@ -49,8 +49,6 @@ int cntr_push_pop = 0; /* global counter for checking balanced push_wmops()/pop_ #define DOUBLE_MAX 0x80000000 #define FAC ( FRAMES_PER_SECOND / 1e6 ) -#define FRAMES_PER_SECOND 50.0 #define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */ - typedef struct { char label[MAX_FUNCTION_NAME_LENGTH]; diff --git a/src/wmc_tool/test_data/ref/wmc_auto.h b/src/wmc_tool/test_data/ref/wmc_auto.h index 5d24b5a..650a067 100644 --- a/src/wmc_tool/test_data/ref/wmc_auto.h +++ b/src/wmc_tool/test_data/ref/wmc_auto.h @@ -28,6 +28,7 @@ #pragma GCC system_header #endif +#define FRAMES_PER_SECOND 50.0 #define ENH_32_BIT_OPERATOR #define ENH_64_BIT_OPERATOR #define ENH_U_32_BIT_OPERATOR diff --git a/src/wmc_tool/wmc_auto_c.txt b/src/wmc_tool/wmc_auto_c.txt index c18b9dd..caafb65 100644 --- a/src/wmc_tool/wmc_auto_c.txt +++ b/src/wmc_tool/wmc_auto_c.txt @@ -40,7 +40,7 @@ " * Complexity counting tool\r\n", " *--------------------------------------------------------------------*/\r\n", "\r\n", -"\r\n", +"#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */\r\n", "#define MAX_FUNCTION_NAME_LENGTH 200 /* Maximum length of the function name */\r\n", "#define MAX_PARAMS_LENGTH 200 /* Maximum length of the function parameter string */\r\n", "#define MAX_NUM_RECORDS 300 /* Initial maximum number of records -> might be increased during runtime, if needed */\r\n", @@ -49,9 +49,6 @@ "#define DOUBLE_MAX 0x80000000\r\n", "#define FAC ( FRAMES_PER_SECOND / 1e6 )\r\n", "\r\n", -"#define FRAMES_PER_SECOND 50.0\r\n", -"#define PROM_INST_SIZE 32 /* number of bits of each program instruction when stored in the PROM memory (applied only when the user selects reporting in bytes) */\r\n", -"\r\n", "typedef struct\r\n", "{\r\n", " char label[MAX_FUNCTION_NAME_LENGTH];\r\n", diff --git a/src/wmc_tool/wmc_auto_h.txt b/src/wmc_tool/wmc_auto_h.txt index fde3701..0a89db6 100644 --- a/src/wmc_tool/wmc_auto_h.txt +++ b/src/wmc_tool/wmc_auto_h.txt @@ -28,6 +28,7 @@ "#pragma GCC system_header\r\n", "#endif\r\n", "\r\n", +"#define FRAMES_PER_SECOND 50.0\r\n", "#define ENH_32_BIT_OPERATOR\r\n", "#define ENH_64_BIT_OPERATOR\r\n", "#define ENH_U_32_BIT_OPERATOR\r\n",