OpenRTX/rtos/uC-CPU/cpu_core.c

2255 wiersze
110 KiB
C

/*
*********************************************************************************************************
* uC/CPU
* CPU CONFIGURATION & PORT LAYER
*
* Copyright 2004-2020 Silicon Laboratories Inc. www.silabs.com
*
* SPDX-License-Identifier: APACHE-2.0
*
* This software is subject to an open source license and is distributed by
* Silicon Laboratories Inc. pursuant to the terms of the Apache License,
* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
*
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*
* CORE CPU MODULE
*
* Filename : cpu_core.c
* Version : v1.32.00
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#define MICRIUM_SOURCE
#define CPU_CORE_MODULE
#include "cpu_core.h"
#if (CPU_CFG_CACHE_MGMT_EN == DEF_ENABLED)
#include "cpu_cache.h"
#endif
/*
*********************************************************************************************************
* LOCAL DEFINES
*********************************************************************************************************
*/
/* Pop cnt algorithm csts. */
#define CRC_UTIL_POPCNT_MASK01010101_32 0x55555555u
#define CRC_UTIL_POPCNT_MASK00110011_32 0x33333333u
#define CRC_UTIL_POPCNT_MASK00001111_32 0x0F0F0F0Fu
#define CRC_UTIL_POPCNT_POWERSOF256_32 0x01010101u
/*
*********************************************************************************************************
* LOCAL CONSTANTS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL DATA TYPES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL TABLES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* CPU COUNT LEAD ZEROs LOOKUP TABLE
*
* Note(s) : (1) Index into bit pattern table determines the number of leading zeros in an 8-bit value :
*
* b07 b06 b05 b04 b03 b02 b01 b00 # Leading Zeros
* --- --- --- --- --- --- --- --- ---------------
* 1 x x x x x x x 0
* 0 1 x x x x x x 1
* 0 0 1 x x x x x 2
* 0 0 0 1 x x x x 3
* 0 0 0 0 1 x x x 4
* 0 0 0 0 0 1 x x 5
* 0 0 0 0 0 0 1 x 6
* 0 0 0 0 0 0 0 1 7
* 0 0 0 0 0 0 0 0 8
*********************************************************************************************************
*/
#if (!(defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) || \
(CPU_CFG_DATA_SIZE_MAX > CPU_CFG_DATA_SIZE))
static const CPU_INT08U CPU_CntLeadZerosTbl[256] = { /* Data vals : */
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
8u, 7u, 6u, 6u, 5u, 5u, 5u, 5u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, 4u, /* 0x00 to 0x0F */
3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, 3u, /* 0x10 to 0x1F */
2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, /* 0x20 to 0x2F */
2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, 2u, /* 0x30 to 0x3F */
1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, /* 0x40 to 0x4F */
1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, /* 0x50 to 0x5F */
1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, /* 0x60 to 0x6F */
1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, /* 0x70 to 0x7F */
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0x80 to 0x8F */
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0x90 to 0x9F */
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xA0 to 0xAF */
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xB0 to 0xBF */
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xC0 to 0xCF */
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xD0 to 0xDF */
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, /* 0xE0 to 0xEF */
0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u /* 0xF0 to 0xFF */
};
#endif
/*
*********************************************************************************************************
* LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/
CPU_INT32U const CPU_EndiannessTest = 0x12345678LU; /* Variable to test CPU endianness. */
/*
*********************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/
#if (CPU_CFG_NAME_EN == DEF_ENABLED) /* ---------------- CPU NAME FNCTS ---------------- */
static void CPU_NameInit (void);
#endif
/* ----------------- CPU TS FNCTS ----------------- */
#if ((CPU_CFG_TS_EN == DEF_ENABLED) || \
(CPU_CFG_TS_TMR_EN == DEF_ENABLED))
static void CPU_TS_Init (void);
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN /* ---------- CPU INT DIS TIME MEAS FNCTS --------- */
static void CPU_IntDisMeasInit (void);
static CPU_TS_TMR CPU_IntDisMeasMaxCalc(CPU_TS_TMR time_tot_cnts);
#endif
/*
*********************************************************************************************************
* LOCAL CONFIGURATION ERRORS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* CPU_Init()
*
* Description : (1) Initialize CPU module :
*
* (a) Initialize CPU timestamps
* (b) Initialize CPU interrupts disabled time measurements
* (c) Initialize CPU host name
*
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Note(s) : (2) CPU_Init() MUST be called ... :
*
* (a) ONLY ONCE from a product's application; ...
* (b) BEFORE product's application calls any core CPU module function(s)
*
* (3) The following initialization functions MUST be sequenced as follows :
*
* (a) CPU_TS_Init() SHOULD precede ALL calls to other CPU timestamp functions
*
* (b) CPU_IntDisMeasInit() SHOULD precede ALL calls to CPU_CRITICAL_ENTER()/CPU_CRITICAL_EXIT()
* & other CPU interrupts disabled time measurement functions
*********************************************************************************************************
*/
void CPU_Init (void)
{
/* --------------------- INIT TS ---------------------- */
#if ((CPU_CFG_TS_EN == DEF_ENABLED) || \
(CPU_CFG_TS_TMR_EN == DEF_ENABLED))
CPU_TS_Init(); /* See Note #3a. */
#endif
/* -------------- INIT INT DIS TIME MEAS -------------- */
#ifdef CPU_CFG_INT_DIS_MEAS_EN
CPU_IntDisMeasInit(); /* See Note #3b. */
#endif
/* ------------------ INIT CPU NAME ------------------- */
#if (CPU_CFG_NAME_EN == DEF_ENABLED)
CPU_NameInit();
#endif
#if (CPU_CFG_CACHE_MGMT_EN == DEF_ENABLED)
CPU_Cache_Init();
#endif
}
/*
*********************************************************************************************************
* CPU_SW_Exception()
*
* Description : Trap unrecoverable software exception.
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Note(s) : (1) CPU_SW_Exception() deadlocks the current code execution -- whether multi-tasked/
* -processed/-threaded or single-threaded -- when the current code execution cannot
* gracefully recover or report a fault or exception condition.
*
* See also 'cpu_core.h CPU_SW_EXCEPTION() Note #1'.
*********************************************************************************************************
*/
void CPU_SW_Exception (void)
{
for (;;) {
;
}
}
/*
*********************************************************************************************************
* CPU_NameClr()
*
* Description : Clear CPU Name.
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
#if (CPU_CFG_NAME_EN == DEF_ENABLED)
void CPU_NameClr (void)
{
CPU_SR_ALLOC();
CPU_CRITICAL_ENTER();
Mem_Clr((void *)&CPU_Name[0],
(CPU_SIZE_T) CPU_CFG_NAME_SIZE);
CPU_CRITICAL_EXIT();
}
#endif
/*
*********************************************************************************************************
* CPU_NameGet()
*
* Description : Get CPU host name.
*
* Argument(s) : p_name Pointer to an ASCII character array that will receive the return CPU host
* name ASCII string from this function (see Note #1).
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* CPU_ERR_NONE CPU host name successfully returned.
* CPU_ERR_NULL_PTR Argument 'p_name' passed a NULL pointer.
*
* Return(s) : none.
*
* Note(s) : (1) The size of the ASCII character array that will receive the return CPU host name
* ASCII string :
*
* (a) MUST be greater than or equal to the current CPU host name's ASCII string
* size including the terminating NULL character;
* (b) SHOULD be greater than or equal to CPU_CFG_NAME_SIZE
*********************************************************************************************************
*/
#if (CPU_CFG_NAME_EN == DEF_ENABLED)
void CPU_NameGet (CPU_CHAR *p_name,
CPU_ERR *p_err)
{
CPU_SR_ALLOC();
if (p_err == (CPU_ERR *)0) {
CPU_SW_EXCEPTION(;);
}
if (p_name == (CPU_CHAR *)0) {
*p_err = CPU_ERR_NULL_PTR;
return;
}
CPU_CRITICAL_ENTER();
(void)Str_Copy_N(p_name,
&CPU_Name[0],
CPU_CFG_NAME_SIZE);
CPU_CRITICAL_EXIT();
*p_err = CPU_ERR_NONE;
}
#endif
/*
*********************************************************************************************************
* CPU_NameSet()
*
* Description : Set CPU host name.
*
* Argument(s) : p_name Pointer to CPU host name to set.
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* CPU_ERR_NONE CPU host name successfully set.
* CPU_ERR_NULL_PTR Argument 'p_name' passed a NULL pointer.
* CPU_ERR_NAME_SIZE Invalid CPU host name size (see Note #1).
*
* Return(s) : none.
*
* Note(s) : (1) 'p_name' ASCII string size, including the terminating NULL character, MUST be less
* than or equal to CPU_CFG_NAME_SIZE.
*********************************************************************************************************
*/
#if (CPU_CFG_NAME_EN == DEF_ENABLED)
void CPU_NameSet (const CPU_CHAR *p_name,
CPU_ERR *p_err)
{
CPU_SIZE_T len;
CPU_SR_ALLOC();
if (p_err == (CPU_ERR *)0) {
CPU_SW_EXCEPTION(;);
}
if (p_name == (const CPU_CHAR *)0) {
*p_err = CPU_ERR_NULL_PTR;
return;
}
len = Str_Len_N(p_name,
CPU_CFG_NAME_SIZE);
if (len < CPU_CFG_NAME_SIZE) { /* If cfg name len < max name size, ... */
CPU_CRITICAL_ENTER();
(void)Str_Copy_N(&CPU_Name[0], /* ... copy cfg name to CPU host name. */
p_name,
CPU_CFG_NAME_SIZE);
CPU_CRITICAL_EXIT();
*p_err = CPU_ERR_NONE;
} else {
*p_err = CPU_ERR_NAME_SIZE;
}
}
#endif
/*
*********************************************************************************************************
* CPU_TS_Get32()
*
* Description : Get current 32-bit CPU timestamp.
*
* Argument(s) : none.
*
* Return(s) : Current 32-bit CPU timestamp (in timestamp timer counts).
*
* Note(s) : (1) When applicable, the amount of time measured by CPU timestamps is calculated by
* either of the following equations :
*
* (a) Time measured = Number timer counts * Timer period
*
* where
*
* Number timer counts Number of timer counts measured
* Timer period Timer's period in some units of
* (fractional) seconds
* Time measured Amount of time measured, in same
* units of (fractional) seconds
* as the Timer period
*
* Number timer counts
* (b) Time measured = ---------------------
* Timer frequency
*
* where
*
* Number timer counts Number of timer counts measured
* Timer frequency Timer's frequency in some units
* of counts per second
* Time measured Amount of time measured, in seconds
*
* See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c1'.
*
* (2) In case the CPU timestamp timer has lower precision than the 32-bit CPU timestamp;
* its precision is extended via periodic updates by accumulating the deltas of the
* timestamp timer count values into the higher-precision 32-bit CPU timestamp.
*
* (3) After initialization, 'CPU_TS_32_Accum' & 'CPU_TS_32_TmrPrev' MUST ALWAYS
* be accessed AND updated exclusively with interrupts disabled -- but NOT
* with critical sections.
*********************************************************************************************************
*/
#if (CPU_CFG_TS_32_EN == DEF_ENABLED)
CPU_TS32 CPU_TS_Get32 (void)
{
CPU_TS32 ts;
#if (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)
CPU_TS_TMR tmr_cur;
CPU_TS_TMR tmr_delta;
CPU_SR_ALLOC();
#endif
#if (CPU_CFG_TS_TMR_SIZE >= CPU_WORD_SIZE_32)
ts = (CPU_TS32)CPU_TS_TmrRd(); /* Get cur ts tmr val (in 32-bit ts cnts). */
#else
CPU_INT_DIS();
tmr_cur = (CPU_TS_TMR) CPU_TS_TmrRd(); /* Get cur ts tmr val (in ts tmr cnts). */
tmr_delta = (CPU_TS_TMR)(tmr_cur - CPU_TS_32_TmrPrev); /* Calc delta ts tmr cnts. */
CPU_TS_32_Accum += (CPU_TS32 ) tmr_delta; /* Inc ts by delta ts tmr cnts (see Note #2). */
CPU_TS_32_TmrPrev = (CPU_TS_TMR) tmr_cur; /* Save cur ts tmr cnts for next update. */
ts = (CPU_TS32 ) CPU_TS_32_Accum;
CPU_INT_EN();
#endif
return (ts);
}
#endif
/*
*********************************************************************************************************
* CPU_TS_Get64()
*
* Description : Get current 64-bit CPU timestamp.
*
* Argument(s) : none.
*
* Return(s) : Current 64-bit CPU timestamp (in timestamp timer counts).
*
* Note(s) : (1) When applicable, the amount of time measured by CPU timestamps is calculated by
* either of the following equations :
*
* (a) Time measured = Number timer counts * Timer period
*
* where
*
* Number timer counts Number of timer counts measured
* Timer period Timer's period in some units of
* (fractional) seconds
* Time measured Amount of time measured, in same
* units of (fractional) seconds
* as the Timer period
*
* Number timer counts
* (b) Time measured = ---------------------
* Timer frequency
*
* where
*
* Number timer counts Number of timer counts measured
* Timer frequency Timer's frequency in some units
* of counts per second
* Time measured Amount of time measured, in seconds
*
* See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c1'.
*
* (2) In case the CPU timestamp timer has lower precision than the 64-bit CPU timestamp;
* its precision is extended via periodic updates by accumulating the deltas of the
* timestamp timer count values into the higher-precision 64-bit CPU timestamp.
*
* (3) After initialization, 'CPU_TS_64_Accum' & 'CPU_TS_64_TmrPrev' MUST ALWAYS
* be accessed AND updated exclusively with interrupts disabled -- but NOT
* with critical sections.
*********************************************************************************************************
*/
#if (CPU_CFG_TS_64_EN == DEF_ENABLED)
CPU_TS64 CPU_TS_Get64 (void)
{
CPU_TS64 ts;
#if (CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64)
CPU_TS_TMR tmr_cur;
CPU_TS_TMR tmr_delta;
CPU_SR_ALLOC();
#endif
#if (CPU_CFG_TS_TMR_SIZE >= CPU_WORD_SIZE_64)
ts = (CPU_TS64)CPU_TS_TmrRd(); /* Get cur ts tmr val (in 64-bit ts cnts). */
#else
CPU_INT_DIS();
tmr_cur = (CPU_TS_TMR) CPU_TS_TmrRd(); /* Get cur ts tmr val (in ts tmr cnts). */
tmr_delta = (CPU_TS_TMR)(tmr_cur - CPU_TS_64_TmrPrev); /* Calc delta ts tmr cnts. */
CPU_TS_64_Accum += (CPU_TS64 ) tmr_delta; /* Inc ts by delta ts tmr cnts (see Note #2). */
CPU_TS_64_TmrPrev = (CPU_TS_TMR) tmr_cur; /* Save cur ts tmr cnts for next update. */
ts = (CPU_TS64 ) CPU_TS_64_Accum;
CPU_INT_EN();
#endif
return (ts);
}
#endif
/*
*********************************************************************************************************
* CPU_TS_Update()
*
* Description : Update current CPU timestamp(s).
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Note(s) : (1) (a) CPU timestamp(s) MUST be updated periodically by some application (or BSP) time
* handler in order to (adequately) maintain CPU timestamp(s)' time.
*
* (b) CPU timestamp(s) MUST be updated more frequently than the CPU timestamp timer
* overflows; otherwise, CPU timestamp(s) will lose time.
*
* See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c2'.
*********************************************************************************************************
*/
#if (CPU_CFG_TS_EN == DEF_ENABLED)
void CPU_TS_Update (void)
{
#if ((CPU_CFG_TS_32_EN == DEF_ENABLED) && \
(CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32))
(void)CPU_TS_Get32();
#endif
#if ((CPU_CFG_TS_64_EN == DEF_ENABLED) && \
(CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64))
(void)CPU_TS_Get64();
#endif
}
#endif
/*
*********************************************************************************************************
* CPU_TS_TmrFreqGet()
*
* Description : Get CPU timestamp's timer frequency.
*
* Argument(s) : p_err Pointer to variable that will receive the return error code from this function :
*
* CPU_ERR_NONE CPU timestamp's timer frequency successfully
* returned.
* CPU_ERR_TS_FREQ_INVALID CPU timestamp's timer frequency invalid &/or
* NOT yet configured.
*
* Return(s) : CPU timestamp's timer frequency (in Hertz), if NO error(s).
*
* 0, otherwise.
*
* Note(s) : none.
*********************************************************************************************************
*/
#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
CPU_TS_TMR_FREQ CPU_TS_TmrFreqGet (CPU_ERR *p_err)
{
CPU_TS_TMR_FREQ freq_hz;
if (p_err == (CPU_ERR *)0) {
CPU_SW_EXCEPTION(0);
}
freq_hz = CPU_TS_TmrFreq_Hz;
*p_err = (freq_hz != 0u) ? CPU_ERR_NONE : CPU_ERR_TS_FREQ_INVALID;
return (freq_hz);
}
#endif
/*
*********************************************************************************************************
* CPU_TS_TmrFreqSet()
*
* Description : Set CPU timestamp's timer frequency.
*
* Argument(s) : freq_hz Frequency (in Hertz) to set for CPU timestamp's timer.
*
* Return(s) : none.
*
* Note(s) : (1) (a) (1) CPU timestamp timer frequency is NOT required for internal CPU timestamp
* operations but may OPTIONALLY be configured by CPU_TS_TmrInit() or other
* application/BSP initialization functions.
*
* (2) CPU timestamp timer frequency MAY be used with optional CPU_TSxx_to_uSec()
* to convert CPU timestamps from timer counts into microseconds.
*
* See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2a'.
*
* (b) CPU timestamp timer period SHOULD be less than the typical measured time but MUST
* be less than the maximum measured time; otherwise, timer resolution inadequate to
* measure desired times.
*
* See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2b'.
*********************************************************************************************************
*/
#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void CPU_TS_TmrFreqSet (CPU_TS_TMR_FREQ freq_hz)
{
CPU_TS_TmrFreq_Hz = freq_hz;
}
#endif
/*
*********************************************************************************************************
* CPU_IntDisMeasMaxCurReset()
*
* Description : Reset current maximum interrupts disabled time.
*
* Argument(s) : none.
*
* Return(s) : Maximum interrupts disabled time (in CPU timestamp timer counts) before resetting.
*
* See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c'
* & 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2'.
*
* Note(s) : (1) After initialization, 'CPU_IntDisMeasMaxCur_cnts' MUST ALWAYS be accessed
* exclusively with interrupts disabled -- but NOT with critical sections.
*********************************************************************************************************
*/
#ifdef CPU_CFG_INT_DIS_MEAS_EN
CPU_TS_TMR CPU_IntDisMeasMaxCurReset (void)
{
CPU_TS_TMR time_max_cnts;
CPU_SR_ALLOC();
time_max_cnts = CPU_IntDisMeasMaxCurGet();
CPU_INT_DIS();
CPU_IntDisMeasMaxCur_cnts = 0u;
CPU_INT_EN();
return (time_max_cnts);
}
#endif
/*
*********************************************************************************************************
* CPU_IntDisMeasMaxCurGet()
*
* Description : Get current maximum interrupts disabled time.
*
* Argument(s) : none.
*
* Return(s) : Current maximum interrupts disabled time (in CPU timestamp timer counts).
*
* See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c'
* & 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2'.
*
* Note(s) : (1) After initialization, 'CPU_IntDisMeasMaxCur_cnts' MUST ALWAYS be accessed
* exclusively with interrupts disabled -- but NOT with critical sections.
*********************************************************************************************************
*/
#ifdef CPU_CFG_INT_DIS_MEAS_EN
CPU_TS_TMR CPU_IntDisMeasMaxCurGet (void)
{
CPU_TS_TMR time_tot_cnts;
CPU_TS_TMR time_max_cnts;
CPU_SR_ALLOC();
CPU_INT_DIS();
time_tot_cnts = CPU_IntDisMeasMaxCur_cnts;
CPU_INT_EN();
time_max_cnts = CPU_IntDisMeasMaxCalc(time_tot_cnts);
return (time_max_cnts);
}
#endif
/*
*********************************************************************************************************
* CPU_IntDisMeasMaxGet()
*
* Description : Get (non-resetable) maximum interrupts disabled time.
*
* Argument(s) : none.
*
* Return(s) : (Non-resetable) maximum interrupts disabled time (in CPU timestamp timer counts).
*
* See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c'
* & 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2'.
*
* Note(s) : (1) After initialization, 'CPU_IntDisMeasMax_cnts' MUST ALWAYS be accessed
* exclusively with interrupts disabled -- but NOT with critical sections.
*********************************************************************************************************
*/
#ifdef CPU_CFG_INT_DIS_MEAS_EN
CPU_TS_TMR CPU_IntDisMeasMaxGet (void)
{
CPU_TS_TMR time_tot_cnts;
CPU_TS_TMR time_max_cnts;
CPU_SR_ALLOC();
CPU_INT_DIS();
time_tot_cnts = CPU_IntDisMeasMax_cnts;
CPU_INT_EN();
time_max_cnts = CPU_IntDisMeasMaxCalc(time_tot_cnts);
return (time_max_cnts);
}
#endif
/*
*********************************************************************************************************
* CPU_IntDisMeasStart()
*
* Description : Start interrupts disabled time measurement.
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
#ifdef CPU_CFG_INT_DIS_MEAS_EN
void CPU_IntDisMeasStart (void)
{
CPU_IntDisMeasCtr++;
if (CPU_IntDisNestCtr == 0u) { /* If ints NOT yet dis'd, ... */
CPU_IntDisMeasStart_cnts = CPU_TS_TmrRd(); /* ... get ints dis'd start time. */
}
CPU_IntDisNestCtr++;
}
#endif
/*
*********************************************************************************************************
* CPU_IntDisMeasStop()
*
* Description : Stop interrupts disabled time measurement.
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Note(s) : (1) (a) The total amount of time interrupts are disabled by system &/or application code
* during critical sections is calculated by the following equations :
*
* (1) When interrupts disabled time measurements are disabled :
*
*
* | CRITICAL | | CRITICAL |
* |<- SECTION ->| |<- SECTION ->|
* | ENTER | | EXIT |
*
* Disable Enable
* Interrupts Interrupts
*
* || || || ||
* || || || ||
* || | ||<------------------------->|| | ||
* || |<->|| | ||<----->| ||
* || | | || | || | | ||
* | | | | |
* interrupts time interrupts
* disabled interrupts |enabled
* | disabled |
* | (via application) |
* time time
* interrupts interrupts
* disabled ovrhd enabled ovrhd
*
*
* (A) time = [ time - time ] - time
* interrupts [ interrupts interrupts ] total
* disabled [ enabled disabled ] ovrhd
* (via application)
*
*
* (B) time = time + time
* total interrupts interrupts
* ovrhd enabled ovrhd disabled ovrhd
*
*
* where
*
* time time interrupts are disabled between
* interrupts first critical section enter &
* disabled last critical section exit (i.e.
* (via application) minus total overhead time)
*
* time time when interrupts are disabled
* interrupts
* disabled
*
* time time when interrupts are enabled
* interrupts
* enabled
*
*
* time total overhead time to disable/enable
* total interrupts during critical section
* ovrhd enter & exit
*
* time total overhead time to disable interrupts
* interrupts during critical section enter
* disabled ovrhd
*
* time total overhead time to enable interrupts
* interrupts during critical section exit
* enabled ovrhd
*
*
* (2) When interrupts disabled time measurements are enabled :
*
*
* | | | |
* |<----- CRITICAL SECTION ENTER ----->| |<------- CRITICAL SECTION EXIT ------->|
* | | | |
*
* Time Time
* Disable Measurement Measurement Enable
* Interrupts Start Stop Interrupts
*
* || | || || | ||
* || | || || | ||
* || | | ||<------------------------->|| | | ||
* || | | |<----------->|| | ||<------------->| | | ||
* || | | | | || | || | | | | ||
* | | | | | | |
* interrupts get | time | get interrupts
* disabled start time | interrupts | stop time enabled
* meas | disabled | meas
* time (via application) time
* start meas stop meas
* ovrhd ovrhd
*
*
* (A) time = [ time - time ] - time
* interrupts [ stop start ] total meas
* disabled [ meas meas ] ovrhd
* (via application)
*
*
* (B) time = time + time
* total meas start meas stop meas
* ovrhd ovrhd ovrhd
*
*
* where
*
* time time interrupts are disabled between first
* interrupts critical section enter & last critical
* disabled section exit (i.e. minus measurement
* (via application) overhead time; however, this does NOT
* include any overhead time to disable
* or enable interrupts during critical
* section enter & exit)
*
* time time of disable interrupts start time
* start measurement (in timer counts)
* meas
*
* time time of disable interrupts stop time
* stop measurement (in timer counts)
* meas
*
*
* time total overhead time to start/stop disabled
* total meas interrupts time measurements (in timer
* ovrhd counts)
*
* time total overhead time after getting start
* start meas time until end of start measurement
* ovrhd function (in timer counts)
*
* time total overhead time from beginning of stop
* stop meas measurement function until after getting
* ovrhd stop time (in timer counts)
*
*
* (b) (1) (A) In order to correctly handle unsigned subtraction overflows of start times
* from stop times, CPU timestamp timer count values MUST be returned via
* word-size-configurable 'CPU_TS_TMR' data type.
*
* See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2a'.
*
* (B) Since unsigned subtraction of start times from stop times assumes increasing
* values, timestamp timer count values MUST increase with each time count.
*
* See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2b'.
*
* (2) (A) To expedite & reduce interrupts disabled time measurement overhead; only the
* subtraction of start times from stop times is performed.
*
* (B) The final calculations to subtract the interrupts disabled time measurement
* overhead is performed asynchronously in appropriate API functions.
*
* See also 'CPU_IntDisMeasMaxCalc() Note #1b'.
*********************************************************************************************************
*/
#ifdef CPU_CFG_INT_DIS_MEAS_EN
void CPU_IntDisMeasStop (void)
{
CPU_TS_TMR time_ints_disd_cnts;
CPU_IntDisNestCtr--;
if (CPU_IntDisNestCtr == 0u) { /* If ints NO longer dis'd, ... */
CPU_IntDisMeasStop_cnts = CPU_TS_TmrRd(); /* ... get ints dis'd stop time & ... */
/* ... calc ints dis'd tot time (see Note #1b2A). */
time_ints_disd_cnts = CPU_IntDisMeasStop_cnts -
CPU_IntDisMeasStart_cnts;
/* Calc max ints dis'd times. */
if (CPU_IntDisMeasMaxCur_cnts < time_ints_disd_cnts) {
CPU_IntDisMeasMaxCur_cnts = time_ints_disd_cnts;
}
if (CPU_IntDisMeasMax_cnts < time_ints_disd_cnts) {
CPU_IntDisMeasMax_cnts = time_ints_disd_cnts;
}
}
}
#endif
/*
*********************************************************************************************************
* CPU_CntLeadZeros()
*
* Description : Count the number of contiguous, most-significant, leading zero bits in a data value.
*
* Argument(s) : val Data value to count leading zero bits.
*
* Return(s) : Number of contiguous, most-significant, leading zero bits in 'val', if NO error(s).
*
* DEF_INT_CPU_U_MAX_VAL, otherwise.
*
* Note(s) : (1) (a) Supports the following data value sizes :
*
* (1) 8-bits
* (2) 16-bits
* (3) 32-bits
* (4) 64-bits
*
* See also 'cpu_def.h CPU WORD CONFIGURATION Note #1'.
*
* (b) (1) For 8-bit values :
*
* b07 b06 b05 b04 b03 b02 b01 b00 # Leading Zeros
* --- --- --- --- --- --- --- --- ---------------
* 1 x x x x x x x 0
* 0 1 x x x x x x 1
* 0 0 1 x x x x x 2
* 0 0 0 1 x x x x 3
* 0 0 0 0 1 x x x 4
* 0 0 0 0 0 1 x x 5
* 0 0 0 0 0 0 1 x 6
* 0 0 0 0 0 0 0 1 7
* 0 0 0 0 0 0 0 0 8
*
*
* (2) For 16-bit values :
*
* b15 b14 b13 ... b04 b03 b02 b01 b00 # Leading Zeros
* --- --- --- --- --- --- --- --- ---------------
* 1 x x x x x x x 0
* 0 1 x x x x x x 1
* 0 0 1 x x x x x 2
* : : : : : : : : :
* : : : : : : : : :
* 0 0 0 1 x x x x 11
* 0 0 0 0 1 x x x 12
* 0 0 0 0 0 1 x x 13
* 0 0 0 0 0 0 1 x 14
* 0 0 0 0 0 0 0 1 15
* 0 0 0 0 0 0 0 0 16
*
* (3) For 32-bit values :
*
* b31 b30 b29 ... b04 b03 b02 b01 b00 # Leading Zeros
* --- --- --- --- --- --- --- --- ---------------
* 1 x x x x x x x 0
* 0 1 x x x x x x 1
* 0 0 1 x x x x x 2
* : : : : : : : : :
* : : : : : : : : :
* 0 0 0 1 x x x x 27
* 0 0 0 0 1 x x x 28
* 0 0 0 0 0 1 x x 29
* 0 0 0 0 0 0 1 x 30
* 0 0 0 0 0 0 0 1 31
* 0 0 0 0 0 0 0 0 32
*
*
* (4) For 64-bit values :
*
* b63 b62 b61 ... b04 b03 b02 b01 b00 # Leading Zeros
* --- --- --- --- --- --- --- --- ---------------
* 1 x x x x x x x 0
* 0 1 x x x x x x 1
* 0 0 1 x x x x x 2
* : : : : : : : : :
* : : : : : : : : :
* 0 0 0 1 x x x x 59
* 0 0 0 0 1 x x x 60
* 0 0 0 0 0 1 x x 61
* 0 0 0 0 0 0 1 x 62
* 0 0 0 0 0 0 0 1 63
* 0 0 0 0 0 0 0 0 64
*
*
* See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE Note #1'.
*********************************************************************************************************
*/
#ifndef CPU_CFG_LEAD_ZEROS_ASM_PRESENT
CPU_DATA CPU_CntLeadZeros (CPU_DATA val)
{
CPU_DATA nbr_lead_zeros;
#if (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_08)
nbr_lead_zeros = CPU_CntLeadZeros08((CPU_INT08U)val);
#elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_16)
nbr_lead_zeros = CPU_CntLeadZeros16((CPU_INT16U)val);
#elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_32)
nbr_lead_zeros = CPU_CntLeadZeros32((CPU_INT32U)val);
#elif (CPU_CFG_DATA_SIZE == CPU_WORD_SIZE_64)
nbr_lead_zeros = CPU_CntLeadZeros64((CPU_INT64U)val);
#else /* See Note #1a. */
nbr_lead_zeros = DEF_INT_CPU_U_MAX_VAL;
#endif
return (nbr_lead_zeros);
}
#endif
/*
*********************************************************************************************************
* CPU_CntLeadZeros08()
*
* Description : Count the number of contiguous, most-significant, leading zero bits in an 8-bit data value.
*
* Argument(s) : val Data value to count leading zero bits.
*
* Return(s) : Number of contiguous, most-significant, leading zero bits in 'val'.
*
* Note(s) : (1) Supports 8-bit values :
*
* b07 b06 b05 b04 b03 b02 b01 b00 # Leading Zeros
* --- --- --- --- --- --- --- --- ---------------
* 1 x x x x x x x 0
* 0 1 x x x x x x 1
* 0 0 1 x x x x x 2
* 0 0 0 1 x x x x 3
* 0 0 0 0 1 x x x 4
* 0 0 0 0 0 1 x x 5
* 0 0 0 0 0 0 1 x 6
* 0 0 0 0 0 0 0 1 7
* 0 0 0 0 0 0 0 0 8
*
*
* See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE Note #1'.
*********************************************************************************************************
*/
#if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_08)
CPU_DATA CPU_CntLeadZeros08 (CPU_INT08U val)
{
#if (!((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_08)))
CPU_DATA ix;
#endif
CPU_DATA nbr_lead_zeros;
/* ---------- ASM-OPTIMIZED ----------- */
#if ((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_08))
nbr_lead_zeros = CPU_CntLeadZeros((CPU_DATA)val);
nbr_lead_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_08) * DEF_OCTET_NBR_BITS;
#else /* ----------- C-OPTIMIZED ------------ */
/* Chk bits [07:00] : */
/* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 0 bits */
nbr_lead_zeros = (CPU_DATA)(CPU_CntLeadZerosTbl[ix]); /* .. plus nbr msb lead zeros = 0 bits.*/
#endif
return (nbr_lead_zeros);
}
#endif
/*
*********************************************************************************************************
* CPU_CntLeadZeros16()
*
* Description : Count the number of contiguous, most-significant, leading zero bits in a 16-bit data value.
*
* Argument(s) : val Data value to count leading zero bits.
*
* Return(s) : Number of contiguous, most-significant, leading zero bits in 'val'.
*
* Note(s) : (1) Supports 16-bit values :
*
* b15 b14 b13 ... b04 b03 b02 b01 b00 # Leading Zeros
* --- --- --- --- --- --- --- --- ---------------
* 1 x x x x x x x 0
* 0 1 x x x x x x 1
* 0 0 1 x x x x x 2
* : : : : : : : : :
* : : : : : : : : :
* 0 0 0 1 x x x x 11
* 0 0 0 0 1 x x x 12
* 0 0 0 0 0 1 x x 13
* 0 0 0 0 0 0 1 x 14
* 0 0 0 0 0 0 0 1 15
* 0 0 0 0 0 0 0 0 16
*
*
* See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE Note #1'.
*********************************************************************************************************
*/
#if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_16)
CPU_DATA CPU_CntLeadZeros16 (CPU_INT16U val)
{
#if (!((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_16)))
CPU_DATA ix;
#endif
CPU_DATA nbr_lead_zeros;
/* ---------- ASM-OPTIMIZED ----------- */
#if ((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_16))
nbr_lead_zeros = CPU_CntLeadZeros((CPU_DATA)val);
nbr_lead_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_16) * DEF_OCTET_NBR_BITS;
#else /* ----------- C-OPTIMIZED ------------ */
if (val > 0x00FFu) { /* Chk bits [15:08] : */
val >>= 8u; /* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 8 bits */
nbr_lead_zeros = (CPU_DATA)(CPU_CntLeadZerosTbl[ix]); /* .. plus nbr msb lead zeros = 0 bits.*/
} else { /* Chk bits [07:00] : */
/* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 0 bits */
nbr_lead_zeros = (CPU_DATA)((CPU_DATA)CPU_CntLeadZerosTbl[ix] + 8u); /* .. plus nbr msb lead zeros = 8 bits.*/
}
#endif
return (nbr_lead_zeros);
}
#endif
/*
*********************************************************************************************************
* CPU_CntLeadZeros32()
*
* Description : Count the number of contiguous, most-significant, leading zero bits in a 32-bit data value.
*
* Argument(s) : val Data value to count leading zero bits.
*
* Return(s) : Number of contiguous, most-significant, leading zero bits in 'val'.
*
* Note(s) : (1) Supports 32-bit values :
*
* b31 b30 b29 ... b04 b03 b02 b01 b00 # Leading Zeros
* --- --- --- --- --- --- --- --- ---------------
* 1 x x x x x x x 0
* 0 1 x x x x x x 1
* 0 0 1 x x x x x 2
* : : : : : : : : :
* : : : : : : : : :
* 0 0 0 1 x x x x 27
* 0 0 0 0 1 x x x 28
* 0 0 0 0 0 1 x x 29
* 0 0 0 0 0 0 1 x 30
* 0 0 0 0 0 0 0 1 31
* 0 0 0 0 0 0 0 0 32
*
*
* See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE Note #1'.
*********************************************************************************************************
*/
#if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_32)
CPU_DATA CPU_CntLeadZeros32 (CPU_INT32U val)
{
#if (!((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_32)))
CPU_DATA ix;
#endif
CPU_DATA nbr_lead_zeros;
/* ---------- ASM-OPTIMIZED ----------- */
#if ((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_32))
nbr_lead_zeros = CPU_CntLeadZeros((CPU_DATA)val);
nbr_lead_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_32) * DEF_OCTET_NBR_BITS;
#else /* ----------- C-OPTIMIZED ------------ */
if (val > 0x0000FFFFu) {
if (val > 0x00FFFFFFu) { /* Chk bits [31:24] : */
val >>= 24u; /* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 24 bits */
nbr_lead_zeros = (CPU_DATA)(CPU_CntLeadZerosTbl[ix]); /* .. plus nbr msb lead zeros = 0 bits.*/
} else { /* Chk bits [23:16] : */
val >>= 16u; /* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 16 bits */
nbr_lead_zeros = (CPU_DATA)((CPU_DATA)CPU_CntLeadZerosTbl[ix] + 8u);/* .. plus nbr msb lead zeros = 8 bits.*/
}
} else {
if (val > 0x000000FFu) { /* Chk bits [15:08] : */
val >>= 8u; /* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 8 bits */
nbr_lead_zeros = (CPU_DATA)((CPU_DATA)CPU_CntLeadZerosTbl[ix] + 16u);/* .. plus nbr msb lead zeros = 16 bits.*/
} else { /* Chk bits [07:00] : */
/* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 0 bits */
nbr_lead_zeros = (CPU_DATA)((CPU_DATA)CPU_CntLeadZerosTbl[ix] + 24u);/* .. plus nbr msb lead zeros = 24 bits.*/
}
}
#endif
return (nbr_lead_zeros);
}
#endif
/*
*********************************************************************************************************
* CPU_CntLeadZeros64()
*
* Description : Count the number of contiguous, most-significant, leading zero bits in a 64-bit data value.
*
* Argument(s) : val Data value to count leading zero bits.
*
* Return(s) : Number of contiguous, most-significant, leading zero bits in 'val'.
*
* Note(s) : (1) Supports 64-bit values :
*
* b63 b62 b61 ... b04 b03 b02 b01 b00 # Leading Zeros
* --- --- --- --- --- --- --- --- ---------------
* 1 x x x x x x x 0
* 0 1 x x x x x x 1
* 0 0 1 x x x x x 2
* : : : : : : : : :
* : : : : : : : : :
* 0 0 0 1 x x x x 59
* 0 0 0 0 1 x x x 60
* 0 0 0 0 0 1 x x 61
* 0 0 0 0 0 0 1 x 62
* 0 0 0 0 0 0 0 1 63
* 0 0 0 0 0 0 0 0 64
*
*
* See also 'CPU COUNT LEAD ZEROs LOOKUP TABLE Note #1'.
*********************************************************************************************************
*/
#if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_64)
CPU_DATA CPU_CntLeadZeros64 (CPU_INT64U val)
{
#if (!((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_64)))
CPU_DATA ix;
#endif
CPU_DATA nbr_lead_zeros;
/* ---------- ASM-OPTIMIZED ----------- */
#if ((defined(CPU_CFG_LEAD_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_64))
nbr_lead_zeros = CPU_CntLeadZeros((CPU_DATA)val);
nbr_lead_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_64) * DEF_OCTET_NBR_BITS;
#else /* ----------- C-OPTIMIZED ------------ */
if (val > 0x00000000FFFFFFFFuLL) {
if (val > 0x0000FFFFFFFFFFFFuLL) {
if (val > 0x00FFFFFFFFFFFFFFuLL) { /* Chk bits [63:56] : */
val >>= 56u; /* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 56 bits */
nbr_lead_zeros = (CPU_DATA)(CPU_CntLeadZerosTbl[ix]); /* .. plus nbr msb lead zeros = 0 bits.*/
} else { /* Chk bits [55:48] : */
val >>= 48u; /* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 48 bits */
nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 8u);/* .. plus nbr msb lead zeros = 8 bits.*/
}
} else {
if (val > 0x000000FFFFFFFFFFuLL) { /* Chk bits [47:40] : */
val >>= 40u; /* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 40 bits */
nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 16u);/* .. plus nbr msb lead zeros = 16 bits.*/
} else { /* Chk bits [39:32] : */
val >>= 32u; /* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 32 bits */
nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 24u);/* .. plus nbr msb lead zeros = 24 bits.*/
}
}
} else {
if (val > 0x000000000000FFFFuLL) {
if (val > 0x0000000000FFFFFFuLL) { /* Chk bits [31:24] : */
val >>= 24u; /* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 24 bits */
nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 32u);/* .. plus nbr msb lead zeros = 32 bits.*/
} else { /* Chk bits [23:16] : */
val >>= 16u; /* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 16 bits */
nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 40u);/* .. plus nbr msb lead zeros = 40 bits.*/
}
} else {
if (val > 0x00000000000000FFuLL) { /* Chk bits [15:08] : */
val >>= 8u; /* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 8 bits */
nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 48u);/* .. plus nbr msb lead zeros = 48 bits.*/
} else { /* Chk bits [07:00] : */
/* .. Nbr lead zeros = .. */
ix = (CPU_DATA)(val); /* .. lookup tbl ix = 'val' >> 0 bits */
nbr_lead_zeros = (CPU_DATA)((CPU_INT64U)CPU_CntLeadZerosTbl[ix] + 56u);/* .. plus nbr msb lead zeros = 56 bits.*/
}
}
}
#endif
return (nbr_lead_zeros);
}
#endif
/*
*********************************************************************************************************
* CPU_CntTrailZeros()
*
* Description : Count the number of contiguous, least-significant, trailing zero bits in a data value.
*
* Argument(s) : val Data value to count trailing zero bits.
*
* Return(s) : Number of contiguous, least-significant, trailing zero bits in 'val'.
*
* Note(s) : (1) (a) Supports the following data value sizes :
*
* (1) 8-bits
* (2) 16-bits
* (3) 32-bits
* (4) 64-bits
*
* See also 'cpu_def.h CPU WORD CONFIGURATION Note #1'.
*
* (b) (1) For 8-bit values :
*
* b07 b06 b05 b04 b03 b02 b01 b00 # Trailing Zeros
* --- --- --- --- --- --- --- --- ----------------
* x x x x x x x 1 0
* x x x x x x 1 0 1
* x x x x x 1 0 0 2
* x x x x 1 0 0 0 3
* x x x 1 0 0 0 0 4
* x x 1 0 0 0 0 0 5
* x 1 0 0 0 0 0 0 6
* 1 0 0 0 0 0 0 0 7
* 0 0 0 0 0 0 0 0 8
*
*
* (2) For 16-bit values :
*
* b15 b14 b13 b12 b11 ... b02 b01 b00 # Trailing Zeros
* --- --- --- --- --- --- --- --- ----------------
* x x x x x x x 1 0
* x x x x x x 1 0 1
* x x x x x 1 0 0 2
* : : : : : : : : :
* : : : : : : : : :
* x x x x 1 0 0 0 11
* x x x 1 0 0 0 0 12
* x x 1 0 0 0 0 0 13
* x 1 0 0 0 0 0 0 14
* 1 0 0 0 0 0 0 0 15
* 0 0 0 0 0 0 0 0 16
*
*
* (3) For 32-bit values :
*
* b31 b30 b29 b28 b27 ... b02 b01 b00 # Trailing Zeros
* --- --- --- --- --- --- --- --- ----------------
* x x x x x x x 1 0
* x x x x x x 1 0 1
* x x x x x 1 0 0 2
* : : : : : : : : :
* : : : : : : : : :
* x x x x 1 0 0 0 27
* x x x 1 0 0 0 0 28
* x x 1 0 0 0 0 0 29
* x 1 0 0 0 0 0 0 30
* 1 0 0 0 0 0 0 0 31
* 0 0 0 0 0 0 0 0 32
*
*
* (4) For 64-bit values :
*
* b63 b62 b61 b60 b59 ... b02 b01 b00 # Trailing Zeros
* --- --- --- --- --- --- --- --- ----------------
* x x x x x x x 1 0
* x x x x x x 1 0 1
* x x x x x 1 0 0 2
* : : : : : : : : :
* : : : : : : : : :
* x x x x 1 0 0 0 59
* x x x 1 0 0 0 0 60
* x x 1 0 0 0 0 0 61
* x 1 0 0 0 0 0 0 62
* 1 0 0 0 0 0 0 0 63
* 0 0 0 0 0 0 0 0 64
*
* (2) For non-zero values, the returned number of contiguous, least-significant, trailing
* zero bits is also equivalent to the bit position of the least-significant set bit.
*
* (3) 'val' SHOULD be validated for non-'0' PRIOR to all other counting zero calculations :
*
* (a) CPU_CntTrailZeros()'s final conditional statement calculates 'val's number of
* trailing zeros based on its return data size, 'CPU_CFG_DATA_SIZE', & 'val's
* calculated number of lead zeros ONLY if the initial 'val' is non-'0' :
*
* if (val != 0u) {
* nbr_trail_zeros = ((CPU_CFG_DATA_SIZE * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros;
* } else {
* nbr_trail_zeros = nbr_lead_zeros;
* }
*
* Therefore, initially validating all non-'0' values avoids having to conditionally
* execute the final 'if' statement.
*********************************************************************************************************
*/
#ifndef CPU_CFG_TRAIL_ZEROS_ASM_PRESENT
CPU_DATA CPU_CntTrailZeros (CPU_DATA val)
{
CPU_DATA val_bit_mask;
CPU_DATA nbr_lead_zeros;
CPU_DATA nbr_trail_zeros;
if (val == 0u) { /* Rtn ALL val bits as zero'd (see Note #3). */
return ((CPU_DATA)(CPU_CFG_DATA_SIZE * DEF_OCTET_NBR_BITS));
}
val_bit_mask = val & ((CPU_DATA)~val + 1u); /* Zero/clr all bits EXCEPT least-sig set bit. */
nbr_lead_zeros = CPU_CntLeadZeros(val_bit_mask); /* Cnt nbr lead 0s. */
/* Calc nbr trail 0s = (nbr val bits - 1) - nbr lead 0s.*/
nbr_trail_zeros = ((CPU_DATA)((CPU_CFG_DATA_SIZE * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros);
return (nbr_trail_zeros);
}
#endif
/*
*********************************************************************************************************
* CPU_CntTrailZeros08()
*
* Description : Count the number of contiguous, least-significant, trailing zero bits in an 8-bit data value.
*
* Argument(s) : val Data value to count trailing zero bits.
*
* Return(s) : Number of contiguous, least-significant, trailing zero bits in 'val'.
*
* Note(s) : (1) Supports 8-bit values :
*
* b07 b06 b05 b04 b03 b02 b01 b00 # Trailing Zeros
* --- --- --- --- --- --- --- --- ----------------
* x x x x x x x 1 0
* x x x x x x 1 0 1
* x x x x x 1 0 0 2
* x x x x 1 0 0 0 3
* x x x 1 0 0 0 0 4
* x x 1 0 0 0 0 0 5
* x 1 0 0 0 0 0 0 6
* 1 0 0 0 0 0 0 0 7
* 0 0 0 0 0 0 0 0 8
*
*
* (2) For non-zero values, the returned number of contiguous, least-significant, trailing
* zero bits is also equivalent to the bit position of the least-significant set bit.
*
* (3) 'val' SHOULD be validated for non-'0' PRIOR to all other counting zero calculations :
*
* (a) For assembly-optimized implementations, CPU_CntTrailZeros() returns 'val's
* number of trailing zeros via CPU's native data size, 'CPU_CFG_DATA_SIZE'.
* If the returned number of zeros exceeds CPU_CntTrailZeros08()'s 8-bit return
* data size, then the returned number of zeros must be offset by the difference
* between CPU_CntTrailZeros()'s & CPU_CntTrailZeros08()'s return data size :
*
* nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val);
* if (nbr_trail_zeros > (CPU_WORD_SIZE_08 * DEF_OCTET_NBR_BITS)) {
* nbr_trail_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_08) * DEF_OCTET_NBR_BITS;
* }
*
* However, this ONLY occurs for an initial 'val' of '0' since all non-'0' 8-bit
* values would return a number of trailing zeros less than or equal to 8 bits.
*
* Therefore, initially validating all non-'0' values prior to calling assembly-
* optimized CPU_CntTrailZeros() avoids having to offset the number of returned
* trailing zeros by the difference in CPU data size and 8-bit data value bits.
*
* (b) For CPU_CntTrailZeros08()'s C implementation, the final conditional statement
* calculates 'val's number of trailing zeros based on CPU_CntTrailZeros08()'s
* 8-bit return data size & 'val's calculated number of lead zeros ONLY if the
* initial 'val' is non-'0' :
*
* if (val != 0u) {
* nbr_trail_zeros = ((CPU_WORD_SIZE_08 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros;
* } else {
* nbr_trail_zeros = nbr_lead_zeros;
* }
*
* Therefore, initially validating all non-'0' values avoids having to conditionally
* execute the final 'if' statement.
*********************************************************************************************************
*/
#if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_08)
CPU_DATA CPU_CntTrailZeros08 (CPU_INT08U val)
{
#if (!((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_08)))
CPU_INT08U val_bit_mask;
CPU_DATA nbr_lead_zeros;
#endif
CPU_DATA nbr_trail_zeros;
if (val == 0u) { /* Rtn ALL val bits as zero'd (see Note #3). */
return ((CPU_DATA)(CPU_WORD_SIZE_08 * DEF_OCTET_NBR_BITS));
}
/* ------------------ ASM-OPTIMIZED ------------------- */
#if ((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_08))
nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val);
#else /* ------------------- C-OPTIMIZED -------------------- */
val_bit_mask = val & ((CPU_INT08U)~val + 1u); /* Zero/clr all bits EXCEPT least-sig set bit. */
nbr_lead_zeros = CPU_CntLeadZeros08(val_bit_mask); /* Cnt nbr lead 0s. */
/* Calc nbr trail 0s = (nbr val bits - 1) - nbr lead 0s.*/
nbr_trail_zeros = ((CPU_DATA)((CPU_WORD_SIZE_08 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros);
#endif
return (nbr_trail_zeros);
}
#endif
/*
*********************************************************************************************************
* CPU_CntTrailZeros16()
*
* Description : Count the number of contiguous, least-significant, trailing zero bits in a 16-bit data value.
*
* Argument(s) : val Data value to count trailing zero bits.
*
* Return(s) : Number of contiguous, least-significant, trailing zero bits in 'val'.
*
* Note(s) : (1) Supports 16-bit values :
*
* b15 b14 b13 b12 b11 ... b02 b01 b00 # Trailing Zeros
* --- --- --- --- --- --- --- --- ----------------
* x x x x x x x 1 0
* x x x x x x 1 0 1
* x x x x x 1 0 0 2
* : : : : : : : : :
* : : : : : : : : :
* x x x x 1 0 0 0 11
* x x x 1 0 0 0 0 12
* x x 1 0 0 0 0 0 13
* x 1 0 0 0 0 0 0 14
* 1 0 0 0 0 0 0 0 15
* 0 0 0 0 0 0 0 0 16
*
*
* (2) For non-zero values, the returned number of contiguous, least-significant, trailing
* zero bits is also equivalent to the bit position of the least-significant set bit.
*
* (3) 'val' SHOULD be validated for non-'0' PRIOR to all other counting zero calculations :
*
* (a) For assembly-optimized implementations, CPU_CntTrailZeros() returns 'val's
* number of trailing zeros via CPU's native data size, 'CPU_CFG_DATA_SIZE'.
* If the returned number of zeros exceeds CPU_CntTrailZeros16()'s 16-bit return
* data size, then the returned number of zeros must be offset by the difference
* between CPU_CntTrailZeros()'s & CPU_CntTrailZeros16()'s return data size :
*
* nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val);
* if (nbr_trail_zeros > (CPU_WORD_SIZE_16 * DEF_OCTET_NBR_BITS)) {
* nbr_trail_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_16) * DEF_OCTET_NBR_BITS;
* }
*
* However, this ONLY occurs for an initial 'val' of '0' since all non-'0' 16-bit
* values would return a number of trailing zeros less than or equal to 16 bits.
*
* Therefore, initially validating all non-'0' values prior to calling assembly-
* optimized CPU_CntTrailZeros() avoids having to offset the number of returned
* trailing zeros by the difference in CPU data size and 16-bit data value bits.
*
* (b) For CPU_CntTrailZeros16()'s C implementation, the final conditional statement
* calculates 'val's number of trailing zeros based on CPU_CntTrailZeros16()'s
* 16-bit return data size & 'val's calculated number of lead zeros ONLY if the
* initial 'val' is non-'0' :
*
* if (val != 0u) {
* nbr_trail_zeros = ((CPU_WORD_SIZE_16 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros;
* } else {
* nbr_trail_zeros = nbr_lead_zeros;
* }
*
* Therefore, initially validating all non-'0' values avoids having to conditionally
* execute the final 'if' statement.
*********************************************************************************************************
*/
#if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_16)
CPU_DATA CPU_CntTrailZeros16 (CPU_INT16U val)
{
#if (!((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_16)))
CPU_INT16U val_bit_mask;
CPU_DATA nbr_lead_zeros;
#endif
CPU_DATA nbr_trail_zeros;
if (val == 0u) { /* Rtn ALL val bits as zero'd (see Note #3). */
return ((CPU_DATA)(CPU_WORD_SIZE_16 * DEF_OCTET_NBR_BITS));
}
/* ------------------ ASM-OPTIMIZED ------------------- */
#if ((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_16))
nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val);
#else /* ------------------- C-OPTIMIZED -------------------- */
val_bit_mask = val & ((CPU_INT16U)~val + 1u); /* Zero/clr all bits EXCEPT least-sig set bit. */
nbr_lead_zeros = CPU_CntLeadZeros16(val_bit_mask); /* Cnt nbr lead 0s. */
/* Calc nbr trail 0s = (nbr val bits - 1) - nbr lead 0s.*/
nbr_trail_zeros = ((CPU_DATA)((CPU_WORD_SIZE_16 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros);
#endif
return (nbr_trail_zeros);
}
#endif
/*
*********************************************************************************************************
* CPU_CntTrailZeros32()
*
* Description : Count the number of contiguous, least-significant, trailing zero bits in a 32-bit data value.
*
* Argument(s) : val Data value to count trailing zero bits.
*
* Return(s) : Number of contiguous, least-significant, trailing zero bits in 'val'.
*
* Note(s) : (1) Supports 32-bit values :
*
* b31 b30 b29 b28 b27 ... b02 b01 b00 # Trailing Zeros
* --- --- --- --- --- --- --- --- ----------------
* x x x x x x x 1 0
* x x x x x x 1 0 1
* x x x x x 1 0 0 2
* : : : : : : : : :
* : : : : : : : : :
* x x x x 1 0 0 0 27
* x x x 1 0 0 0 0 28
* x x 1 0 0 0 0 0 29
* x 1 0 0 0 0 0 0 30
* 1 0 0 0 0 0 0 0 31
* 0 0 0 0 0 0 0 0 32
*
*
* (2) For non-zero values, the returned number of contiguous, least-significant, trailing
* zero bits is also equivalent to the bit position of the least-significant set bit.
*
* (3) 'val' SHOULD be validated for non-'0' PRIOR to all other counting zero calculations :
*
* (a) For assembly-optimized implementations, CPU_CntTrailZeros() returns 'val's
* number of trailing zeros via CPU's native data size, 'CPU_CFG_DATA_SIZE'.
* If the returned number of zeros exceeds CPU_CntTrailZeros32()'s 32-bit return
* data size, then the returned number of zeros must be offset by the difference
* between CPU_CntTrailZeros()'s & CPU_CntTrailZeros32()'s return data size :
*
* nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val);
* if (nbr_trail_zeros > (CPU_WORD_SIZE_32 * DEF_OCTET_NBR_BITS)) {
* nbr_trail_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_32) * DEF_OCTET_NBR_BITS;
* }
*
* However, this ONLY occurs for an initial 'val' of '0' since all non-'0' 32-bit
* values would return a number of trailing zeros less than or equal to 32 bits.
*
* Therefore, initially validating all non-'0' values prior to calling assembly-
* optimized CPU_CntTrailZeros() avoids having to offset the number of returned
* trailing zeros by the difference in CPU data size and 32-bit data value bits.
*
* (b) For CPU_CntTrailZeros32()'s C implementation, the final conditional statement
* calculates 'val's number of trailing zeros based on CPU_CntTrailZeros32()'s
* 32-bit return data size & 'val's calculated number of lead zeros ONLY if the
* initial 'val' is non-'0' :
*
* if (val != 0u) {
* nbr_trail_zeros = ((CPU_WORD_SIZE_32 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros;
* } else {
* nbr_trail_zeros = nbr_lead_zeros;
* }
*
* Therefore, initially validating all non-'0' values avoids having to conditionally
* execute the final 'if' statement.
*********************************************************************************************************
*/
#if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_32)
CPU_DATA CPU_CntTrailZeros32 (CPU_INT32U val)
{
#if (!((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_32)))
CPU_INT32U val_bit_mask;
CPU_DATA nbr_lead_zeros;
#endif
CPU_DATA nbr_trail_zeros;
if (val == 0u) { /* Rtn ALL val bits as zero'd (see Note #3). */
return ((CPU_DATA)(CPU_WORD_SIZE_32 * DEF_OCTET_NBR_BITS));
}
/* ------------------ ASM-OPTIMIZED ------------------- */
#if ((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_32))
nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val);
#else /* ------------------- C-OPTIMIZED -------------------- */
val_bit_mask = val & ((CPU_INT32U)~val + 1u); /* Zero/clr all bits EXCEPT least-sig set bit. */
nbr_lead_zeros = CPU_CntLeadZeros32(val_bit_mask); /* Cnt nbr lead 0s. */
/* Calc nbr trail 0s = (nbr val bits - 1) - nbr lead 0s.*/
nbr_trail_zeros = ((CPU_DATA)((CPU_WORD_SIZE_32 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros);
#endif
return (nbr_trail_zeros);
}
#endif
/*
*********************************************************************************************************
* CPU_CntTrailZeros64()
*
* Description : Count the number of contiguous, least-significant, trailing zero bits in a 64-bit data value.
*
* Argument(s) : val Data value to count trailing zero bits.
*
* Return(s) : Number of contiguous, least-significant, trailing zero bits in 'val'.
*
* Note(s) : (1) Supports 64-bit values :
*
* b63 b62 b61 b60 b59 ... b02 b01 b00 # Trailing Zeros
* --- --- --- --- --- --- --- --- ----------------
* x x x x x x x 1 0
* x x x x x x 1 0 1
* x x x x x 1 0 0 2
* : : : : : : : : :
* : : : : : : : : :
* x x x x 1 0 0 0 59
* x x x 1 0 0 0 0 60
* x x 1 0 0 0 0 0 61
* x 1 0 0 0 0 0 0 62
* 1 0 0 0 0 0 0 0 63
* 0 0 0 0 0 0 0 0 64
*
*
* (2) For non-zero values, the returned number of contiguous, least-significant, trailing
* zero bits is also equivalent to the bit position of the least-significant set bit.
*
* (3) 'val' SHOULD be validated for non-'0' PRIOR to all other counting zero calculations :
*
* (a) For assembly-optimized implementations, CPU_CntTrailZeros() returns 'val's
* number of trailing zeros via CPU's native data size, 'CPU_CFG_DATA_SIZE'.
* If the returned number of zeros exceeds CPU_CntTrailZeros64()'s 64-bit return
* data size, then the returned number of zeros must be offset by the difference
* between CPU_CntTrailZeros()'s & CPU_CntTrailZeros64()'s return data size :
*
* nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val);
* if (nbr_trail_zeros > (CPU_WORD_SIZE_64 * DEF_OCTET_NBR_BITS)) {
* nbr_trail_zeros -= (CPU_CFG_DATA_SIZE - CPU_WORD_SIZE_64) * DEF_OCTET_NBR_BITS;
* }
*
* However, this ONLY occurs for an initial 'val' of '0' since all non-'0' 64-bit
* values would return a number of trailing zeros less than or equal to 64 bits.
*
* Therefore, initially validating all non-'0' values prior to calling assembly-
* optimized CPU_CntTrailZeros() avoids having to offset the number of returned
* trailing zeros by the difference in CPU data size and 64-bit data value bits.
*
* (b) For CPU_CntTrailZeros64()'s C implementation, the final conditional statement
* calculates 'val's number of trailing zeros based on CPU_CntTrailZeros64()'s
* 64-bit return data size & 'val's calculated number of lead zeros ONLY if the
* initial 'val' is non-'0' :
*
* if (val != 0u) {
* nbr_trail_zeros = ((CPU_WORD_SIZE_64 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros;
* } else {
* nbr_trail_zeros = nbr_lead_zeros;
* }
*
* Therefore, initially validating all non-'0' values avoids having to conditionally
* execute the final 'if' statement.
*********************************************************************************************************
*/
#if (CPU_CFG_DATA_SIZE_MAX >= CPU_WORD_SIZE_64)
CPU_DATA CPU_CntTrailZeros64 (CPU_INT64U val)
{
#if (!((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_64)))
CPU_INT64U val_bit_mask;
CPU_DATA nbr_lead_zeros;
#endif
CPU_DATA nbr_trail_zeros;
if (val == 0u) { /* Rtn ALL val bits as zero'd (see Note #3). */
return ((CPU_DATA)(CPU_WORD_SIZE_64 * DEF_OCTET_NBR_BITS));
}
/* ------------------ ASM-OPTIMIZED ------------------- */
#if ((defined(CPU_CFG_TRAIL_ZEROS_ASM_PRESENT)) && \
(CPU_CFG_DATA_SIZE >= CPU_WORD_SIZE_64))
nbr_trail_zeros = CPU_CntTrailZeros((CPU_DATA)val);
#else /* ------------------- C-OPTIMIZED -------------------- */
val_bit_mask = val & ((CPU_INT64U)~val + 1u); /* Zero/clr all bits EXCEPT least-sig set bit. */
nbr_lead_zeros = CPU_CntLeadZeros64(val_bit_mask); /* Cnt nbr lead 0s. */
/* Calc nbr trail 0s = (nbr val bits - 1) - nbr lead 0s.*/
nbr_trail_zeros = ((CPU_DATA)((CPU_WORD_SIZE_64 * DEF_OCTET_NBR_BITS) - 1u) - nbr_lead_zeros);
#endif
return (nbr_trail_zeros);
}
#endif
/*
*********************************************************************************************************
* CRCUtil_PopCnt_32()
*
* Description : Compute population count (hamming weight) for value (number of bits set).
*
* Argument(s) : value Value to compute population count on.
*
*
* Return(s) : value's population count.
*
* Note(s) : (1) Algorithm taken from en.wikipedia.org/wiki/Hamming_weight
*********************************************************************************************************
*/
CPU_INT08U CPU_PopCnt32 (CPU_INT32U value)
{
CPU_INT32U even_cnt;
CPU_INT32U odd_cnt;
CPU_INT32U result;
odd_cnt = (value >> 1u) & CRC_UTIL_POPCNT_MASK01010101_32; /* 2-bits pieces. */
result = value - odd_cnt; /* Same result as result=odd_cnt+(value & 0x55555555). */
even_cnt = result & CRC_UTIL_POPCNT_MASK00110011_32; /* 4-bits pieces. */
odd_cnt = (result >> 2u) & CRC_UTIL_POPCNT_MASK00110011_32;
result = even_cnt + odd_cnt;
even_cnt = result & CRC_UTIL_POPCNT_MASK00001111_32; /* 8-bits pieces. */
odd_cnt = (result >> 4u) & CRC_UTIL_POPCNT_MASK00001111_32;
result = even_cnt + odd_cnt;
result = (result * CRC_UTIL_POPCNT_POWERSOF256_32) >> 24u;
return ((CPU_INT08U)result);
}
/*
*********************************************************************************************************
* CPU_StatReset()
*
* Description : Reset all performance monitors.
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Note(s) : Critical section provided by caller.
*********************************************************************************************************
*/
#if (CPU_CFG_PERF_MON_EN == DEF_ENABLED)
void CPU_StatReset (void)
{
#ifdef CPU_CFG_INT_DIS_MEAS_EN
CPU_IntDisMeasMax_cnts = 0u;
#endif
}
#endif
/*
*********************************************************************************************************
*********************************************************************************************************
* LOCAL FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* CPU_NameInit()
*
* Description : Initialize CPU Name.
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
#if (CPU_CFG_NAME_EN == DEF_ENABLED)
static void CPU_NameInit (void)
{
CPU_NameClr();
}
#endif
/*
*********************************************************************************************************
* CPU_TS_Init()
*
* Description : (1) Initialize CPU timestamp :
*
* (a) Initialize/start CPU timestamp timer See Note #1
* (b) Initialize CPU timestamp controls
*
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Note(s) : (1) The following initialization MUST be sequenced as follows :
*
* (a) CPU_TS_TmrFreq_Hz MUST be initialized prior to CPU_TS_TmrInit()
* (b) CPU_TS_TmrInit() SHOULD precede calls to all other CPU timestamp functions;
* otherwise, invalid time measurements may be calculated/
* returned.
*
* See also 'CPU_Init() Note #3a'.
*********************************************************************************************************
*/
#if ((CPU_CFG_TS_EN == DEF_ENABLED) || \
(CPU_CFG_TS_TMR_EN == DEF_ENABLED))
static void CPU_TS_Init (void)
{
#if (((CPU_CFG_TS_32_EN == DEF_ENABLED ) && \
(CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)) || \
((CPU_CFG_TS_64_EN == DEF_ENABLED ) && \
(CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64)))
CPU_TS_TMR ts_tmr_cnts;
#endif
/* ----------------- INIT CPU TS TMR ------------------ */
#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
CPU_TS_TmrFreq_Hz = 0u; /* Init/clr ts tmr freq (see Note #1a). */
CPU_TS_TmrInit(); /* Init & start ts tmr (see Note #1b). */
#endif
/* ------------------- INIT CPU TS -------------------- */
#if (((CPU_CFG_TS_32_EN == DEF_ENABLED ) && \
(CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32)) || \
((CPU_CFG_TS_64_EN == DEF_ENABLED ) && \
(CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64)))
ts_tmr_cnts = CPU_TS_TmrRd(); /* Get init ts tmr val (in ts tmr cnts). */
#endif
#if ((CPU_CFG_TS_32_EN == DEF_ENABLED) && \
(CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_32))
CPU_TS_32_Accum = 0u; /* Init 32-bit accum'd ts. */
CPU_TS_32_TmrPrev = ts_tmr_cnts; /* Init 32-bit ts prev tmr val. */
#endif
#if ((CPU_CFG_TS_64_EN == DEF_ENABLED) && \
(CPU_CFG_TS_TMR_SIZE < CPU_WORD_SIZE_64))
CPU_TS_64_Accum = 0u; /* Init 64-bit accum'd ts. */
CPU_TS_64_TmrPrev = ts_tmr_cnts; /* Init 64-bit ts prev tmr val. */
#endif
}
#endif
/*
*********************************************************************************************************
* CPU_IntDisMeasInit()
*
* Description : (1) Initialize interrupts disabled time measurements feature :
*
* (a) Initialize interrupts disabled time measurement controls
* (b) Calculate interrupts disabled time measurement overhead
*
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Note(s) : (2) CPU_IntDisMeasInit() SHOULD precede ALL calls to CPU_CRITICAL_ENTER()/CPU_CRITICAL_EXIT()
* & other CPU interrupts disabled time measurement functions; otherwise, invalid interrupts
* disabled time measurements may be calculated/returned.
*
* See also 'CPU_Init() Note #3b'.
*
* (3) (a) (1) Interrupts disabled time measurement overhead performed multiple times to calculate
* a rounded average with better accuracy, hopefully of +/- one timer count.
*
* (2) However, a single overhead time measurement is recommended, even for instruction-
* cache-enabled CPUs, since critical sections are NOT typically called within
* instruction-cached loops. Thus a single non-cached/non-averaged time measurement
* is a more realistic overhead for the majority of non-cached interrupts disabled
* time measurements.
*
* (b) Interrupts MUST be disabled while measuring the interrupts disabled time measurement
* overhead; otherwise, overhead measurements could be interrupted which would incorrectly
* calculate an inflated overhead time which would then incorrectly calculate deflated
* interrupts disabled times.
*********************************************************************************************************
*/
#ifdef CPU_CFG_INT_DIS_MEAS_EN
static void CPU_IntDisMeasInit (void)
{
CPU_TS_TMR time_meas_tot_cnts;
CPU_INT16U i;
CPU_SR_ALLOC();
/* ----------- INIT INT DIS TIME MEAS CTRLS ----------- */
CPU_IntDisMeasCtr = 0u;
CPU_IntDisNestCtr = 0u;
CPU_IntDisMeasStart_cnts = 0u;
CPU_IntDisMeasStop_cnts = 0u;
CPU_IntDisMeasMaxCur_cnts = 0u;
CPU_IntDisMeasMax_cnts = 0u;
CPU_IntDisMeasOvrhd_cnts = 0u;
/* ----------- CALC INT DIS TIME MEAS OVRHD ----------- */
time_meas_tot_cnts = 0u;
CPU_INT_DIS(); /* Ints MUST be dis'd for ovrhd calc (see Note #3b). */
for (i = 0u; i < CPU_CFG_INT_DIS_MEAS_OVRHD_NBR; i++) {
CPU_IntDisMeasMaxCur_cnts = 0u;
CPU_IntDisMeasStart(); /* Perform multiple consecutive start/stop time meas's */
CPU_IntDisMeasStop();
time_meas_tot_cnts += CPU_IntDisMeasMaxCur_cnts; /* ... & sum time meas max's ... */
}
/* ... to calc avg time meas ovrhd (see Note #3a). */
CPU_IntDisMeasOvrhd_cnts = (time_meas_tot_cnts + (CPU_CFG_INT_DIS_MEAS_OVRHD_NBR / 2u))
/ CPU_CFG_INT_DIS_MEAS_OVRHD_NBR;
CPU_IntDisMeasMaxCur_cnts = 0u; /* Reset max ints dis'd times. */
CPU_IntDisMeasMax_cnts = 0u;
CPU_INT_EN();
}
#endif
/*
*********************************************************************************************************
* CPU_IntDisMeasMaxCalc()
*
* Description : Calculate maximum interrupts disabled time.
*
* Argument(s) : time_tot_cnts Total interrupt disabled time, in timer counts.
*
* Return(s) : Maximum interrupts disabled time (in CPU timestamp timer counts).
*
* Note(s) : (1) (a) The total amount of time interrupts are disabled by system &/or application code
* during critical sections is calculated by the following equations :
*
* (1) time = [ time - time ] - time
* interrupts [ stop start ] total meas
* disabled [ meas meas ] ovrhd
* (via application)
*
*
* (2) time = time + time
* total meas start meas stop meas
* ovrhd ovrhd ovrhd
*
*
* where
*
* time time interrupts are disabled between
* interrupts first critical section enter &
* disabled last critical section exit minus
* (via application) time measurement overhead
*
* time time of disable interrupts start time
* start measurement (in timer counts)
* meas
*
* time time of disable interrupts stop time
* stop measurement (in timer counts)
* meas
*
* time total overhead time to start/stop disabled
* total meas interrupts time measurements (in timer
* ovrhd counts)
*
* time total overhead time after getting start
* start meas time until end of start measurement
* ovrhd function (in timer counts)
*
* time total overhead time from beginning of stop
* stop meas measurement function until after getting
* ovrhd stop time (in timer counts)
*
*
* (b) To expedite & reduce interrupts disabled time measurement overhead, the final
* calculations to subtract the interrupts disabled time measurement overhead is
* performed asynchronously in API functions.
*
* See also 'CPU_IntDisMeasStop() Note #1b2'.
*
* (c) The amount of time interrupts are disabled is calculated by either of the
* following equations :
*
* (1) Interrupts disabled time = Number timer counts * Timer period
*
* where
*
* Number timer counts Number of timer counts measured
* Timer period Timer's period in some units of
* (fractional) seconds
* Interrupts disabled time Amount of time interrupts are
* disabled, in same units of
* (fractional) seconds as the
* Timer period
*
* Number timer counts
* (2) Interrupts disabled time = ---------------------
* Timer frequency
*
* where
*
* Number timer counts Number of timer counts measured
* Timer frequency Timer's frequency in some units
* of counts per second
* Interrupts disabled time Amount of time interrupts are
* disabled, in seconds
*
* See also 'cpu_core.h FUNCTION PROTOTYPES CPU_TS_TmrRd() Note #2c'
* & 'cpu_core.h FUNCTION PROTOTYPES CPU_TSxx_to_uSec() Note #2'.
*
* (2) Although it is not typical, it is possible for an interrupts disabled time
* measurement to be less than the interrupts disabled time measurement overhead;
* especially if the overhead was calculated with a single, non-cached measurement
* & critical sections are called within instruction-cached loops.
*********************************************************************************************************
*/
#ifdef CPU_CFG_INT_DIS_MEAS_EN
static CPU_TS_TMR CPU_IntDisMeasMaxCalc (CPU_TS_TMR time_tot_cnts)
{
CPU_TS_TMR time_max_cnts;
time_max_cnts = time_tot_cnts;
if (time_max_cnts > CPU_IntDisMeasOvrhd_cnts) { /* If max ints dis'd time > ovrhd time, ... */
time_max_cnts -= CPU_IntDisMeasOvrhd_cnts; /* ... adj max ints dis'd time by ovrhd time; ... */
} else { /* ... else max ints dis'd time < ovrhd time, ... */
time_max_cnts = 0u; /* ... clr max ints dis'd time (see Note #2). */
}
return (time_max_cnts);
}
#endif