Index: cmake/modules/InitFixedPointBits.cmake =================================================================== --- cmake/modules/InitFixedPointBits.cmake +++ cmake/modules/InitFixedPointBits.cmake @@ -60,26 +60,170 @@ set(ULACCUM_IBIT 32) endif() -# Checks for each bit size +# Checks for each bit size defined in clause 6.2.6.3 + +# Cannot go below the minimum number of fractional and integral bits for the +# various types specified in clause 7.18a.3. +function(assert_min_bits macro min_bits) + set("macro_name" ${macro}) + set("macro_val" ${${macro}}) + if(${macro_val} LESS ${min_bits}) + message(FATAL_ERROR "The minimum value allowed for ${macro_name} is ${min_bits}. " + "${macro_val} was provided.") + endif() +endfunction() + +assert_min_bits(SFRACT_FBIT 7) +assert_min_bits(FRACT_FBIT 15) +assert_min_bits(LFRACT_FBIT 23) +assert_min_bits(USFRACT_FBIT 7) +assert_min_bits(UFRACT_FBIT 15) +assert_min_bits(ULFRACT_FBIT 23) + +assert_min_bits(SACCUM_FBIT 7) +assert_min_bits(ACCUM_FBIT 15) +assert_min_bits(LACCUM_FBIT 23) +assert_min_bits(USACCUM_FBIT 7) +assert_min_bits(UACCUM_FBIT 15) +assert_min_bits(ULACCUM_FBIT 23) + +assert_min_bits(SACCUM_IBIT 4) +assert_min_bits(ACCUM_IBIT 4) +assert_min_bits(LACCUM_IBIT 4) +assert_min_bits(USACCUM_IBIT 4) +assert_min_bits(UACCUM_IBIT 4) +assert_min_bits(ULACCUM_IBIT 4) + # Each unsigned fract type has either the same number of fractional bits as, # or one more fractional bit than, its corresponding signed fract type. -# TODO: Implement remaining checks in clause 6.2.6.3. -function(check_diff_at_most_1 sfract_fbits ufract_fbits) - if(sfract_fbits EQUAL ufract_fbits) - return() - endif() +function(assert_fract_diff sfract_fbits ufract_fbits) math(EXPR diff "${ufract_fbits} - ${sfract_fbits}") - if(diff EQUAL 1) - return() + if(NOT((${diff} EQUAL 0) OR (${diff} EQUAL 1))) + message(FATAL_ERROR "Each unsigned fract type must have either the same number of " + "fractional bits as, or one more fractional bit than, its corresponding " + "signed fract type.") + endif() +endfunction() + +assert_fract_diff(${SFRACT_FBIT} ${USFRACT_FBIT}) +assert_fract_diff(${FRACT_FBIT} ${UFRACT_FBIT}) +assert_fract_diff(${LFRACT_FBIT} ${ULFRACT_FBIT}) + +# When arranged in order of increasing rank (see 6.3.1.3a), the number of +# fractional bits is nondecreasing for each of the following sets of +# fixed-point types: +# - signed fract types +# - unsigned fract types +# - signed accum types +# - unsigned accum types. +function(assert_non_decreasing short_type_bits middle_type_bits long_type_bits + type_family bit_type) + if((${short_type_bits} GREATER ${middle_type_bits}) OR + (${middle_type_bits} GREATER ${long_type_bits})) + message(FATAL_ERROR "The number of ${bit_type} bits in ${type_family} types must be " + "non decreasing in order of increasing rank.") + endif() +endfunction() + +assert_non_decreasing(${SFRACT_FBIT} ${FRACT_FBIT} ${LFRACT_FBIT} "signed _Fract" "fractional") +assert_non_decreasing(${USFRACT_FBIT} ${UFRACT_FBIT} ${ULFRACT_FBIT} "unsigned _Fract" "fractional") +assert_non_decreasing(${SACCUM_FBIT} ${ACCUM_FBIT} ${LACCUM_FBIT} "signed _Accum" "fractional") +assert_non_decreasing(${USACCUM_FBIT} ${UACCUM_FBIT} ${ULACCUM_FBIT} "unsigned _Accum" "fractional") + +# When arranged in order of increasing rank (see 6.3.1.3a), the number of +# integral bits is nondecreasing for each of the following sets of +# fixed-point types: +# - signed accum types +# - unsigned accum types. +assert_non_decreasing(${SACCUM_IBIT} ${ACCUM_IBIT} ${LACCUM_IBIT} "signed _Accum" "integral") +assert_non_decreasing(${USACCUM_IBIT} ${UACCUM_IBIT} ${ULACCUM_IBIT} "unsigned _Accum" "integral") + +# Each signed accum type has at least as many integral bits as its +# corresponding unsigned accum type. +function(assert_integral_diff saccum_ibits uaccum_ibits) + if(${saccum_ibits} LESS ${uaccum_ibits}) + message(FATAL_ERROR "Each signed accum type must have at least as many integral bits as its " + "corresponding unsigned accum type.") + endif() +endfunction() + +assert_integral_diff(${SACCUM_IBIT} ${USACCUM_IBIT}) +assert_integral_diff(${ACCUM_IBIT} ${UACCUM_IBIT}) +assert_integral_diff(${LACCUM_IBIT} ${ULACCUM_IBIT}) + +# The following checks are not required, bit recommended to promote consistency +# amongst implementations. + +# The signed long _Fract type has at least 31 fractional bits +if(${LFRACT_FBIT} LESS 31) + message(WARNING "It is recommended that the signed long _Fract type has at least 31 " + "fractional bits") +endif() + +# Each accum type has at least 8 integral bits +function(check_accum_ibits accum_ibits) + if(${accum_ibits} LESS 8) + message(WARNING "It is recommended that each accum type has at least 8 integral bits") + endif() +endfunction() + +check_accum_ibits(${SACCUM_IBIT}) +check_accum_ibits(${ACCUM_IBIT}) +check_accum_ibits(${LACCUM_IBIT}) +check_accum_ibits(${USACCUM_IBIT}) +check_accum_ibits(${UACCUM_IBIT}) +check_accum_ibits(${ULACCUM_IBIT}) + +# Each unsigned accum type has the same number of fractional bits as its corresponding +# unsigned fract type. +function(check_unsigned_fract_diff uaccum_fbits ufract_fbits) + if(NOT(${uaccum_fbits} EQUAL ${ufract_fbits})) + message(WARNING "It is recommended that each unsigned accum type have the same " + "number of fractional bits as its corresponding unsigned fract type.") + endif() +endfunction() + +check_unsigned_fract_diff(${USACCUM_FBIT} ${USFRACT_FBIT}) +check_unsigned_fract_diff(${UACCUM_FBIT} ${UFRACT_FBIT}) +check_unsigned_fract_diff(${ULACCUM_FBIT} ${ULFRACT_FBIT}) + +# Each signed accum type has the same number of fractional bits as either its +# corresponding signed fract type or its corresponding unsigned fract type. +function(check_signed_fract_diff saccum_fbits sfract_fbits) + if(NOT(${saccum_fbits} EQUAL ${sfract_fbits})) + message(WARNING "It is recommended that each unsigned accum type have the same " + "number of fractional bits as its corresponding unsigned fract type.") + endif() +endfunction() + +# Not part of N1169 but can help with some optimizations by not having to mask or reset +# any padding bits on operations that involve reading from them. For example, if a short +# _Accum type has 7 fractional bits, 4 integral bits, 1 sign bit, and is stored in a 16 +# bit integer, there will be 4 padding bits left in the int. When performing normal +# arithmetic operations like addition, we can normally ignore these bits, but for operations +# that involve reading the entire bit width like equality, these padding bits will be read. +# They will need to be ignored either by zeroing them out if the fixed point type is +# unsigned, or extending the sign with a shift left then shift right into the padding. +# +# Having no padding can allow for ignoring these instructions on _Accum types. This won't +# apply to _Fract types since they normally have padding by having no integral part. +# One can technically extend the _Fract FBITS to take up the whole integer width to avoid +# padding, but this is not recommended since they may not have the same number of fractional +# bits for their corresponding _Accum types. +function(check_bits_fill_int ibits fbits sign bit_width) + math(EXPR num_bits "${ibits} + ${fbits} + ${sign}") + if(NOT(${num_bits} EQUAL ${bit_width})) + message(WARNING "It is recommended that the number of fractional, integral, " + "and sign bits fill the whole width of the integer for some optimizations.") endif() - message(FATAL_ERROR "Each unsigned fract type has either the same number of " - "fractional bits as, or one more fractional bit than, its corresponding " - "signed fract type.") endfunction() -check_diff_at_most_1(${SFRACT_FBIT} ${USFRACT_FBIT}) -check_diff_at_most_1(${FRACT_FBIT} ${UFRACT_FBIT}) -check_diff_at_most_1(${LFRACT_FBIT} ${ULFRACT_FBIT}) +check_bits_fill_int(${SACCUM_IBIT} ${SACCUM_FBIT} 1 16) +check_bits_fill_int(${ACCUM_IBIT} ${ACCUM_FBIT} 1 32) +check_bits_fill_int(${LACCUM_IBIT} ${LACCUM_FBIT} 1 64) +check_bits_fill_int(${USACCUM_IBIT} ${USACCUM_FBIT} 0 16) +check_bits_fill_int(${UACCUM_IBIT} ${UACCUM_FBIT} 0 32) +check_bits_fill_int(${ULACCUM_IBIT} ${ULACCUM_FBIT} 0 64) # Configure the FixedPoint.h file. configure_file(