Skip to content
Commits on Source (127)
......@@ -10,6 +10,8 @@ variables:
LONG_TEST_SUITE: "tests/codec_be_on_mr_nonselection tests/renderer --param_file scripts/config/self_test_ltv.prm --use_ltv"
LONG_TEST_SUITE_NO_RENDERER: "tests/codec_be_on_mr_nonselection --param_file scripts/config/self_test_ltv.prm --use_ltv"
SHORT_TEST_SUITE: "tests/codec_be_on_mr_nonselection"
SHORT_TEST_SUITE_ENCODER: "tests/codec_be_on_mr_nonselection/test_param_file.py --param_file scripts/config/self_test_basop_encoder.prm"
LONG_TEST_SUITE_ENCODER: "tests/codec_be_on_mr_nonselection/test_param_file.py --param_file scripts/config/self_test_ltv_basop_encoder.prm"
TEST_SUITE: ""
DUT_ENCODER_PATH: "./IVAS_cod"
DUT_DECODER_PATH: "./IVAS_dec"
......@@ -28,6 +30,8 @@ variables:
CI_REGRESSION_THRESH_ODG: "-0.05"
GIT_CLEAN_FLAGS: -ffdxq
INSTR_DIR: "scripts/c-code_instrument"
BUILD_WITH_DEBUG_MODE_INFO: ""
ENCODER_TEST: ""
MANUAL_PIPELINE_TYPE:
description: "Type for the manual pipeline run. Use 'pytest-compare' to run comparison test against reference float codec."
value: 'default'
......@@ -38,7 +42,7 @@ variables:
- 'pytest-compare-to-input'
- 'pytest-saturation-smoke-test'
- 'evs-26444'
- 'sanitizer-stv'
- 'sanitizer'
- 'pytest-renderer'
- 'complexity'
- 'coverage'
......@@ -79,7 +83,7 @@ workflow:
- if: $CI_PIPELINE_SOURCE == 'web' && $MANUAL_PIPELINE_TYPE == 'evs-26444'
variables:
IVAS_PIPELINE_NAME: 'EVS 26.444 test: $CI_COMMIT_BRANCH'
- if: $CI_PIPELINE_SOURCE == 'web' && $MANUAL_PIPELINE_TYPE == 'sanitizer-stv'
- if: $CI_PIPELINE_SOURCE == 'web' && $MANUAL_PIPELINE_TYPE == 'sanitizer'
variables:
IVAS_PIPELINE_NAME: 'Short testvectors sanitizers'
- if: $CI_PIPELINE_SOURCE == 'web' && $MANUAL_PIPELINE_TYPE == 'pytest-renderer'
......@@ -117,11 +121,18 @@ stages:
echo "Commit time was $CI_COMMIT_TIMESTAMP"
date | xargs echo "System time is"
.activate-debug-mode-info-if-set: &activate-debug-mode-info-if-set
- if [ "$BUILD_WITH_DEBUG_MODE_INFO" = "true" ]; then
- sed -i.bak -e "s/\/\*\ *\(#define\ *DEBUGGING\ *\)\*\//\1/g" lib_com/options.h
- sed -i.bak -e "s/\/\*\ *\(#define\ *DEBUG_MODE_INFO\ *\)\*\//\1/g" lib_com/options.h
- fi
.build-reference-binaries: &build-reference-binaries
- current_commit_sha=$(git rev-parse HEAD)
### build reference binaries
- git checkout $REFERENCE_BRANCH
- git pull
- *activate-debug-mode-info-if-set
- make clean
- make -j
- mv ./IVAS_cod ./$REF_ENCODER_PATH
......@@ -136,6 +147,7 @@ stages:
### build reference binaries
- *build-reference-binaries
### build dut binaries
- *activate-debug-mode-info-if-set
- make clean
- make -j
......@@ -147,7 +159,9 @@ stages:
- python3 tests/create_short_testvectors.py
# create references
- exit_code=0
- python3 -m pytest $TEST_SUITE -v --update_ref 1 --create_ref -n auto --ref_encoder_path $REF_ENCODER_PATH --ref_decoder_path $REF_DECODER_PATH --dut_encoder_path $DUT_ENCODER_PATH --dut_decoder_path $DUT_DECODER_PATH || exit_code=$?
- enc_stats_arg=""
- if [ "$ENCODER_TEST" = "true" ]; then enc_stats_arg="--enc_stats"; fi
- python3 -m pytest $TEST_SUITE -v --update_ref 1 $enc_stats_arg --create_ref -n auto --ref_encoder_path $REF_ENCODER_PATH --ref_decoder_path $REF_DECODER_PATH --dut_encoder_path $DUT_ENCODER_PATH --dut_decoder_path $DUT_DECODER_PATH || exit_code=$?
.update-scripts-repo: &update-scripts-repo
- cd $SCRIPTS_DIR
......@@ -291,11 +305,17 @@ stages:
- if [ $LEVEL_SCALING != "1.0" ];then
- *apply-testv-scaling
- fi
- if [ "$ENCODER_TEST" = "true" ]; then BUILD_WITH_DEBUG_MODE_INFO="true"; fi
- *build-and-create-reference-outputs
- comp_args="--mld --ssnr --odg"
- if [ "$ENCODER_TEST" = "true" ]; then comp_args="${comp_args} --enc_stats"; fi
- echo "$comp_args"
### run pytest
- exit_code=0
- python3 -m pytest --tb=no $TEST_SUITE -v --create_cut --html=report.html --self-contained-html --junit-xml=report-junit.xml --mld --ssnr --odg -n auto --testcase_timeout $testcase_timeout --ref_encoder_path $REF_ENCODER_PATH --ref_decoder_path $REF_DECODER_PATH --dut_encoder_path $DUT_ENCODER_PATH --dut_decoder_path $DUT_DECODER_PATH || exit_code=$?
- python3 -m pytest --tb=no $TEST_SUITE -v --create_cut --html=report.html --self-contained-html --junit-xml=report-junit.xml $comp_args -n auto --testcase_timeout $testcase_timeout --ref_encoder_path $REF_ENCODER_PATH --ref_decoder_path $REF_DECODER_PATH --dut_encoder_path $DUT_ENCODER_PATH --dut_decoder_path $DUT_DECODER_PATH || exit_code=$?
- zero_errors=$(cat report-junit.xml | grep -c 'errors="0"') || true
- python3 scripts/parse_xml_report.py report-junit.xml $CSV_ARTIFACT_NAME
......@@ -474,14 +494,14 @@ stages:
.ivas-pytest-sanitizers-anchor: &ivas-pytest-sanitizers-anchor
stage: test
needs: ["build-codec-linux-make"]
timeout: "90 minutes"
timeout: "300 minutes"
rules:
- if: $CI_PIPELINE_SOURCE == 'push'
when: never
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
when: never
- if: $CI_PIPELINE_SOURCE == 'schedule' && $IVAS_PYTEST_MSAN
- if: $CI_PIPELINE_SOURCE == 'web' && $MANUAL_PIPELINE_TYPE == "sanitizer-stv"
- if: $CI_PIPELINE_SOURCE == 'web' && $MANUAL_PIPELINE_TYPE == "sanitizer"
script:
- *print-common-info
- *update-scripts-repo
......@@ -491,7 +511,7 @@ stages:
- make -j CLANG=$CLANG_NUM
- if [[ $CLANG_NUM == 3 ]]; then export UBSAN_OPTIONS="suppressions=scripts/ubsan.supp,report_error_type=1"; fi
- testcase_timeout=$TESTCASE_TIMEOUT_STV_SANITIZERS
- python3 -m pytest $SHORT_TEST_SUITE -v --tb=no --update_ref 1 --html=report.html --self-contained-html --junit-xml=report-junit.xml --testcase_timeout $testcase_timeout --ref_encoder_path $DUT_ENCODER_PATH --ref_decoder_path $DUT_DECODER_PATH
- python3 -m pytest $TEST_SUITE -v --tb=no --update_ref 1 --html=report.html --self-contained-html --junit-xml=report-junit.xml --testcase_timeout $testcase_timeout --ref_encoder_path $DUT_ENCODER_PATH --ref_decoder_path $DUT_DECODER_PATH
artifacts:
name: "$CI_JOB_NAME--sha-$CI_COMMIT_SHORT_SHA--results"
when: always
......@@ -683,6 +703,24 @@ build-codec-linux-instrumented-make:
- bash scripts/prepare_instrumentation.sh -m MEM_ONLY -p BASOP
- make -j -C $INSTR_DIR
build-codec-linux-debugging-make:
rules:
- if: $CI_PIPELINE_SOURCE == 'web'
- if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main" # only have MR pipelines for MRs to main
- if: $CI_PIPELINE_SOURCE == 'schedule'
- if: $CI_PIPELINE_SOURCE == 'push'
when: never
extends:
- .build-job-linux
timeout: "7 minutes"
variables:
BUILD_WITH_DEBUG_MODE_INFO: "true"
script:
- *print-common-info
- *activate-debug-mode-info-if-set
- make -j
# ---------------------------------------------------------------
# Short test jobs that run in merge request pipelines
# ---------------------------------------------------------------
......@@ -696,7 +734,7 @@ build-codec-linux-instrumented-make:
# before_script:
# - USE_LTV=0
# - DUT_DECODER_PATH=./IVAS_dec_ref
# - TEST_SUITE="$SHORT_TEST_SUITE"
# - TEST_SUITE="$SHORT_TEST_SUITE_ENCODER"
# - LEVEL_SCALING=1.0
# <<: *ivas-pytest-on-merge-request-anchor
......@@ -707,7 +745,7 @@ build-codec-linux-instrumented-make:
# before_script:
# - USE_LTV=0
# - DUT_DECODER_PATH=./IVAS_dec_ref
# - TEST_SUITE="$SHORT_TEST_SUITE"
# - TEST_SUITE="$SHORT_TEST_SUITE_ENCODER"
# - LEVEL_SCALING=0.3162
# <<: *ivas-pytest-on-merge-request-anchor
......@@ -718,7 +756,7 @@ build-codec-linux-instrumented-make:
# before_script:
# - USE_LTV=0
# - DUT_DECODER_PATH=./IVAS_dec_ref
# - TEST_SUITE="$SHORT_TEST_SUITE"
# - TEST_SUITE="$SHORT_TEST_SUITE_ENCODER"
# - LEVEL_SCALING=3.162
# <<: *ivas-pytest-on-merge-request-anchor
......@@ -771,8 +809,9 @@ ivas-pytest-compare_to_ref-short-enc:
- .test-job-linux
before_script:
- USE_LTV=0
- ENCODER_TEST="true"
- DUT_DECODER_PATH=./$REF_DECODER_PATH
- TEST_SUITE="$SHORT_TEST_SUITE"
- TEST_SUITE="$SHORT_TEST_SUITE_ENCODER"
- LEVEL_SCALING=1.0
<<: *ivas-pytest-anchor
......@@ -783,8 +822,9 @@ ivas-pytest-compare_to_ref-short-enc-lev-10:
- .test-job-linux
before_script:
- USE_LTV=0
- ENCODER_TEST="true"
- DUT_DECODER_PATH=./$REF_DECODER_PATH
- TEST_SUITE="$SHORT_TEST_SUITE"
- TEST_SUITE="$SHORT_TEST_SUITE_ENCODER"
- LEVEL_SCALING=0.3162
<<: *ivas-pytest-anchor
......@@ -795,8 +835,9 @@ ivas-pytest-compare_to_ref-short-enc-lev+10:
- .test-job-linux
before_script:
- USE_LTV=0
- ENCODER_TEST="true"
- DUT_DECODER_PATH=./$REF_DECODER_PATH
- TEST_SUITE="$SHORT_TEST_SUITE"
- TEST_SUITE="$SHORT_TEST_SUITE_ENCODER"
- LEVEL_SCALING=3.162
<<: *ivas-pytest-anchor
......@@ -806,6 +847,7 @@ ivas-pytest-enc-msan:
before_script:
- CLANG_NUM=1
- DUT_DECODER_PATH=./$REF_DECODER_PATH
- TEST_SUITE=$LONG_TEST_SUITE_ENCODER
<<: *ivas-pytest-sanitizers-anchor
ivas-pytest-enc-asan:
......@@ -814,6 +856,7 @@ ivas-pytest-enc-asan:
before_script:
- CLANG_NUM=2
- DUT_DECODER_PATH=./$REF_DECODER_PATH
- TEST_SUITE=$LONG_TEST_SUITE_ENCODER
<<: *ivas-pytest-sanitizers-anchor
ivas-pytest-enc-usan:
......@@ -822,6 +865,7 @@ ivas-pytest-enc-usan:
before_script:
- CLANG_NUM=3
- DUT_DECODER_PATH=./$REF_DECODER_PATH
- TEST_SUITE=$SHORT_TEST_SUITE_ENCODER
<<: *ivas-pytest-sanitizers-anchor
### jobs that test flt encoder -> fx decoder
......@@ -858,6 +902,7 @@ ivas-pytest-compare_to_ref-short-dec-lev+10:
- LEVEL_SCALING=3.162
<<: *ivas-pytest-anchor
### jobs that compare the output synthesis to the input files directly
ivas-pytest-compare-to-input-short-dec:
extends:
- .rules-pytest-to-input-short
......@@ -876,32 +921,35 @@ ivas-pytest-compare-to-input-short-enc:
before_script:
- USE_LTV=0
- DUT_DECODER_PATH=./$REF_DECODER_PATH
- TEST_SUITE="$SHORT_TEST_SUITE"
- TEST_SUITE="$SHORT_TEST_SUITE_ENCODER"
- LEVEL_SCALING=1.0
<<: *ivas-pytest-compare-to-input-anchor
ivas-pytest-dec-msan-short:
ivas-pytest-dec-msan:
extends:
- .test-job-linux
before_script:
- CLANG_NUM=1
- DUT_ENCODER_PATH=./$REF_ENCODER_PATH
- TEST_SUITE=$LONG_TEST_SUITE_SELF_TEST
<<: *ivas-pytest-sanitizers-anchor
ivas-pytest-dec-asan-short:
ivas-pytest-dec-asan:
extends:
- .test-job-linux
before_script:
- CLANG_NUM=2
- DUT_ENCODER_PATH=./$REF_ENCODER_PATH
- TEST_SUITE=$LONG_TEST_SUITE_SELF_TEST
<<: *ivas-pytest-sanitizers-anchor
ivas-pytest-dec-usan-short:
ivas-pytest-dec-usan:
extends:
- .test-job-linux
before_script:
- CLANG_NUM=3
- DUT_ENCODER_PATH=./$REF_ENCODER_PATH
- TEST_SUITE=$SHORT_TEST_SUITE
<<: *ivas-pytest-sanitizers-anchor
# ---------------------------------------------------------------
......@@ -915,7 +963,7 @@ ivas-pytest-compare_ref-long-enc:
before_script:
- USE_LTV=1
- DUT_DECODER_PATH=./$REF_DECODER_PATH
- TEST_SUITE="$LONG_TEST_SUITE"
- TEST_SUITE="$LONG_TEST_SUITE_ENCODER"
- LEVEL_SCALING=1.0
<<: *ivas-pytest-anchor
......@@ -937,7 +985,7 @@ ivas-pytest-compare_ref-long-enc-lev-10:
before_script:
- USE_LTV=1
- DUT_DECODER_PATH=./$REF_DECODER_PATH
- TEST_SUITE="$LONG_TEST_SUITE"
- TEST_SUITE="$LONG_TEST_SUITE_ENCODER"
- LEVEL_SCALING=0.3162
<<: *ivas-pytest-anchor
......@@ -959,7 +1007,7 @@ ivas-pytest-compare_ref-long-enc-lev+10:
before_script:
- USE_LTV=1
- DUT_DECODER_PATH=./$REF_DECODER_PATH
- TEST_SUITE="$LONG_TEST_SUITE"
- TEST_SUITE="$LONG_TEST_SUITE_ENCODER"
- LEVEL_SCALING=3.162
<<: *ivas-pytest-anchor
......
......@@ -142,9 +142,7 @@
<ClCompile Include="..\lib_com\cng_exc_fx.c" />
<ClCompile Include="..\lib_com\codec_tcx_common.c" />
<ClCompile Include="..\lib_com\complex_basop.c" />
<ClCompile Include="..\lib_com\control.c" />
<ClCompile Include="..\lib_com\core_com_config.c" />
<ClCompile Include="..\lib_com\count.c" />
<ClCompile Include="..\lib_com\deemph.c" />
<ClCompile Include="..\lib_com\delay_comp.c" />
<ClCompile Include="..\lib_com\disclaimer.c" />
......@@ -160,7 +158,6 @@
<ClCompile Include="..\lib_com\env_adj.c" />
<ClCompile Include="..\lib_com\env_stab.c" />
<ClCompile Include="..\lib_com\env_stab_trans.c" />
<ClCompile Include="..\lib_com\est_tilt.c" />
<ClCompile Include="..\lib_com\est_tilt_fx.c" />
<ClCompile Include="..\lib_com\fd_cng_com_fx.c" />
<ClCompile Include="..\lib_com\fft.c" />
......@@ -172,19 +169,16 @@
<ClCompile Include="..\lib_com\fft_rel_fx.c" />
<ClCompile Include="..\lib_com\fill_spectrum.c" />
<ClCompile Include="..\lib_com\findpulse.c" />
<ClCompile Include="..\lib_com\fine_gain_bits.c" />
<ClCompile Include="..\lib_com\fine_gain_bits_fx.c" />
<ClCompile Include="..\lib_com\float_to_fix_ops.c" />
<ClCompile Include="..\lib_com\frame_ener_fx.c" />
<ClCompile Include="..\lib_com\gain_inov_fx.c" />
<ClCompile Include="..\lib_com\get_gain_fx.c" />
<ClCompile Include="..\lib_com\gs_bitallocation.c" />
<ClCompile Include="..\lib_com\gs_bitallocation_fx.c" />
<ClCompile Include="..\lib_com\gs_bitallocation_ivas_fx.c" />
<ClCompile Include="..\lib_com\gs_gains.c" />
<ClCompile Include="..\lib_com\gs_gains_fx.c" />
<ClCompile Include="..\lib_com\gs_inact_switching_fx.c" />
<ClCompile Include="..\lib_com\gs_noisefill.c" />
<ClCompile Include="..\lib_com\gs_noisefill_fx.c" />
<ClCompile Include="..\lib_com\gs_preech_fx.c" />
<ClCompile Include="..\lib_com\guided_plc_util_fx.c" />
......@@ -278,7 +272,6 @@
<ClCompile Include="..\lib_com\rom_basic_math.c" />
<ClCompile Include="..\lib_com\rom_basop_util.c" />
<ClCompile Include="..\lib_com\rom_com.c" />
<ClCompile Include="..\lib_com\ivas_sns_com.c" />
<ClCompile Include="..\lib_com\rom_com_fx.c" />
<ClCompile Include="..\lib_com\scale_mem_fx.c" />
<ClCompile Include="..\lib_com\stab_est_fx.c" />
......
......@@ -10,9 +10,6 @@
<ClCompile Include="..\lib_com\ivas_sba_config.c">
<Filter>common_ivas_c</Filter>
</ClCompile>
<ClCompile Include="..\lib_com\ivas_sns_com.c">
<Filter>common_ivas_c</Filter>
</ClCompile>
<ClCompile Include="..\lib_com\ivas_mc_com.c">
<Filter>common_ivas_c</Filter>
</ClCompile>
......@@ -79,9 +76,6 @@
<ClCompile Include="..\lib_com\ivas_lfe_com.c">
<Filter>common_ivas_c</Filter>
</ClCompile>
<ClCompile Include="..\lib_com\control.c">
<Filter>common_all_c</Filter>
</ClCompile>
<ClCompile Include="..\lib_com\enh64.c">
<Filter>common_all_c</Filter>
</ClCompile>
......@@ -386,15 +380,11 @@
<ClCompile Include="..\lib_com\enr_1_az.c" />
<ClCompile Include="..\lib_com\env_adj.c" />
<ClCompile Include="..\lib_com\env_stab.c" />
<ClCompile Include="..\lib_com\est_tilt.c" />
<ClCompile Include="..\lib_com\fft.c" />
<ClCompile Include="..\lib_com\fft_rel.c" />
<ClCompile Include="..\lib_com\fill_spectrum.c" />
<ClCompile Include="..\lib_com\findpulse.c" />
<ClCompile Include="..\lib_com\fine_gain_bits.c" />
<ClCompile Include="..\lib_com\gs_bitallocation.c" />
<ClCompile Include="..\lib_com\gs_gains.c" />
<ClCompile Include="..\lib_com\gs_noisefill.c" />
<ClCompile Include="..\lib_com\hq2_core_com.c" />
<ClCompile Include="..\lib_com\hq_conf.c" />
<ClCompile Include="..\lib_com\ifft_rel.c" />
......@@ -424,7 +414,6 @@
<ClCompile Include="..\lib_com\tools.c" />
<ClCompile Include="..\lib_com\wtda.c" />
<ClCompile Include="..\lib_com\gs_bitallocation_ivas_fx.c" />
<ClCompile Include="..\lib_com\count.c" />
<ClCompile Include="..\lib_com\ivas_stereo_ica_com_fx.c" />
<ClCompile Include="..\lib_com\frame_ener_fx.c" />
<ClCompile Include="..\lib_com\get_gain_fx.c" />
......
......@@ -159,7 +159,9 @@ HISTORY:
#include <stdio.h>
#include <stdlib.h>
#include "options.h"
#include "stl.h"
#ifdef BASOP_NOGLOB
#include <assert.h>
#endif /* BASOP_NOGLOB */
......@@ -170,10 +172,6 @@ HISTORY:
#pragma warning( disable : 4310 )
#endif
#ifdef WMOPS
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
#endif
/*___________________________________________________________________________
| |
......@@ -2825,6 +2823,11 @@ Word16 shr_ro( Word16 var1, Word16 var2, Flag *Overflow )
{
var_out = shr_o( var1, var2, Overflow );
#ifdef FIX_1049_SHR_RO_COMPLEXITY
#ifdef WMOPS
multiCounter[currCounter].shr--;
#endif
#endif
if ( var2 > 0 )
{
if ( ( var1 & ( (Word16) 1 << ( var2 - 1 ) ) ) != 0 )
......@@ -2833,6 +2836,15 @@ Word16 shr_ro( Word16 var1, Word16 var2, Flag *Overflow )
}
}
}
#ifdef FIX_1049_SHR_RO_COMPLEXITY
#ifdef WMOPS
multiCounter[currCounter].shr_r++;
#endif
BASOP_CHECK();
#endif
return ( var_out );
}
Word16 shr_r_sat( Word16 var1, Word16 var2 )
......
......@@ -43,7 +43,6 @@
#include "rom_com.h"
#include "rom_basic_math.h"
#include "basop_settings.h"
#include "control.h"
#include "cnst.h"
......@@ -1556,7 +1555,7 @@ Word16 findIndexOfMinWord32( Word32 *x, const Word16 len )
Word16 imult1616( Word16 x, Word16 y )
{
assert( (int) x * (int) y < 32768 && (int) x * (int) y >= -32768 );
return extract_l( L_mult0( x, y ) );
return i_mult( x, y );
}
Word32 imult3216( Word32 x, Word16 y )
......
......@@ -9,22 +9,9 @@
*****************************************************************************/
#include "typedef.h"
#include "basop32.h"
#include "complex_basop.h"
#include "stl.h"
#ifdef WMOPS
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
#endif /* if WMOPS */
#define WMC_TOOL_SKIP
#ifdef COMPLEX_OPERATOR
......
......@@ -10,8 +10,6 @@
#ifndef _COMPLEX_BASIC_OP_H
#define _COMPLEX_BASIC_OP_H
#include "typedef.h"
#include "basop32.h"
#include "stl.h"
#ifdef COMPLEX_OPERATOR
......
/*
===========================================================================
File: CONTROL.C v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
CONTROL FLOW OPERATOR INTERNAL VARIABLE DECLARATIONS
History:
07 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
March 06 v2.1 Changed to improve portability.
============================================================================
*/
#include "stl.h"
#ifdef WMOPS
int funcId_where_last_call_to_else_occurred;
long funcid_total_wmops_at_last_call_to_else;
int call_occurred = 1;
#endif
#ifdef CONTROL_CODE_OPS
Flag LT_16( Word16 var1, Word16 var2 )
{
Flag F_ret = 0;
if ( var1 < var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].LT_16++;
#endif
return F_ret;
}
Flag GT_16( Word16 var1, Word16 var2 )
{
Flag F_ret = 0;
if ( var1 > var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].GT_16++;
#endif
return F_ret;
}
Flag LE_16( Word16 var1, Word16 var2 )
{
Flag F_ret = 0;
if ( var1 <= var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].LE_16++;
#endif
return F_ret;
}
Flag GE_16( Word16 var1, Word16 var2 )
{
Flag F_ret = 0;
if ( var1 >= var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].GE_16++;
#endif
return F_ret;
}
Flag EQ_16( Word16 var1, Word16 var2 )
{
Flag F_ret = 0;
if ( var1 == var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].EQ_16++;
#endif
return F_ret;
}
Flag NE_16( Word16 var1, Word16 var2 )
{
Flag F_ret = 0;
if ( var1 != var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].NE_16++;
#endif
return F_ret;
}
Flag LT_32( Word32 L_var1, Word32 L_var2 )
{
Flag F_ret = 0;
if ( L_var1 < L_var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].LT_32++;
#endif
return F_ret;
}
Flag GT_32( Word32 L_var1, Word32 L_var2 )
{
Flag F_ret = 0;
if ( L_var1 > L_var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].GT_32++;
#endif
return F_ret;
}
Flag LE_32( Word32 L_var1, Word32 L_var2 )
{
Flag F_ret = 0;
if ( L_var1 <= L_var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].LE_32++;
#endif
return F_ret;
}
Flag GE_32( Word32 L_var1, Word32 L_var2 )
{
Flag F_ret = 0;
if ( L_var1 >= L_var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].GE_32++;
#endif
return F_ret;
}
Flag EQ_32( Word32 L_var1, Word32 L_var2 )
{
Flag F_ret = 0;
if ( L_var1 == L_var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].EQ_32++;
#endif
return F_ret;
}
Flag NE_32( Word32 L_var1, Word32 L_var2 )
{
Flag F_ret = 0;
if ( L_var1 != L_var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].NE_32++;
#endif
return F_ret;
}
Flag LT_64( Word64 L64_var1, Word64 L64_var2 )
{
Flag F_ret = 0;
if ( L64_var1 < L64_var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].LT_64++;
#endif
return F_ret;
}
Flag GT_64( Word64 L64_var1, Word64 L64_var2 )
{
Flag F_ret = 0;
if ( L64_var1 > L64_var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].GT_64++;
#endif
return F_ret;
}
Flag LE_64( Word64 L64_var1, Word64 L64_var2 )
{
Flag F_ret = 0;
if ( L64_var1 <= L64_var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].LE_64++;
#endif
return F_ret;
}
Flag GE_64( Word64 L64_var1, Word64 L64_var2 )
{
Flag F_ret = 0;
if ( L64_var1 >= L64_var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].GE_64++;
#endif
return F_ret;
}
Flag EQ_64( Word64 L64_var1, Word64 L64_var2 )
{
Flag F_ret = 0;
if ( L64_var1 == L64_var2 )
{
F_ret = 1;
}
#ifdef WMOPS
multiCounter[currCounter].EQ_64++;
#endif
return F_ret;
}
Flag NE_64( Word64 L64_var1, Word64 L64_var2 )
{
Flag 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 */
/* end of file */
/******************************************************************************************************
(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository. All Rights Reserved.
This software is protected by copyright law and by international treaties.
The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository retain full ownership rights in their respective contributions in
the software. This notice grants no license of any kind, including but not limited to patent
license, nor is any license granted by implication, estoppel or otherwise.
Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
contributions.
This software is provided "AS IS", without any express or implied warranties. The software is in the
development stage. It is intended exclusively for experts who have experience with such software and
solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
and fitness for a particular purpose are hereby disclaimed and excluded.
Any dispute, controversy or claim arising under or in relation to providing this software shall be
submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
the United Nations Convention on Contracts on the International Sales of Goods.
*******************************************************************************************************/
#ifndef _CONTROL_H
#define _CONTROL_H
#include "stl.h"
/*****************************************************************************
*
* Constants and Globals
*
*****************************************************************************/
#ifdef WMOPS
extern BASIC_OP multiCounter[MAXCOUNTERS];
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;
#endif /* ifdef WMOPS */
/*****************************************************************************
*
* Function Macros
*
*****************************************************************************/
/*****************************************************************************
*
* 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 /* ifndef WMOPS */
#define FOR( a ) \
if ( incrFor(), 0 ) \
; \
else \
for ( a )
static __inline void incrFor( void )
{
multiCounter[currCounter].For++;
}
#endif /* ifndef WMOPS */
/*****************************************************************************
*
* 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 /* ifndef WMOPS */
#define WHILE( a ) while ( incrWhile(), a )
static __inline void incrWhile( void )
{
multiCounter[currCounter].While++;
}
#endif /* ifndef WMOPS */
/*****************************************************************************
*
* 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 /* ifndef WMOPS */
#define DO do
#endif /* ifndef WMOPS */
/*****************************************************************************
*
* 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 /* ifndef WMOPS */
#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 = MAXCOUNTERS;
}
#endif /* ifndef WMOPS */
/*****************************************************************************
*
* 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 /* ifndef WMOPS */
#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 /* ifndef WMOPS */
/*****************************************************************************
*
* 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 /* ifndef WMOPS */
#define SWITCH( a ) switch ( incrSwitch(), a )
static __inline void incrSwitch( void )
{
multiCounter[currCounter].Switch++;
}
#endif /* ifndef WMOPS */
/*****************************************************************************
*
* 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 /* ifndef WMOPS */
#define CONTINUE \
if ( incrContinue(), 0 ) \
; \
else \
continue
static __inline void incrContinue( void )
{
multiCounter[currCounter].Continue++;
}
#endif /* ifndef WMOPS */
/*****************************************************************************
*
* 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 /* ifndef WMOPS */
#define BREAK \
if ( incrBreak(), 0 ) \
; \
else \
break
static __inline void incrBreak( void )
{
multiCounter[currCounter].Break++;
}
#endif /* ifndef WMOPS */
/*****************************************************************************
*
* 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 /* ifndef WMOPS */
#define GOTO \
if ( incrGoto(), 0 ) \
; \
else \
goto
static __inline void incrGoto( void )
{
multiCounter[currCounter].Goto++;
}
#endif /* ifndef WMOPS */
/*
* New control code basops
*/
#ifdef CONTROL_CODE_OPS
Flag LT_16( Word16 var1, Word16 var2 );
Flag GT_16( Word16 var1, Word16 var2 );
Flag LE_16( Word16 var1, Word16 var2 );
Flag GE_16( Word16 var1, Word16 var2 );
Flag EQ_16( Word16 var1, Word16 var2 );
Flag NE_16( Word16 var1, Word16 var2 );
Flag LT_32( Word32 L_var1, Word32 L_var2 );
Flag GT_32( Word32 L_var1, Word32 L_var2 );
Flag LE_32( Word32 L_var1, Word32 L_var2 );
Flag GE_32( Word32 L_var1, Word32 L_var2 );
Flag EQ_32( Word32 L_var1, Word32 L_var2 );
Flag NE_32( Word32 L_var1, Word32 L_var2 );
Flag LT_64( Word64 L64_var1, Word64 L64_var2 );
Flag GT_64( Word64 L64_var1, Word64 L64_var2 );
Flag LE_64( Word64 L64_var1, Word64 L64_var2 );
Flag GE_64( Word64 L64_var1, Word64 L64_var2 );
Flag EQ_64( Word64 L64_var1, Word64 L64_var2 );
Flag NE_64( Word64 L64_var1, Word64 L64_var2 );
#endif /* #ifdef CONTROL_CODE_OPS */
#endif /* _CONTROL_H */
/* end of file */
/*
===========================================================================
File: COUNT.C v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
COMPLEXITY EVALUATION FUNCTIONS
History:
03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
norm_s() weight reduced from 15 to 1.
norm_l() weight reduced from 30 to 1.
L_abs() weight reduced from 2 to 1.
L_add() weight reduced from 2 to 1.
L_negate() weight reduced from 2 to 1.
L_shl() weight reduced from 2 to 1.
L_shr() weight reduced from 2 to 1.
L_sub() weight reduced from 2 to 1.
mac_r() weight reduced from 2 to 1.
msu_r() weight reduced from 2 to 1.
mult_r() weight reduced from 2 to 1.
L_deposit_h() weight reduced from 2 to 1.
L_deposit_l() weight reduced from 2 to 1.
March 06 v2.1 Changed to improve portability.
Dec 06 v2.2 Changed to specify frame rate using setFrameRate()
Adding WMOPS_output_avg() for global average computation
L_mls() weight of 5.
div_l() weight of 32.
i_mult() weight of 3.
============================================================================
*/
/*****************************************************************************
*
* This file contains functions for the automatic complexity calculation
*
*****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "stl.h"
#include "options.h"
#include "wmc_auto.h"
#ifndef WMOPS
#include "options_warnings.h"
#endif
#define WMC_TOOL_SKIP
#ifdef WMOPS
static double frameRate = FRAME_RATE; /* default value : 10 ms */
#define MAX_RECORDS 1024
#define MAX_STACK 64
#define MAX_CHAR 64
// 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;
// };
//
// static struct wmops_record wmops[MAX_RECORDS];
static int stack[MAX_STACK];
static int sptr;
static int sum_stack[MAX_STACK];
/* Global counter variable for calculation of complexity weight */
/* Some enhancement written by Vail., GJR and M.Mul. during EVS time */
BASIC_OP multiCounter[MAXCOUNTERS];
BASIC_OP glob_multiCounter;
int currCounter = 0; /* Zero equals global counter */
void setFrameRate( int samplingFreq, int frameLength )
{
if ( frameLength > 0 )
{
frameRate = samplingFreq / 1000000.0 / frameLength;
}
return;
}
/*
* Below list is used for displaying the code profiling information in
* the file which name is defined by CODE_PROFILE_FILENAME.
* For further details see generic_WMOPS_output() function.
* Attention, the ordering in this table must be kept in synchronisation
* with the structure definition BASIC_OP.
*/
char *BasicOperationList[] = {
"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"
/* New complex basops */
#ifdef COMPLEX_OPERATOR
,
"CL_shr", "CL_shl", "CL_add", "CL_sub", "CL_scale", "CL_dscale", "CL_msu_j", "CL_mac_j", "CL_move", "CL_Extract_real", "CL_Extract_imag", "CL_form", "CL_multr_32x16", "CL_negate", "CL_conjugate", "CL_mul_j", "CL_swap_real_imag", "C_add", "C_sub", "C_mul_j", "C_multr", "C_form"
,
"C_scale", "CL_round32_16", "CL_scale_32", "CL_dscale_32", "CL_multr_32x32", "C_mac_r", "C_msu_r", "C_Extract_real", "C_Extract_imag", "C_negate", "C_conjugate", "C_shr", "C_shl"
#endif /* #ifdef COMPLEX_OPERATOR */
/* New 64 bit basops */
#ifdef ENH_64_BIT_OPERATOR
,
"move64", "W_add_nosat", "W_sub_nosat", "W_shl", "W_shr", "W_shl_nosat", "W_shr_nosat", "W_mac_32_16", "W_msu_32_16", "W_mult_32_16", "W_mult0_16_16", "W_mac0_16_16", "W_msu0_16_16", "W_mult_16_16", "W_mac_16_16", "W_msu_16_16", "W_shl_sat_l", "W_sat_l", "W_sat_m", "W_deposit32_l", "W_deposit32_h", "W_extract_l", "W_extract_h", "W_round48_L", "W_round32_s", "W_norm", "W_add", "W_sub", "W_neg", "W_abs", "W_mult_32_32", "W_mult0_32_32", "W_lshl", "W_lshr", "W_round64_L"
#endif /* #ifdef ENH_64_BIT_OPERATOR */
#ifdef ENH_32_BIT_OPERATOR
,
"Mpy_32_16_1", "Mpy_32_16_r", "Mpy_32_32", "Mpy_32_32_r", "Madd_32_16", "Madd_32_16_r", "Msub_32_16", "Msub_32_16_r", "Madd_32_32", "Madd_32_32_r", "Msub_32_32", "Msub_32_32_r"
#endif /* #ifdef ENH_32_BIT_OPERATOR */
#ifdef ENH_U_32_BIT_OPERATOR
,
"UL_addNs", "UL_subNs", "UL_Mpy_32_32", "Mpy_32_32_uu", "Mpy_32_16_uu", "norm_ul_float", "UL_deposit_l"
#endif /* #ifdef ENH_U_32_BIT_OPERATOR */
#ifdef CONTROL_CODE_OPS
,
"LT_16", "GT_16", "LE_16", "GE_16", "EQ_16", "NE_16", "LT_32", "GT_32", "LE_32", "GE_32", "EQ_32", "NE_32", "LT_64", "GT_64", "LE_64", "GE_64", "EQ_64", "NE_64"
#endif /* #ifdef CONTROL_CODE_OPS */
};
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, 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 */
};
#endif /* ifdef WMOPS */
Word32 TotalWeightedOperation( void );
Word32 DeltaWeightedOperation( void );
#ifdef WMOPS
/* Counters for separating counting for different objects */
/* FROM_EVS_DEV */
/**
maxCounter: current number of counters. Each scope initialized with BASOP_sub_start() gets a own counter assigned.
objectName: Name of each counter passed to BASOP_sub_start().
fwc_corr:
nbTimeObjectIsCalled: number of times a counter (object) is referenced in the current frame.
*/
static int maxCounter = 0;
static char *objectName[MAXCOUNTERS + 1];
static Word16 fwc_corr[MAXCOUNTERS + 1];
static long int nbTimeObjectIsCalled[MAXCOUNTERS + 1];
#define NbFuncMax ( 4096 )
/**
funcid: current function call for each counter
bc : best case for each counter and function call
wc : worst case for each counter and function call
nbframe: number of frames for each counter.
glob_bc: global best case self time for each counter for current frame.
glob_wc: global worst case self time for each counter for current frame.
glob_sum_curr: global cummulative time for each counter for current frame.
glob_sum_bc: global best case cummulative time for each counter for current frame.
glob_sum_wc: global worst case cummulative time for each counter for current frame.
total_wmops: total wmops self time for each counter for current frame.
total_sum: total wmops cummulative time for each counter for current frame.
LastWOper: values used for WMOPS deltas
*/
static Word32 funcid[MAXCOUNTERS], nbframe[MAXCOUNTERS], nbcalls[MAXCOUNTERS];
static Word32 glob_bc[MAXCOUNTERS], glob_wc[MAXCOUNTERS], bc[MAXCOUNTERS][NbFuncMax], wc[MAXCOUNTERS][NbFuncMax];
static float total_wmops[MAXCOUNTERS];
static Word32 LastWOper[MAXCOUNTERS];
/* FROM_EVS_DEV */
static float total_sum[MAXCOUNTERS];
static Word16 call_tree[MAXCOUNTERS][MAXCOUNTERS];
static int sum_curr[MAXCOUNTERS + 1];
static int sum_bc[MAXCOUNTERS + 1];
static int sum_wc[MAXCOUNTERS + 1];
static int glob_sum_curr[MAXCOUNTERS + 1];
static int glob_sum_bc[MAXCOUNTERS + 1];
static int glob_sum_wc[MAXCOUNTERS + 1];
#if MAX_CALLERS_SAVED_FRAMES
#define MAX_CALLERS_PRINT 20
static float callers_frames[MAX_CALLERS_SAVED_FRAMES + 1][MAXCOUNTERS + 1];
static int callers_frames_nos[MAX_CALLERS_SAVED_FRAMES];
static float callers_totals[MAX_CALLERS_SAVED_FRAMES];
#endif
#endif /* ifdef WMOPS */
#ifdef WMOPS
static char *my_strdup( const char *s )
{
/*
* duplicates UNIX function strdup() which is not ANSI standard:
* -- malloc() memory area big enough to hold the string s
* -- copy string into new area
* -- return pointer to new area
*
* returns NULL if either s==NULL or malloc() fails
*/
char *dup;
if ( s == NULL )
return NULL;
/* allocate memory for copy of ID string (including string terminator) */
/* NOTE: the ID strings will never be deallocated because there is no way to "destroy" a counter that is not longer needed */
if ( ( dup = (char *) malloc( strlen( s ) + 1 ) ) == NULL )
return NULL;
return strcpy( dup, s );
}
#endif /* ifdef WMOPS */
int getCounterId( const char *objectNameArg )
{
#ifdef WMOPS
if ( maxCounter >= MAXCOUNTERS - 1 )
return 0;
objectName[++maxCounter] = my_strdup( objectNameArg );
return maxCounter;
#else /* ifdef WMOPS */
(void) objectNameArg;
return 0; /* Dummy */
#endif /* ifdef WMOPS */
}
#ifdef WMOPS
int readCounterId()
{
return currCounter;
}
#endif /* ifdef WMOPS */
#ifdef WMOPS
char *readCounterIdName()
{
return objectName[currCounter];
}
#endif /* ifdef WMOPS */
void setCounter( int counterId )
{
#ifdef WMOPS
if ( ( counterId > maxCounter ) || ( counterId < 0 ) )
{
currCounter = 0;
return;
}
currCounter = counterId;
call_occurred = 1;
#else
(void) counterId;
#endif /* ifdef WMOPS */
}
void incrementNbTimeObjectIsCalled( int counterId )
{
#ifdef WMOPS
if ( ( counterId > maxCounter ) || ( counterId < 0 ) )
{
nbTimeObjectIsCalled[0]++;
return;
}
nbTimeObjectIsCalled[counterId]++;
#else
(void) counterId;
#endif /* ifdef WMOPS */
}
#ifdef WMOPS
static Word32 WMOPS_frameStat( void )
{
/* calculate the WMOPS seen so far and update the global
per-frame maximum (glob_wc)
*/
Word32 tot;
tot = TotalWeightedOperation();
if ( tot > glob_wc[currCounter] )
{
glob_wc[currCounter] = tot;
}
if ( tot < glob_bc[currCounter] )
{
glob_bc[currCounter] = tot;
}
/* check if fwc() was forgotten at end of last frame */
if ( tot > LastWOper[currCounter] )
{
if ( !fwc_corr[currCounter] )
{
fprintf( stderr,
"count: operations counted after last fwc() for '%s'; "
"-> fwc() called\n",
objectName[currCounter] ? objectName[currCounter] : "" );
}
fwc();
}
return tot;
}
#endif /* ifdef WMOPS */
#ifdef WMOPS
static void WMOPS_clearMultiCounter( void )
{
Word16 i;
Word32 *ptr = (Word32 *) &multiCounter[currCounter];
for ( i = 0; i < (Word16) ( sizeof( multiCounter[currCounter] ) / sizeof( Word32 ) ); i++ )
{
*ptr++ = 0;
}
}
#endif /* ifdef WMOPS */
void ClearNbTimeObjectsAreCalled()
{
#ifdef WMOPS
Word16 i;
for ( i = 0; i < (Word16) ( sizeof( multiCounter[currCounter] ) / sizeof( Word32 ) ); i++ )
{
nbTimeObjectIsCalled[i] = 0;
}
#endif /* ifdef WMOPS */
}
Word32 TotalWeightedOperation()
{
#ifdef WMOPS
Word16 i;
Word32 tot, *ptr;
const Word32 *ptr2;
tot = 0;
ptr = (Word32 *) &multiCounter[currCounter];
ptr2 = (const Word32 *) &op_weight;
for ( i = 0; i < (Word16) ( sizeof( multiCounter[currCounter] ) / sizeof( Word32 ) ); i++ )
{
tot += ( ( *ptr++ ) * ( *ptr2++ ) );
}
return ( (Word32) tot );
#else /* ifdef WMOPS */
return 0; /* Dummy */
#endif /* ifdef WMOPS */
}
Word32 DeltaWeightedOperation()
{
#ifdef WMOPS
Word32 NewWOper, delta;
NewWOper = TotalWeightedOperation();
delta = NewWOper - LastWOper[currCounter];
LastWOper[currCounter] = NewWOper;
return ( delta );
#else /* ifdef WMOPS */
return 0; /* Dummy */
#endif /* ifdef WMOPS */
}
void Init_WMOPS_counter( void )
{
#ifdef WMOPS
Word16 i;
/* reset function weight operation counter variable */
for ( i = 0; i < NbFuncMax; i++ )
wc[currCounter][i] = (Word32) 0;
glob_wc[currCounter] = 0;
nbframe[currCounter] = 0;
total_wmops[currCounter] = 0.0;
for ( i = 0; i < NbFuncMax; i++ )
{
bc[currCounter][i] = (Word32) MAX_32;
}
glob_bc[currCounter] = MAX_32;
nbcalls[currCounter] = 0;
total_sum[currCounter] = 0.0;
/* initially clear all counters */
WMOPS_clearMultiCounter();
LastWOper[currCounter] = 0;
funcid[currCounter] = 0;
/* Following line is useful for incrIf(), see control.h */
call_occurred = 1;
funcId_where_last_call_to_else_occurred = MAXCOUNTERS;
sum_bc[currCounter] = MAX_32;
sum_wc[currCounter] = 0;
sum_curr[currCounter] = 0;
for ( i = 0; i < MAXCOUNTERS; i++ )
{
call_tree[currCounter][i] = -1;
}
glob_sum_curr[currCounter] = 0;
glob_sum_wc[currCounter] = 0;
glob_sum_bc[currCounter] = MAX_32;
#endif /* ifdef WMOPS */
}
Word32 Reset_WMOPS_counter( void )
{
#ifdef WMOPS
Word32 tot = WMOPS_frameStat();
/* increase the frame counter --> a frame is counted WHEN IT BEGINS */
nbframe[currCounter]++;
/* Call counter */
nbcalls[currCounter] += funcid[currCounter];
/* add wmops used in last frame to count, then reset counter (in first frame, this is a no-op */
total_wmops[currCounter] += (float) ( tot * frameRate );
total_sum[currCounter] += (float) ( ( glob_sum_curr[currCounter] ) * frameRate );
/* clear counter before new frame starts */
WMOPS_clearMultiCounter();
LastWOper[currCounter] = 0;
funcid[currCounter] = 0; /* new frame, set function id to zero */
glob_sum_curr[currCounter] = 0;
sum_curr[currCounter] = 0;
return tot;
#else
return 0;
#endif /* ifdef WMOPS */
}
Word32 fwc( void )
{
/* function worst case */
#ifdef WMOPS
Word32 tot;
tot = DeltaWeightedOperation();
if ( tot > wc[currCounter][funcid[currCounter]] )
wc[currCounter][funcid[currCounter]] = tot;
if ( tot < bc[currCounter][funcid[currCounter]] )
bc[currCounter][funcid[currCounter]] = tot;
funcid[currCounter]++;
/*make sure that BASOP_frame_update(); is put at the end of the main loop*/
if ( funcid[currCounter] >= NbFuncMax )
{
printf( "to many function calls\n" );
}
assert( funcid[currCounter] < NbFuncMax );
return ( tot );
#else
return 0;
#endif /* ifdef WMOPS */
}
void WMOPS_output( Word16 dtx_mode )
{
#ifdef WMOPS
Word16 i;
Word32 tot, tot_wm, tot_wc;
/* get operations since last reset (or init), but do not update the counters (except the glob_wc[] maximum)
so output CAN be called in each frame without problems. The frame counter is NOT updated! */
tot = WMOPS_frameStat();
tot_wm = (Word32) ( total_wmops[currCounter] + ( (float) tot ) * frameRate );
fprintf( stdout,
"%10s:WMOPS=%.3f", objectName[currCounter] ? objectName[currCounter] : "",
( (float) tot ) * frameRate );
if ( nbframe[currCounter] != 0 )
{
fprintf( stdout, " Average=%.3f", tot_wm / (float) nbframe[currCounter] );
}
fprintf( stdout, " WorstCase=%.3f", ( (float) glob_wc[currCounter] ) * frameRate );
/* Worst worst case printed only when not in DTX mode */
if ( dtx_mode == 0 )
{
tot_wc = 0L;
for ( i = 0; i < funcid[currCounter]; i++ )
tot_wc += wc[currCounter][i];
fprintf( stdout, " WorstWC=%.3f", ( (float) tot_wc ) * frameRate );
}
fprintf( stdout, " (%d frames)\n", nbframe[currCounter] );
#else
(void) dtx_mode;
#endif /* ifdef WMOPS */
}
void WMOPS_output_avg( Word16 dtx_mode, Word32 *tot_wm, Word32 *num_frames )
{
#ifdef WMOPS
Word16 i;
Word32 tot, tot_wc;
/* get operations since last reset (or init), but do not update the counters (except the glob_wc[] maximum)
so output CAN be called in each frame without problems. The frame counter is NOT updated! */
tot = WMOPS_frameStat();
*tot_wm = (Word32) ( total_wmops[currCounter] + ( (float) tot ) * frameRate );
*num_frames = nbframe[currCounter];
fprintf( stdout, "%10s:WMOPS=%.3f", objectName[currCounter] ? objectName[currCounter] : "", ( (float) tot ) * frameRate );
if ( nbframe[currCounter] != 0 )
{
fprintf( stdout, " Average=%.3f", *tot_wm / (float) nbframe[currCounter] );
}
fprintf( stdout, " WorstCase=%.3f", ( (float) glob_wc[currCounter] ) * frameRate );
/* Worst worst case printed only when not in DTX mode */
if ( dtx_mode == 0 )
{
tot_wc = 0L;
for ( i = 0; i < funcid[currCounter]; i++ )
tot_wc += wc[currCounter][i];
fprintf( stdout, " WorstWC=%.3f", ( (float) tot_wc ) * frameRate );
}
fprintf( stdout, " (%d frames)\n", nbframe[currCounter] );
#else
(void) dtx_mode;
(void) tot_wm;
(void) num_frames;
#endif /* ifdef WMOPS */
}
void generic_WMOPS_output( Word16 dtx_mode, char *test_file_name )
{
#ifdef WMOPS
int saved_value;
Word16 i;
Word32 tot, tot_wm, tot_wc, *ptr;
const Word32 *ptr2;
Word40 grand_total;
FILE *WMOPS_file;
saved_value = currCounter;
/* Count the grand_total WMOPS so that % ratio per function group can be displayed. */
grand_total = 0;
for ( currCounter = 0; currCounter <= maxCounter; currCounter++ )
{
tot = WMOPS_frameStat();
grand_total += tot;
}
if ( ( WMOPS_file = fopen( WMOPS_DATA_FILENAME, "a" ) ) != NULL )
{
printf( "opened file %s in order to print WMOPS for each function group.\n", WMOPS_DATA_FILENAME );
/* Print the file header line. */
fprintf( WMOPS_file, "Test file name\tFunction Name \tFrame\tNb Times Called\tWMOPS\t%% versus grand total" );
if ( nbframe[saved_value] != 0 )
fprintf( WMOPS_file, "\tAverage" );
fprintf( WMOPS_file, "\tWorstCase" );
/* Worst worst case printed only when not in DTX mode */
if ( dtx_mode == 0 )
fprintf( WMOPS_file, "\tWorstWC" );
fprintf( WMOPS_file, "\n" );
/* Print the WMOPS for each Function Group by scanning all the function groups with currCounter index. */
for ( currCounter = 0; currCounter <= maxCounter; currCounter++ )
{
fprintf( WMOPS_file, "%s", test_file_name );
fprintf( WMOPS_file, "\t%s", objectName[currCounter] ? objectName[currCounter] : "" );
fprintf( WMOPS_file, "\t%d", nbframe[currCounter] );
tot = WMOPS_frameStat();
tot_wm = (Word32) ( total_wmops[currCounter] + ( (float) tot ) * frameRate );
fprintf( WMOPS_file, "\t\t%ld", nbTimeObjectIsCalled[currCounter] );
fprintf( WMOPS_file, "\t%.6f", ( (float) tot ) * frameRate );
fprintf( WMOPS_file, "\t%.3f", ( (float) tot ) / grand_total * 100 );
if ( nbframe[currCounter] != 0 )
fprintf( WMOPS_file, "\t%.3f", tot_wm / (float) nbframe[currCounter] );
fprintf( WMOPS_file, "\t%.3f", ( (float) glob_wc[currCounter] ) * frameRate );
/* Worst worst case printed only when not in DTX mode */
if ( dtx_mode == 0 )
{
tot_wc = 0L;
for ( i = 0; i < funcid[currCounter]; i++ )
tot_wc += wc[currCounter][i];
fprintf( WMOPS_file, "\t%.3f", ( (float) tot_wc ) * frameRate );
}
fprintf( WMOPS_file, "\n" );
}
/* Print the file Grand Total line */
fprintf( WMOPS_file, "%s", test_file_name );
fprintf( WMOPS_file, "\tGrand Total" );
fprintf( WMOPS_file, "\t%d", nbframe[saved_value] );
fprintf( WMOPS_file, "\t\t%.6f", ( (float) grand_total ) * frameRate );
fprintf( WMOPS_file, "\t100.000" );
fprintf( WMOPS_file, "\n" );
fclose( WMOPS_file );
}
else
printf( "Can not open file %s for WMOPS editing\n", WMOPS_DATA_FILENAME );
if ( ( WMOPS_file = fopen( WMOPS_TOTAL_FILENAME, "a" ) ) != NULL )
{
printf( "opened file %s in order to print application's total WMOPS.\n", WMOPS_TOTAL_FILENAME );
fprintf( WMOPS_file, "%s", test_file_name );
fprintf( WMOPS_file, "\tframe=%d", nbframe[currCounter] );
fprintf( WMOPS_file, "\tWMOPS=%.6f", ( (float) grand_total ) * frameRate );
fprintf( WMOPS_file, "\n" );
fclose( WMOPS_file );
}
else
printf( "Can not open file %s for WMOPS editing.\n", WMOPS_TOTAL_FILENAME );
if ( ( WMOPS_file = fopen( CODE_PROFILE_FILENAME, "a" ) ) != NULL )
{
printf( "opened file %s in order to print basic operation distribution statistics.\n", CODE_PROFILE_FILENAME );
/* Print the file header line. */
fprintf( WMOPS_file, "Test file name\tBasic Operation Name\tframe\tWMOPS\t\t%% versus grand total\n" );
/* Print the WMOPS for each Basic Operation across all the defined */
/* Function Groups. */
for ( i = 0; i < (Word16) ( sizeof( op_weight ) / sizeof( Word32 ) ); i++ )
{
fprintf( WMOPS_file, "%-16s", test_file_name );
fprintf( WMOPS_file, "\t%s", BasicOperationList[i] );
fprintf( WMOPS_file, "\t%d", nbframe[0] );
tot = 0;
ptr = (Word32 *) &multiCounter[0] + i;
ptr2 = (const Word32 *) &op_weight + i;
for ( currCounter = 0; currCounter <= maxCounter; currCounter++ )
{
tot += ( ( *ptr ) * ( *ptr2 ) );
ptr += ( sizeof( op_weight ) / sizeof( Word32 ) );
}
fprintf( WMOPS_file, "\t%.6f", ( (float) tot ) * frameRate );
fprintf( WMOPS_file, "\t%.3f", ( (float) tot ) / grand_total * 100 );
fprintf( WMOPS_file, "\n" );
}
/* Print the file Grand Total line */
fprintf( WMOPS_file, "%s", test_file_name );
fprintf( WMOPS_file, "\tGrand Total" );
fprintf( WMOPS_file, "\t%d", nbframe[saved_value] );
fprintf( WMOPS_file, "\t%.6f", ( (float) grand_total ) * frameRate );
fprintf( WMOPS_file, "\t100.000" );
fprintf( WMOPS_file, "\n" );
fclose( WMOPS_file );
}
else
printf( "Can not open file %s for basic operations distribution statistic editing\n", CODE_PROFILE_FILENAME );
currCounter = saved_value;
#else
(void) dtx_mode;
(void) test_file_name;
#endif /* ifdef WMOPS */
}
/* FROM_EVS_DEV */
/* jdr 20120117: add FLC similar functions */
void BASOP_frame_update( void )
{
#ifdef WMOPS
int i, current;
#if MAX_CALLERS_SAVED_FRAMES
int k;
#endif
float total = 0.0f;
#ifdef DEBUG
{
static int sptr_target = -2;
if ( sptr_target == -2 )
{
sptr_target = sptr;
}
else
{
if ( sptr_target != sptr )
{
fprintf( stderr, "BASOP_sub_start/BASOP_sub_end imbalance detected!!!\n" );
sptr_target = sptr;
}
}
}
#endif
/* Get current counter */
current = readCounterId();
/* Update global operation counters */
for ( i = 1; i <= maxCounter; i++ )
{
int j;
for ( j = 0; j < (int) ( sizeof( BASIC_OP ) / sizeof( UWord32 ) ); j++ )
{
( (UWord32 *) &glob_multiCounter )[j] += ( (UWord32 *) &multiCounter[i] )[j];
}
}
#if MAX_CALLERS_SAVED_FRAMES
/* Reset all counters */
for ( i = 1; i <= maxCounter; i++ )
{
callers_frames[0][i] = 0.0f;
}
#endif
/* Reset all counters */
for ( i = 1; i <= maxCounter; i++ )
{
if ( current != i && funcid[i] > 0 )
{
setCounter( i );
glob_sum_curr[currCounter] += sum_curr[currCounter];
if ( glob_sum_curr[currCounter] > glob_sum_wc[currCounter] )
{
glob_sum_wc[currCounter] = glob_sum_curr[currCounter];
}
if ( glob_sum_curr[currCounter] < glob_sum_bc[currCounter] )
{
glob_sum_bc[currCounter] = glob_sum_curr[currCounter];
}
#if MAX_CALLERS_SAVED_FRAMES
/* Keep a Copy before it is Reset */
callers_frames[0][currCounter] = (float) Reset_WMOPS_counter();
total += callers_frames[0][currCounter];
#else
total += (float) Reset_WMOPS_counter();
#endif
}
}
#if MAX_CALLERS_SAVED_FRAMES
/* Keep Callers for this Worst Case Frame */
/* Select Slot to Use (Slot 0 is the Current) */
k = 0;
for ( i = k + 1; i < MAX_CALLERS_SAVED_FRAMES; i++ )
{
/* Is it the Min? */
if ( callers_totals[i] < callers_totals[k] )
{ /* Yes */
k = i;
}
}
/* Current Greater than the Min? */
if ( total > callers_totals[k] )
{
k += 1;
/* Save Info of Callers */
for ( i = 1; i <= maxCounter; i++ )
{
callers_frames[k][i] = callers_frames[0][i];
}
if ( i < MAXCOUNTERS )
callers_frames[k][i] = -1;
/* Save Total */
callers_totals[k - 1] = total;
/* Save Frame Number */
callers_frames_nos[k - 1] = nbframe[0];
}
#endif
if ( total < glob_bc[0] )
{
glob_bc[0] = (Word32) total;
}
if ( total > glob_wc[0] )
{
glob_wc[0] = (Word32) total;
}
/* Restore current counter */
setCounter( current );
nbframe[0]++;
#endif /* if WMOPS */
}
void printStack( char *text, char *Id )
{
#ifdef WMOPS
int i;
if ( !Id )
return;
if ( !strcmp( "*", Id ) || ( !strcmp( Id, objectName[currCounter] ) ) )
{
printf( "%s %s", text, objectName[currCounter] );
for ( i = sptr - 1; i > 0; i-- )
{
printf( " <- %s", objectName[stack[i]] );
}
printf( "\n" );
}
#else
printf( "%s %s\n", text, Id ? Id : "(no name)" );
#endif
}
#ifdef WMOPS
void BASOP_push_wmops( const char *label )
{
int new_flag, prev_counter;
int i, j;
/* Check if new counter label */
new_flag = 1;
for ( i = 1; i <= maxCounter; i++ )
{
if ( strcmp( objectName[i], label ) == 0 )
{
new_flag = 0;
break;
}
}
prev_counter = readCounterId();
/* Configure new record */
if ( new_flag )
{
i = (int) getCounterId( label );
setCounter( i );
Init_WMOPS_counter();
}
else
{
setCounter( i );
}
/* Push current context onto stack */
if ( currCounter >= 0 )
{
if ( sptr >= MAX_STACK )
{
fprintf( stderr, "\r push_wmops(): stack exceeded, try inreasing MAX_STACK\n" );
exit( -1 );
}
stack[sptr++] = prev_counter;
/* Reset accumulated WMOPS */
sum_stack[sptr] = 0;
/* update call tree */
for ( j = 0; j < MAXCOUNTERS; j++ )
{
if ( call_tree[i][j] == prev_counter )
{
break;
}
else if ( call_tree[i][j] == -1 )
{
call_tree[i][j] = (Word16) prev_counter;
break;
}
}
}
/*wmops[currCounter].start_selfcnt = ops_cnt;
wmops[currCounter].start_cnt = ops_cnt;
nbTimeObjectIsCalled[currCounter]++;*/
incrementNbTimeObjectIsCalled( currCounter );
sum_curr[currCounter] = 0;
#ifdef DEBUG_COUNTER
printf( "Entering: %s\n", readCounterIdName() );
#endif
}
#endif
Word32 BASOP_pop_wmops( void )
{
#ifdef WMOPS
Word32 ops_cnt;
#ifdef DEBUG_COUNTER
printf( "Exiting: %s\n", readCounterIdName() );
#endif
ops_cnt = fwc();
/* Get back previous context from stack */
if ( sptr > 0 )
{
int prevCounter;
sum_stack[sptr] += ops_cnt;
prevCounter = currCounter;
setCounter( stack[--sptr] );
sum_stack[sptr] += sum_stack[sptr + 1];
sum_curr[prevCounter] += sum_stack[sptr + 1];
}
else
{
/* current_record = -1; */
setCounter( 0 );
}
if ( sum_curr[currCounter] > sum_wc[currCounter] )
{
sum_wc[currCounter] = sum_curr[currCounter];
}
if ( sum_curr[currCounter] < sum_bc[currCounter] )
{
sum_bc[currCounter] = sum_curr[currCounter];
}
return ops_cnt;
#else /* if WMOPS */
return 0;
#endif /* if WMOPS */
}
Word32 BASOP_get_wops( void )
{
return BASOP_pop_wmops();
}
void WMOPS_destroy( void )
{
#ifdef WMOPS
int i;
/* release the memory allocated for the objectName array */
for ( i = 0; i < MAXCOUNTERS + 1; i++ )
{
if ( NULL != objectName[i] )
{
free( objectName[i] );
objectName[i] = NULL;
}
}
maxCounter = 0;
#endif
return;
}
void WMOPS_output_all( Word16 dtx_mode )
{
#ifdef WMOPS
float ops_cnt = 0.0f;
int i;
char *sfmts = "%-40s %8s %8s %7s %7s\n";
char *dfmts = "%-40s %8.2f %8.3f %7.3f %7.3f\n";
char *sfmt = "%-40s %8s %8s %7s %7s %7s %7s %7s\n";
char *dfmt = "%-40s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n";
/*fprintf (stderr, "\nInstruction Type Analysis (for worst case frame):\n\n");*/
fprintf( stderr, "\nInstruction Type Analysis (for worst case frame number %ld):\n\n", (long int) nbframe[0] ); /* added -- JPA */
for ( i = 0; i < (int) ( sizeof( BasicOperationList ) / sizeof( char * ) ); i++ )
{
if ( ( (UWord32 *) &glob_multiCounter )[i] > 0 )
fprintf( stderr, "\t%16s: %12d\n", BasicOperationList[i], ( (UWord32 *) &glob_multiCounter )[i] );
}
fprintf( stderr, "\n\nWeighted MOPS Analysis:\n" );
fprintf( stderr, "%74s %23s\n", "|------ SELF ------|", "|--- CUMULATIVE ---|" );
fprintf( stderr, sfmt, " routine", " calls", " min ", " max ", " avg ", " min ", " max ", " avg " );
fprintf( stderr, sfmt, " ------------------------", " ------", "------", "------", "------", "------", "------", "------" );
for ( i = 1; i <= maxCounter; i++ )
{
if ( nbcalls[i] > 0 )
{
fprintf( stderr, dfmt,
objectName[i],
( nbframe[i] == 0 ) ? 0 : (float) nbcalls[i] / (float) nbframe[0],
( glob_bc[i] == 0 ) ? 0 : frameRate * (float) glob_bc[i],
( glob_wc[i] == 0 ) ? 0 : frameRate * (float) glob_wc[i],
( nbframe[i] == 0 ) ? 0 : (float) total_wmops[i] / (float) nbframe[i],
frameRate * ( glob_sum_bc[i] ),
frameRate * ( glob_sum_wc[i] ),
( nbframe[i] == 0 ) ? 0 : (float) ( total_sum[i] / (float) nbframe[i] ) );
/* frameRate*(glob_bc[i]+wmops_children_bc[i]), */
/* frameRate*(glob_wc[i]+wmops_children_wc[i]), */
/* (nbframe[i] == 0) ? 0 : (float)((total_wmops[i] + total_wmops_children[i]) /(float)nbframe[i])); */
}
ops_cnt += total_wmops[i];
}
fprintf( stderr, sfmts, " -----------------", " ------", "------", "------", "------" );
if ( nbframe[i] > 0 )
{
fprintf( stderr, dfmts,
"total",
(double) nbframe[0],
frameRate * glob_bc[0],
frameRate * glob_wc[0],
( nbframe[0] == 0 ) ? 0 : ops_cnt / nbframe[0] );
}
#if 0
{
char *sfmtt = "%20s %4s %15s\n";
char *dfmtt = "%20s %4d ";
fprintf (stderr, "\nCall Tree:\n\n");
fprintf (stderr, sfmtt, " function", "num", "called by: ");
fprintf (stderr, sfmtt, "---------------", "---", "--------------");
for (i = 1; i <= maxCounter; i++)
{
int j;
fprintf (stderr, dfmtt, objectName[i], i);
for (j = 0; call_tree[i][j] != -1; j++)
{
if (j != 0)
{
fprintf (stderr, ", ");
}
fprintf (stderr, "%s", objectName[call_tree[i][j]]);
}
fprintf (stderr, "\n");
}
fprintf (stderr, sfmtt, "---------------", "---", "--------------");
fprintf (stderr, "\n\n");
}
#endif
#if 0
fprintf (stderr, "\n\n");
for (i=1; i<=maxCounter; i++)
{
setCounter(i);
WMOPS_output(dtx_mode);
}
#else
(void) dtx_mode;
#endif
#if MAX_CALLERS_SAVED_FRAMES
for ( i = 1; i <= MAX_CALLERS_SAVED_FRAMES; i++ )
{
int j, k, l, m;
const char *frame_rank[] = { "st", "nd", "rd", "th" };
float current;
k = 0;
for ( j = k + 1; j < MAX_CALLERS_SAVED_FRAMES; j++ )
{
/* Is it the Max? */
if ( callers_totals[j] > callers_totals[k] )
{ /* Yes */
k = j;
}
}
k += 1;
fprintf( stderr, "\nActive Callers Report for %i%s Worst Case Frame #: %i\n",
i, i <= 3 ? frame_rank[i - 1] : frame_rank[3],
callers_frames_nos[k - 1] );
/* Print up to 'MAX_CALLERS_PRINT' Callers */
current = 0.0f;
for ( l = 0; l < MAX_CALLERS_PRINT; l++ )
{
/* Find Highest Complexity */
m = 1;
for ( j = m + 1; j <= maxCounter; j++ )
{
if ( callers_frames[k][j] < 0 )
break;
if ( callers_frames[k][j] > callers_frames[k][m] )
m = j;
}
/* Done ? */
if ( callers_frames[k][m] == 0 )
break;
fprintf( stderr, " %-52s %10.3f\n", objectName[m], callers_frames[k][m] * frameRate );
/* Count it */
current += callers_frames[k][m];
/* Mark as Done */
callers_frames[k][m] = 0.0f;
}
/* Check if All Printed */
if ( current + 0.001f < callers_totals[k - 1] )
{
fprintf( stderr, " Only first %i Callers have been Printed!\n", MAX_CALLERS_PRINT );
fprintf( stderr, " %-52s %10.3f\n", "Total for non Printed", ( callers_totals[k - 1] - current ) * frameRate );
}
fprintf( stderr, " %-52s %10.3f\n", "Total", callers_totals[k - 1] * frameRate );
/* Mark as Done */
callers_totals[k - 1] = 0.0f;
}
#endif
WMOPS_destroy();
#else
UNUSED_PARAM( dtx_mode );
#endif /* if WMOPS */
}
void WMOPS_output_all_std( Word16 dtx_mode )
{
#ifdef WMOPS
float ops_cnt = 0.0f;
int i;
char *sfmts = "%-40s %8s %8s %7s %7s\n";
char *dfmts = "%-40s %8.2f %8.3f %7.3f %7.3f\n";
char *sfmt = "%-40s %8s %8s %7s %7s %7s %7s %7s\n";
char *dfmt = "%-40s %8.2f %8.3f %7.3f %7.3f %7.3f %7.3f %7.3f\n";
/*fprintf (stdout, "\nInstruction Type Analysis (for worst case frame):\n\n");*/
fprintf( stdout, "\nInstruction Type Analysis (for worst case frame number %ld):\n\n", (long int) nbframe[0] ); /* added -- JPA */
if ( nbframe[0] > 0 )
{
for ( i = 0; i < (int) ( sizeof( BasicOperationList ) / sizeof( char * ) ); i++ )
{
if ( ( (UWord32 *) &glob_multiCounter )[i] > 0 )
fprintf( stdout, "\t%16s: %12d\n", BasicOperationList[i], ( (UWord32 *) &glob_multiCounter )[i] );
}
}
fprintf( stdout, "\n\nWeighted MOPS Analysis:\n" );
fprintf( stdout, "%74s %23s\n", "|------ SELF ------|", "|--- CUMULATIVE ---|" );
fprintf( stdout, sfmt, " routine", "calls/fr", " min ", " max ", " avg ", " min ", " max ", " avg " );
fprintf( stdout, sfmt, " ------------------------", " ------", "------", "------", "------", "------", "------", "------" );
for ( i = 1; i <= maxCounter; i++ )
{
fprintf( stdout, dfmt,
objectName[i],
( nbframe[i] == 0 ) ? 0 : (float) nbcalls[i] / (float) nbframe[0],
( glob_bc[i] == MAX_32 ) ? 0 : frameRate * (float) glob_bc[i],
( glob_wc[i] == 0 ) ? 0 : frameRate * (float) glob_wc[i],
( nbframe[i] == 0 ) ? 0 : (float) total_wmops[i] / (float) nbframe[i],
frameRate * ( glob_sum_bc[i] ),
frameRate * ( glob_sum_wc[i] ),
( nbframe[i] == 0 ) ? 0 : (float) ( ( total_sum[i] ) / (float) nbframe[i] ) );
/* frameRate*(glob_bc[i]+wmops_children_bc[i]), */
/* frameRate*(glob_wc[i]+wmops_children_wc[i]), */
/* (nbframe[i] == 0) ? 0 : (float)((total_sum[i]) /(float)nbframe[i])); */
ops_cnt += total_wmops[i];
}
fprintf( stdout, sfmts, " -----------------", " ------", "------", "------", "------" );
if ( nbframe[0] > 0 )
{
fprintf( stdout, dfmts,
"total",
(double) nbframe[0],
frameRate * glob_bc[0],
frameRate * glob_wc[0],
( nbframe[0] == 0 ) ? 0 : ops_cnt / nbframe[0] );
}
#if 0
{
char *sfmtt = "%20s %4s %15s\n";
char *dfmtt = "%20s %4d ";
fprintf (stdout, "\nCall Tree:\n\n");
fprintf (stdout, sfmtt, " function", "num", "called by: ");
fprintf (stdout, sfmtt, "---------------", "---", "--------------");
for (i = 1; i <= maxCounter; i++)
{
int j;
fprintf (stdout, dfmtt, objectName[i], i);
for (j = 0; call_tree[i][j] != -1; j++)
{
if (j != 0)
{
fprintf (stdout, ", ");
}
fprintf (stdout, "%s", objectName[call_tree[i][j]]);
}
fprintf (stdout, "\n");
}
fprintf (stdout, sfmtt, "---------------", "---", "--------------");
fprintf (stdout, "\n\n");
}
#endif
#if 0
fprintf (stdout, "\n\n");
for (i=1; i<=maxCounter; i++)
{
setCounter(i);
WMOPS_output(dtx_mode);
}
#else
(void) dtx_mode;
#endif
WMOPS_destroy();
#else
UNUSED_PARAM( dtx_mode );
#endif /* if WMOPS */
}
void Reset_all_WMOPS_counter( void )
{
#ifdef WMOPS
int i;
int currCounterSave;
currCounterSave = currCounter;
for ( i = 2; i <= maxCounter; i++ )
{
setCounter( i );
Init_WMOPS_counter();
objectName[i] = 0;
}
currCounter = currCounterSave;
maxCounter = 1;
#endif /* if WMOPS */
}
/* Returns the total min/max/avg WMOPS values like printed in BASOP_end(). */
void BASOP_get_total_wmops( double *min, double *max, double *avg )
{
#ifdef WMOPS
if ( min != NULL )
*min = frameRate * glob_bc[0];
if ( max != NULL )
*max = frameRate * glob_wc[0];
if ( avg != NULL )
{
int i;
double ops_cnt = 0;
for ( i = 1; i <= maxCounter; i++ )
ops_cnt += total_wmops[i];
*avg = ( nbframe[0] == 0 ) ? 0 : ops_cnt / nbframe[0];
}
#else
UNUSED_PARAM( min );
UNUSED_PARAM( max );
UNUSED_PARAM( avg );
#endif /* if WMOPS */
}
/* end of file */
#undef WMC_TOOL_SKIP
/*
===========================================================================
File: COUNT.H v.2.3 - 30.Nov.2009
===========================================================================
ITU-T STL BASIC OPERATORS
PROTOTYPES & DEFINITION FOR COUNTING OPERATIONS
History
09.Aug.1999 V1.0.0 Input to UGST from ETSI AMR (count.h);
26.Jan.2000 V1.1.0 Added counter entries for G.723.1's
L_mls(), div_l(), i_mult() [from basop32.c]
05.Jul.2000 V1.2.0 Added counter entries for 32bit shiftless
operators L_mult0(), L_mac0(), L_msu0()
03 Nov 04 v2.0 Incorporation of new 32-bit / 40-bit / control
operators for the ITU-T Standard Tool Library as
described in Geneva, 20-30 January 2004 WP 3/16 Q10/16
TD 11 document and subsequent discussions on the
wp3audio@yahoogroups.com email reflector.
March 06 v2.1 Changed to improve portability.
Dec 06 v2.2 Changed to specify frame rate using setFrameRate()
Adding WMOPS_output_avg() for global average computation
L_mls() weight of 5.
div_l() weight of 32.
i_mult() weight of 3.
============================================================================
*/
/******************************************************************************
* Functions for counting operations.
*
* These functions make it possible to measure the wMOPS of a codec.
*
* All functions in this file, and in other *.h files, update a structure so
* that it will be possible to track how many calls to add(), sub(), L_mult()
* ... was made by the code and to estimate the wMOPS (and MIPS) for a certain
* part of the code.
*
* It is also possible to measure the wMOPS separatly for different parts
* of the codec.
*
* This is done by creating a counter group (getCounterId) for each part of
* the code that one wants a seperate measure for. Before a part of the code
* is executed a call to the "setCounter" function is needed to identify
* which counter group to use.
*
* Currently there is a limit of 255 different counter groups.
*
* In the end of this file, there is a piece of code illustrating how the
* functions can be used.
*
******************************************************************************/
#ifndef _COUNT_H
#define _COUNT_H "$Id$"
#include <assert.h>
#define MAXCOUNTERS ( 512 )
#define MAX_CALLERS_SAVED_FRAMES 5 /* # of Frame for which WMOPS Complexity Details will be saved, 0 = Disabled */
int getCounterId( const char *objectName );
/*
* Create a counter group, the "objectname" will be used when printing
* statistics for this counter group.
*
* Returns 0 if no more counter groups are available.
*/
int readCounterId( void );
/*
* Returns the current CounterId.
*/
void setCounter( int counterId );
/*
* Defines which counter group to use, default is zero.
*/
char *readCounterIdName( void );
/*
* Returns the current CounterId name.
*/
void printStack( char *text, char *Id );
/*
* print stack
* text: Any text to print initially
* Id: NULL, if no prints are wanted
* "*", if all prints are wanted (default)
* "pitch_ol" or any other function name
*/
void incrementNbTimeObjectIsCalled( int counterId );
/*
* This function enables to increment by 1 a counter
* tracking the number of times the application enters a groups of functions.
* If the counterId is not refering to a defined function counter group, then it is
* the default function group (0) which is impacted.
*
*/
void ClearNbTimeObjectsAreCalled( void );
/*
* This function enables to clear to 0 all the counters enabling to
* track the number of times the application enters any groups of functions.
*/
void Init_WMOPS_counter( void );
/*
* Initiates the current counter group.
*/
Word32 Reset_WMOPS_counter( void );
/*
* Resets the current counter group.
*/
void WMOPS_output( Word16 notPrintWorstWorstCase );
/*
* Prints the statistics to the screen, if the argument is non zero
* the statistics for worst worst case will not be printed. This is typically
* done for dtx frames.
*
*/
void WMOPS_output_avg( Word16 dtx_mode, Word32 *tot_wm, Word32 *num_frames );
/*
* same as WMOPS_output + returns the total wmops counter and the number of frames
* to support the computation of global average.
*
*/
Word32 fwc( void );
/*
* worst worst case counter.
*
* This function calculates the worst possible case that can be reached.
*
* This is done by calling this function for each subpart of the calculations
* for a frame. This function then stores the maximum wMOPS for each part.
*
* The WMOPS_output function add together all parts and presents the sum.
*/
void setFrameRate( int samplingFreq, int frameLength );
/*
* This function can overwrite the value of the frameRate variable that is
* initialized by the FRAME_RATE constant.
*/
#define WMOPS_DATA_FILENAME "wmops_data.txt"
/*
* WMOPS_DATA_FILENAME is the macro defining the name of the file
* where the Weighted Million of Operations per Second (wMOPS)
* are appended, function group by function group.
*/
#define CODE_PROFILE_FILENAME "code_profile.txt"
/*
* CODE_PROFILE_FILENAME is the macro defining the name of the file
* where the Weighted Million of Operations per Second (WMOPS)
* are appended, basic operation by basic operation.
*/
#define WMOPS_TOTAL_FILENAME "wmops_total.txt"
/*
* WMOPS_TOTAL_FILENAME is the macro defining the name of the file
* where the Weighted Million of Operations per Second (WMOPS)
* are printed, globally for the application.
*/
#define FRAME_RATE ( 0.0001F ) /* in this version frame_rate can be overwriten online by the new setFrameRate function */
/* FRAME_RATE of 0.000025 is corresponding to 40ms frame.*/
/* FRAME_RATE of 0.00005 is corresponding to 20ms frame.*/
/* FRAME_RATE of 0.0001 is corresponding to 10ms frame.*/
/*
* FRAME_RATE is the macro defining the calling rate of the
* application to benchmark.
*/
/* Global counter variable for calculation of complexity weight */
typedef struct
{
UWord32 add; /* Complexity Weight of 1 */
UWord32 sub; /* Complexity Weight of 1 */
UWord32 abs_s; /* Complexity Weight of 1 */
UWord32 shl; /* Complexity Weight of 1 */
UWord32 shr; /* Complexity Weight of 1 */
UWord32 extract_h; /* Complexity Weight of 1 */
UWord32 extract_l; /* Complexity Weight of 1 */
UWord32 mult; /* Complexity Weight of 1 */
UWord32 L_mult; /* Complexity Weight of 1 */
UWord32 negate; /* Complexity Weight of 1 */
UWord32 round; /* Complexity Weight of 1 */
UWord32 L_mac; /* Complexity Weight of 1 */
UWord32 L_msu; /* Complexity Weight of 1 */
UWord32 L_macNs; /* Complexity Weight of 1 */
UWord32 L_msuNs; /* Complexity Weight of 1 */
UWord32 L_add; /* Complexity Weight of 1 */
UWord32 L_sub; /* Complexity Weight of 1 */
UWord32 L_add_c; /* Complexity Weight of 2 */
UWord32 L_sub_c; /* Complexity Weight of 2 */
UWord32 L_negate; /* Complexity Weight of 1 */
UWord32 L_shl; /* Complexity Weight of 1 */
UWord32 L_shr; /* Complexity Weight of 1 */
UWord32 mult_r; /* Complexity Weight of 1 */
UWord32 shr_r; /* Complexity Weight of 3 */
UWord32 mac_r; /* Complexity Weight of 1 */
UWord32 msu_r; /* Complexity Weight of 1 */
UWord32 L_deposit_h; /* Complexity Weight of 1 */
UWord32 L_deposit_l; /* Complexity Weight of 1 */
UWord32 L_shr_r; /* Complexity Weight of 3 */
UWord32 L_abs; /* Complexity Weight of 1 */
UWord32 L_sat; /* Complexity Weight of 4 */
UWord32 norm_s; /* Complexity Weight of 1 */
UWord32 div_s; /* Complexity Weight of 18 */
UWord32 norm_l; /* Complexity Weight of 1 */
UWord32 move16; /* Complexity Weight of 1 */
UWord32 move32; /* Complexity Weight of 2 */
UWord32 Logic16; /* Complexity Weight of 1 */
UWord32 Logic32; /* Complexity Weight of 2 */
UWord32 Test; /* Complexity Weight of 2 */
UWord32 s_max; /* Complexity Weight of 1 */
UWord32 s_min; /* Complexity Weight of 1 */
UWord32 L_max; /* Complexity Weight of 1 */
UWord32 L_min; /* Complexity Weight of 1 */
UWord32 L40_max; /* Complexity Weight of 1 */
UWord32 L40_min; /* Complexity Weight of 1 */
UWord32 shl_r; /* Complexity Weight of 2 */
UWord32 L_shl_r; /* Complexity Weight of 2 */
UWord32 L40_shr_r; /* Complexity Weight of 2 */
UWord32 L40_shl_r; /* Complexity Weight of 2 */
UWord32 norm_L40; /* Complexity Weight of 1 */
UWord32 L40_shl; /* Complexity Weight of 1 */
UWord32 L40_shr; /* Complexity Weight of 1 */
UWord32 L40_negate; /* Complexity Weight of 1 */
UWord32 L40_add; /* Complexity Weight of 1 */
UWord32 L40_sub; /* Complexity Weight of 1 */
UWord32 L40_abs; /* Complexity Weight of 1 */
UWord32 L40_mult; /* Complexity Weight of 1 */
UWord32 L40_mac; /* Complexity Weight of 1 */
UWord32 mac_r40; /* Complexity Weight of 2 */
UWord32 L40_msu; /* Complexity Weight of 1 */
UWord32 msu_r40; /* Complexity Weight of 2 */
UWord32 Mpy_32_16_ss; /* Complexity Weight of 2 */
UWord32 Mpy_32_32_ss; /* Complexity Weight of 2 */
UWord32 L_mult0; /* Complexity Weight of 1 */
UWord32 L_mac0; /* Complexity Weight of 1 */
UWord32 L_msu0; /* Complexity Weight of 1 */
UWord32 lshl; /* Complexity Weight of 1 */
UWord32 lshr; /* Complexity Weight of 1 */
UWord32 L_lshl; /* Complexity Weight of 1 */
UWord32 L_lshr; /* Complexity Weight of 1 */
UWord32 L40_lshl; /* Complexity Weight of 1 */
UWord32 L40_lshr; /* Complexity Weight of 1 */
UWord32 s_and; /* Complexity Weight of 1 */
UWord32 s_or; /* Complexity Weight of 1 */
UWord32 s_xor; /* Complexity Weight of 1 */
UWord32 L_and; /* Complexity Weight of 1 */
UWord32 L_or; /* Complexity Weight of 1 */
UWord32 L_xor; /* Complexity Weight of 1 */
UWord32 rotl; /* Complexity Weight of 3 */
UWord32 rotr; /* Complexity Weight of 3 */
UWord32 L_rotl; /* Complexity Weight of 3 */
UWord32 L_rotr; /* Complexity Weight of 3 */
UWord32 L40_set; /* Complexity Weight of 1 */
UWord32 L40_deposit_h; /* Complexity Weight of 1 */
UWord32 L40_deposit_l; /* Complexity Weight of 1 */
UWord32 L40_deposit32; /* Complexity Weight of 1 */
UWord32 Extract40_H; /* Complexity Weight of 1 */
UWord32 Extract40_L; /* Complexity Weight of 1 */
UWord32 L_Extract40; /* Complexity Weight of 1 */
UWord32 L40_round; /* Complexity Weight of 1 */
UWord32 L_saturate40; /* Complexity Weight of 1 */
UWord32 round40; /* Complexity Weight of 1 */
UWord32 If; /* Complexity Weight of 3 */
UWord32 Goto; /* Complexity Weight of 2 */
UWord32 Break; /* Complexity Weight of 2 */
UWord32 Switch; /* Complexity Weight of 6 */
UWord32 For; /* Complexity Weight of 3 */
UWord32 While; /* Complexity Weight of 3 */
UWord32 Continue; /* Complexity Weight of 2 */
UWord32 L_mls; /* Complexity Weight of 1 */
UWord32 div_l; /* Complexity Weight of 32 */
UWord32 i_mult; /* Complexity Weight of 1 */
/* New complex basic operators */
#ifdef COMPLEX_OPERATOR
UWord32 CL_shr; /* Complexity Weight of 1 */
UWord32 CL_shl; /* Complexity Weight of 1 */
UWord32 CL_add; /* Complexity Weight of 1 */
UWord32 CL_sub; /* Complexity Weight of 1 */
UWord32 CL_scale; /* Complexity Weight of 1 */
UWord32 CL_dscale; /* Complexity Weight of 1 */
UWord32 CL_msu_j; /* Complexity Weight of 1 */
UWord32 CL_mac_j; /* Complexity Weight of 1 */
UWord32 CL_move; /* Complexity Weight of 1 */
UWord32 CL_Extract_real; /* Complexity Weight of 1 */
UWord32 CL_Extract_imag; /* Complexity Weight of 1 */
UWord32 CL_form; /* Complexity Weight of 1 */
UWord32 CL_multr_32x16; /* Complexity Weight of 2 */
UWord32 CL_negate; /* Complexity Weight of 1 */
UWord32 CL_conjugate; /* Complexity Weight of 1 */
UWord32 CL_mul_j; /* Complexity Weight of 1 */
UWord32 CL_swap_real_imag; /* Complexity Weight of 1 */
UWord32 C_add; /* Complexity Weight of 1 */
UWord32 C_sub; /* Complexity Weight of 1 */
UWord32 C_mul_j; /* Complexity Weight of 1 */
UWord32 C_multr; /* Complexity Weight of 2 */
UWord32 C_form; /* Complexity Weight of 1 */
UWord32 C_scale; /* Complexity Weight of 1 */
UWord32 CL_round32_16; /* Complexity Weight of 1 */
UWord32 CL_scale_32; /* Complexity Weight of 1 */
UWord32 CL_dscale_32; /* Complexity Weight of 1 */
UWord32 CL_multr_32x32; /* Complexity Weight of 2 */
UWord32 C_mac_r; /* Complexity Weight of 2 */
UWord32 C_msu_r; /* Complexity Weight of 2 */
UWord32 C_Extract_real; /* Complexity Weight of 1 */
UWord32 C_Extract_imag; /* Complexity Weight of 1 */
UWord32 C_negate; /* Complexity Weight of 1 */
UWord32 C_conjugate; /* Complexity Weight of 1 */
UWord32 C_shr; /* Complexity Weight of 1 */
UWord32 C_shl; /* Complexity Weight of 1 */
#endif /* #ifdef COMPLEX_OPERATOR */
/* New 64 bit basops */
#ifdef ENH_64_BIT_OPERATOR
UWord32 move64; /* Complexity Weight of 1 */
UWord32 W_add_nosat; /* Complexity Weight of 1 */
UWord32 W_sub_nosat; /* Complexity Weight of 1 */
UWord32 W_shl; /* Complexity Weight of 1 */
UWord32 W_shr; /* Complexity Weight of 1 */
UWord32 W_shl_nosat; /* Complexity Weight of 1 */
UWord32 W_shr_nosat; /* Complexity Weight of 1 */
UWord32 W_mac_32_16; /* Complexity Weight of 1 */
UWord32 W_msu_32_16; /* Complexity Weight of 1 */
UWord32 W_mult_32_16; /* Complexity Weight of 1 */
UWord32 W_mult0_16_16; /* Complexity Weight of 1 */
UWord32 W_mac0_16_16; /* Complexity Weight of 1 */
UWord32 W_msu0_16_16; /* Complexity Weight of 1 */
UWord32 W_mult_16_16; /* Complexity Weight of 1 */
UWord32 W_mac_16_16; /* Complexity Weight of 1 */
UWord32 W_msu_16_16; /* Complexity Weight of 1 */
UWord32 W_shl_sat_l; /* Complexity Weight of 1 */
UWord32 W_sat_l; /* Complexity Weight of 1 */
UWord32 W_sat_m; /* Complexity Weight of 1 */
UWord32 W_deposit32_l; /* Complexity Weight of 1 */
UWord32 W_deposit32_h; /* Complexity Weight of 1 */
UWord32 W_extract_l; /* Complexity Weight of 1 */
UWord32 W_extract_h; /* Complexity Weight of 1 */
UWord32 W_round48_L; /* Complexity Weight of 1 */
UWord32 W_round32_s; /* Complexity Weight of 1 */
UWord32 W_norm; /* Complexity Weight of 1 */
UWord32 W_add; /* Complexity Weight of 1 */
UWord32 W_sub; /* Complexity Weight of 1 */
UWord32 W_neg; /* Complexity Weight of 1 */
UWord32 W_abs; /* Complexity Weight of 1 */
UWord32 W_mult_32_32; /* Complexity Weight of 1 */
UWord32 W_mult0_32_32; /* Complexity Weight of 1 */
UWord32 W_lshl; /* Complexity Weight of 1 */
UWord32 W_lshr; /* Complexity Weight of 1 */
UWord32 W_round64_L; /* Complexity Weight of 1 */
#endif /* #ifdef ENH_64_BIT_OPERATOR */
#ifdef ENH_32_BIT_OPERATOR
UWord32 Mpy_32_16_1; /* Complexity Weight of 1 */
UWord32 Mpy_32_16_r; /* Complexity Weight of 1 */
UWord32 Mpy_32_32; /* Complexity Weight of 1 */
UWord32 Mpy_32_32_r; /* Complexity Weight of 1 */
UWord32 Madd_32_16; /* Complexity Weight of 1 */
UWord32 Madd_32_16_r; /* Complexity Weight of 1 */
UWord32 Msub_32_16; /* Complexity Weight of 1 */
UWord32 Msub_32_16_r; /* Complexity Weight of 1 */
UWord32 Madd_32_32; /* Complexity Weight of 1 */
UWord32 Madd_32_32_r; /* Complexity Weight of 1 */
UWord32 Msub_32_32; /* Complexity Weight of 1 */
UWord32 Msub_32_32_r; /* Complexity Weight of 1 */
#endif /* #ifdef ENH_32_BIT_OPERATOR */
#ifdef ENH_U_32_BIT_OPERATOR
UWord32 UL_addNs; /* Complexity Weight of 1 */
UWord32 UL_subNs; /* Complexity Weight of 1 */
UWord32 UL_Mpy_32_32; /* Complexity Weight of 1 */
UWord32 Mpy_32_32_uu; /* Complexity Weight of 2 */
UWord32 Mpy_32_16_uu; /* Complexity Weight of 2 */
UWord32 norm_ul_float; /* Complexity Weight of 1 */
UWord32 UL_deposit_l; /* Complexity Weight of 1 */
#endif /* #ifdef ENH_U_32_BIT_OPERATOR */
#ifdef CONTROL_CODE_OPS
UWord32 LT_16; /* Complexity Weight of 1 */
UWord32 GT_16; /* Complexity Weight of 1 */
UWord32 LE_16; /* Complexity Weight of 1 */
UWord32 GE_16; /* Complexity Weight of 1 */
UWord32 EQ_16; /* Complexity Weight of 1 */
UWord32 NE_16; /* Complexity Weight of 1 */
UWord32 LT_32; /* Complexity Weight of 1 */
UWord32 GT_32; /* Complexity Weight of 1 */
UWord32 LE_32; /* Complexity Weight of 1 */
UWord32 GE_32; /* Complexity Weight of 1 */
UWord32 EQ_32; /* Complexity Weight of 1 */
UWord32 NE_32; /* Complexity Weight of 1 */
UWord32 LT_64; /* Complexity Weight of 1 */
UWord32 GT_64; /* Complexity Weight of 1 */
UWord32 LE_64; /* Complexity Weight of 1 */
UWord32 GE_64; /* Complexity Weight of 1 */
UWord32 EQ_64; /* Complexity Weight of 1 */
UWord32 NE_64; /* Complexity Weight of 1 */
#endif /* #ifdef CONTROL_CODE_OPS */
} BASIC_OP;
Word32 TotalWeightedOperation( void );
Word32 DeltaWeightedOperation( void );
void generic_WMOPS_output( Word16 notPrintWorstWorstCase, char *test_file_name );
/*
* This function enable to append :
* - to WMOPS_DATA_FILENAME file, the WMOPS information related
* to the execution of the application, function group by function
* group.
* - to CODE_PROFILE_FILENAME file, the WMOPS information related
* to the execution of the application, basic operation by basic
* operation.
* - to WMOPS_TOTAL_FILENAME file, the total WMOPS information related
* to the execution of the application.
*
* Note that :
* if the files exists, the data will be written at the end of file.
*
* test_file_name : Is a character string referencing each calls to
* generic_WMOPS_output(). Usually, it is the name of a test
* sequence file.
*
* notPrintWorstWorstCase : Same usage as in WMOPS_output().
*/
void WMOPS_output_all( Word16 dtx_mode );
void WMOPS_output_all_std( Word16 dtx_mode );
/*
* free all allocated counter memory
*/
void WMOPS_destroy( void );
/* jdr 20120117: add FLC similar functions */
/* mul 20130729: set BASOP_COUNT_SUBROUTINES to count on a per-BASOP_sub_start()/BASOP_sub_end() base;
otherwise, count only between BASOP_push_wmops(), BASOP_push_wmops() */
#define BASOP_COUNT_SUBROUTINES
void BASOP_push_wmops( const char *label );
Word32 BASOP_pop_wmops( void );
#define BASOP_init \
{ \
setFrameRate( 32000, 640 ); \
Init_WMOPS_counter(); /* 20ms frames */ \
}
#define BASOP_end \
{ \
WMOPS_output_all_std( 0 ); \
}
/*#define BASOP_end { WMOPS_output_all(0); }*/
#define BASOP_end_noprint \
{ \
WMOPS_destroy(); \
}
#ifdef BASOP_COUNT_SUBROUTINES
#define BASOP_sub_start( label ) \
{ \
BASOP_push_wmops( label ); \
}
#define BASOP_sub_end() \
{ \
BASOP_pop_wmops(); \
}
#else
#define BASOP_sub_start( label )
#define BASOP_sub_end()
#endif
void BASOP_frame_update( void );
void Reset_all_WMOPS_counter( void );
Word32 BASOP_get_wops( void );
/*! Returns the total min/max/avg WMOPS values like printed in BASOP_end(). */
void BASOP_get_total_wmops( double *min, double *max, double *avg );
#define SUB_WMOPS_INIT( label ) BASOP_sub_start( label )
#define END_SUB_WMOPS BASOP_sub_end()
#endif /* _COUNT_H */
/* end of file */
......@@ -58,12 +58,6 @@
#define WMC_TOOL_SKIP
#ifdef WMOPS
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
#endif /* ifdef WMOPS */
/*****************************************************************************
*
* Constants and Globals
......
......@@ -35,14 +35,6 @@
#include "stl.h"
#ifdef WMOPS
#include "count.h"
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
#endif /* ifdef WMOPS */
/*****************************************************************************
*
* Prototypes for enhanced 16/32 bit arithmetic operators
......
......@@ -21,15 +21,10 @@
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "enh32.h"
#include "stl.h"
#define WMC_TOOL_SKIP
#ifdef WMOPS
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
#endif /* if WMOPS */
#ifdef ENH_32_BIT_OPERATOR
/*****************************************************************************
*
......
......@@ -16,16 +16,10 @@
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "enh64.h"
#include "stl.h"
#define WMC_TOOL_SKIP
#ifdef WMOPS
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
#endif /* if WMOPS */
/*****************************************************************************
*
* Local Functions
......
......@@ -25,16 +25,10 @@
#include <stdio.h>
#include <stdlib.h>
#include "stl.h"
#include "enhUL32.h"
#include "stl.h"
#define WMC_TOOL_SKIP
#ifdef WMOPS
extern BASIC_OP multiCounter[MAXCOUNTERS];
extern int currCounter;
#endif /* if WMOPS */
/*****************************************************************************
*
* Constants and Globals
......
......@@ -24,12 +24,6 @@
#define UWord64 unsigned long long /* for local use inside UL_Mpy_32_* */
#endif
#ifdef WMOPS
#include "count.h"
extern BASIC_OP multiCounter[MAXCOUNTERS]; /* existing signed counters are reused for unsigedn operators */
extern int currCounter;
#endif /* if WMOPS */
/*****************************************************************************
*
* Prototypes for enhanced unsigned 32 bit arithmetic operators
......
/******************************************************************************************************
(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository. All Rights Reserved.
This software is protected by copyright law and by international treaties.
The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository retain full ownership rights in their respective contributions in
the software. This notice grants no license of any kind, including but not limited to patent
license, nor is any license granted by implication, estoppel or otherwise.
Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
contributions.
This software is provided "AS IS", without any express or implied warranties. The software is in the
development stage. It is intended exclusively for experts who have experience with such software and
solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
and fitness for a particular purpose are hereby disclaimed and excluded.
Any dispute, controversy or claim arising under or in relation to providing this software shall be
submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
the United Nations Convention on Contracts on the International Sales of Goods.
*******************************************************************************************************/
/*====================================================================================
EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
====================================================================================*/
#include <stdint.h>
#include "options.h"
#include "cnst.h"
#include "prot.h"
#include "wmc_auto.h"
/*-------------------------------------------------------------------*
* est_tilt()
*
* Estimate spectral tilt based on the relative E of adaptive
* and innovative excitations
*-------------------------------------------------------------------*/
/*! r: tilt of the code */
float est_tilt(
const float *adpt_exc, /* i : adaptive excitation vector */
const float gain_pit, /* i : adaptive gain */
const float *fixe_exc, /* i : algebraic exctitation vector */
const float gain_code, /* i : algebraic code gain */
float *voice_fac, /* o : voicing factor */
const int16_t L_subfr, /* i : subframe size */
const int16_t flag_tilt /* i : flag for special tilt */
)
{
float ener, tmp, tilt_code;
ener = dotp( adpt_exc, adpt_exc, L_subfr );
ener *= gain_pit * gain_pit; /* energy of pitch excitation */
tmp = dotp( fixe_exc, fixe_exc, L_subfr );
tmp *= gain_code * gain_code; /* energy of innovative code excitation */
/* find voice factor (1=voiced, -1=unvoiced) */
*voice_fac = (float) ( ( ener - tmp ) / ( ener + tmp + 0.01f ) );
/* find tilt of code for next subframe */
if ( flag_tilt == 0 )
{
/*Between 0 (=unvoiced) and 0.5 (=voiced)*/
tilt_code = (float) ( 0.25f * ( 1.0f + *voice_fac ) );
}
else if ( flag_tilt == 1 )
{
/*Between 0.25 (=unvoiced) and 0.5 (=voiced)*/
tilt_code = (float) ( 0.25f + ( *voice_fac + 1.0f ) * 0.125f );
}
else
{
/*Between 0.28 (=unvoiced) and 0.56 (=voiced)*/
tilt_code = (float) ( 0.28f + ( *voice_fac + 1.0f ) * 0.14f );
}
return tilt_code;
}
......@@ -7262,15 +7262,29 @@ Word16 L_norm_arr( Word32 *arr, Word16 size )
Word16 q = 31;
move16();
FOR( Word16 i = 0; i < size; i++ )
#ifndef FIX_1103_OPT_L_NORM_ARR
IF( arr[i] != 0 )
{
q = s_min( q, norm_l( arr[i] ) );
}
#else
{
Word16 q_tst;
q_tst = norm_l( arr[i] );
if ( arr[i] != 0 )
{
q = s_min( q, q_tst );
}
}
#endif
return q;
}
Word16 get_min_scalefactor( Word32 x, Word32 y )
{
#ifndef FIX_1104_OPT_GETMINSCALEFAC
Word16 scf = Q31;
move16();
test();
......@@ -7287,8 +7301,34 @@ Word16 get_min_scalefactor( Word32 x, Word32 y )
scf = s_min( scf, norm_l( y ) );
}
return scf;
#else
Word16 scf_y;
Word16 scf = Q31;
move16();
test();
if ( x == 0 && y == 0 )
{
scf = 0;
move16();
}
if ( x != 0 )
{
scf = norm_l( x );
}
scf_y = norm_l( y );
if ( y != 0 )
{
scf = s_min( scf_y, scf );
}
return scf;
#endif
}
Flag is_zero_arr( Word32 *arr, Word16 size )
{
FOR( Word16 i = 0; i < size; i++ )
......@@ -7299,3 +7339,14 @@ Flag is_zero_arr( Word32 *arr, Word16 size )
return 1;
}
Flag is_zero_arr16( Word16 *arr, Word16 size )
{
FOR( Word16 i = 0; i < size; i++ )
IF( arr[i] != 0 )
{
return 0;
}
return 1;
}
/******************************************************************************************************
(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository. All Rights Reserved.
This software is protected by copyright law and by international treaties.
The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
contributors to this repository retain full ownership rights in their respective contributions in
the software. This notice grants no license of any kind, including but not limited to patent
license, nor is any license granted by implication, estoppel or otherwise.
Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
contributions.
This software is provided "AS IS", without any express or implied warranties. The software is in the
development stage. It is intended exclusively for experts who have experience with such software and
solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
and fitness for a particular purpose are hereby disclaimed and excluded.
Any dispute, controversy or claim arising under or in relation to providing this software shall be
submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
the United Nations Convention on Contracts on the International Sales of Goods.
*******************************************************************************************************/
/*====================================================================================
EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
====================================================================================*/
#include <stdint.h>
#include "options.h"
#include "rom_com.h"
#include "prot.h"
#include <assert.h>
#include "wmc_auto.h"
#ifndef IVAS_FLOAT_FIXED
/*--------------------------------------------------------------------------
* subband_gain_bits()
*
* HQ core encoder
*--------------------------------------------------------------------------*/
static void subband_gain_bits(
const int16_t *Rk, /* i : bit allocation per band (Q3)*/
const int16_t N, /* i : number of bands */
int16_t *bits, /* o : gain bits per band */
const int16_t *sfmsize /* i : Size of bands */
)
{
int16_t i, b, tot;
int16_t bps;
tot = 0;
for ( i = 0; i < N; i++ )
{
bps = ( Rk[i] * fg_inv_tbl_fx[sfmsize[i] >> 3] ) >> 18;
if ( ( ( sfmsize[i] * ( bps + 1 ) ) << 3 ) - Rk[i] == 0 )
{ /* correct approx. division result, to obtain exact integer division output */
bps++;
}
bps = min( 7, bps );
b = fine_gain_bits[bps];
bits[i] = b;
tot += b;
}
if ( tot == 0 )
{
/* If no gain bits were assigned, use one bit anyway for potential PVQ overage */
bits[0] = 1;
}
return;
}
/*--------------------------------------------------------------------------*
* assign_gain_bits()
*
* Assign gain adjustment bits and update bit budget
*--------------------------------------------------------------------------*/
/*! r: Number of assigned gain bits */
int16_t assign_gain_bits(
const int16_t core, /* i : HQ core */
const int16_t BANDS, /* i : Number of bands */
const int16_t *band_width, /* i : Sub band bandwidth */
int16_t *Rk, /* i/o: Bit allocation/Adjusted bit alloc. (Q3) */
int16_t *gain_bits_array, /* o : Assigned gain bits */
int16_t *Rcalc /* o : Bit budget for shape quantizer (Q3) */
)
{
int16_t gain_bits_tot;
int16_t i;
/* Allocate gain bits for every subband used, based on bitrate and bandwidth */
if ( core == HQ_CORE )
{
subband_gain_bits( Rk, BANDS, gain_bits_array, band_width );
}
else
{
set_s( gain_bits_array, 0, BANDS );
}
/* Re-adjust bit budget for gain quantization */
gain_bits_tot = 0;
*Rcalc = 0;
for ( i = 0; i < BANDS; i++ )
{
if ( Rk[i] > 0 )
{
Rk[i] -= gain_bits_array[i] * 8;
gain_bits_tot += gain_bits_array[i];
*Rcalc += Rk[i];
}
}
return gain_bits_tot;
}
#endif