def subsignalsection_legalizer(optree, input_prec_solver=default_prec_solver): if is_fixed_point(optree.get_precision()) and is_fixed_point( optree.get_input(0).get_precision()): return legalize_fixed_point_subselection( optree, input_prec_solver=input_prec_solver) else: return optree
def solve_format_ArithOperation( optree, integer_size_func=lambda lhs_prec, rhs_prec: None, frac_size_func=lambda lhs_prec, rhs_prec: None, signed_func=lambda lhs, lhs_prec, rhs, rhs_prec: False): """ determining fixed-point format for a generic 2-op arithmetic operation (e.g. Multiplication, Addition, Subtraction) """ lhs = optree.get_input(0) rhs = optree.get_input(1) lhs_precision = lhs.get_precision() rhs_precision = rhs.get_precision() abstract_operation = (lhs_precision is ML_Integer) and (rhs_precision is ML_Integer) if abstract_operation: return ML_Integer if lhs_precision is ML_Integer: cst_eval = evaluate_cst_graph(lhs, input_prec_solver=solve_format_rec) lhs_precision = solve_format_Constant(Constant(cst_eval)) if rhs_precision is ML_Integer: cst_eval = evaluate_cst_graph(rhs, input_prec_solver=solve_format_rec) rhs_precision = solve_format_Constant(Constant(cst_eval)) if is_fixed_point(lhs_precision) and is_fixed_point(rhs_precision): # +1 for carry overflow int_size = integer_size_func(lhs_precision, rhs_precision) frac_size = frac_size_func(lhs_precision, rhs_precision) is_signed = signed_func(lhs, lhs_precision, rhs, rhs_precision) return fixed_point(int_size, frac_size, signed=is_signed) else: return optree.get_precision()
def add_signed_predicate(lhs, lhs_prec, rhs, rhs_prec): """ determine whether subtraction output on a signed or unsigned format """ if is_fixed_point(lhs_prec) and is_fixed_point(rhs_prec): default = lhs_prec.get_signed() or rhs_prec.get_signed() else: default = True return addsub_signed_predicate(lhs, lhs_prec, rhs, rhs_prec, op=operator.__add__, default=default)
def test_format_equality(format0, format1): if format0 == format1: return True elif is_fixed_point(format0) and is_fixed_point(format1): return \ (format0.get_integer_size() == format1.get_integer_size()) and \ (format0.get_frac_size() == format1.get_frac_size()) and \ (format0.get_signed() == format1.get_signed()) return False
def propagate_format_to_input(new_format, optree, input_index_list): """ Propgate new_format to @p optree's input whose index is listed in @p input_index_list """ for op_index in input_index_list: op_input = optree.get_input(op_index) if op_input.get_precision() is None: op_input.set_precision(new_format) index_list = does_node_propagate_format(op_input) propagate_format_to_input(new_format, op_input, index_list) elif not test_format_equality(new_format, op_input.get_precision()): if is_constant(op_input): if not is_fixed_point(new_format): Log.report( Log.Error, "format {} during propagation to input {} of {} is not a fixed-point format", new_format, op_input, optree) elif format_does_fit(op_input, new_format): Log.report( Log.Info, "Simplify Constant Conversion {} to larger Constant: {}", op_input.get_str(display_precision=True) if Log.is_level_enabled(Log.Info) else "", str(new_format)) new_input = op_input.copy() new_input.set_precision(new_format) optree.set_input(op_index, new_input) else: Log.report( Log.Error, "Constant is about to be reduced to a too constrained format: {}", op_input.get_str(display_precision=True) if Log.is_level_enabled(Log.Error) else "") else: new_input = Conversion(op_input, precision=new_format) optree.set_input(op_index, new_input)
def solve_format_SubSignalSelection(optree, format_solver): """ Dummy legalization of SubSignalSelection operation node """ if optree.get_precision() is None: select_input = optree.get_input(0) input_prec = select_input.get_precision() inf_index = evaluate_cst_graph(optree.get_inf_index(), input_prec_solver=format_solver) sup_index = evaluate_cst_graph(optree.get_sup_index(), input_prec_solver=format_solver) if is_fixed_point(input_prec): frac_size = input_prec.get_frac_size() - inf_index integer_size = input_prec.get_integer_size() - ( input_prec.get_bit_size() - 1 - sup_index) if frac_size + integer_size <= 0: Log.report( Log.Error, "range determined for SubSignalSelection format [{}:{}] has negative size: {}, optree is {}", integer_size, frac_size, integer_size + frac_size, optree) return fixed_point(integer_size, frac_size) else: return ML_StdLogicVectorFormat(sup_index - inf_index + 1) else: return optree.get_precision()
def fixed_point_position_legalizer(optree, input_prec_solver=default_prec_solver): """ Legalize a FixedPointPosition node to a constant """ assert isinstance(optree, FixedPointPosition) fixed_input = optree.get_input(0) fixed_precision = input_prec_solver(fixed_input) if not is_fixed_point(fixed_precision): Log.report( Log.Error, "in fixed_point_position_legalizer: precision of {} should be fixed-point but is {}" .format(fixed_input, fixed_precision)) position = optree.get_input(1).get_value() align = optree.get_align() value_computation_map = { FixedPointPosition.FromLSBToLSB: position, FixedPointPosition.FromMSBToLSB: fixed_precision.get_bit_size() - 1 - position, FixedPointPosition.FromPointToLSB: fixed_precision.get_frac_size() + position, FixedPointPosition.FromPointToMSB: fixed_precision.get_integer_size() - position } cst_value = value_computation_map[align] # display value Log.report( Log.LogLevel("FixedPoint"), "fixed-point position {tag} has been resolved to {value}".format( tag=optree.get_tag(), value=cst_value)) result = Constant(cst_value, precision=ML_Integer) forward_attributes(optree, result) return result
def solve_format_CLZ(optree): """ Legalize CountLeadingZeros precision Args: optree (CountLeadingZeros): input node Returns: ML_Format: legal format for CLZ """ assert isinstance(optree, CountLeadingZeros) op_input = optree.get_input(0) input_precision = op_input.get_precision() if is_fixed_point(input_precision): if input_precision.get_signed(): Log.report(Log.Warning , "signed format in solve_format_CLZ") # +1 for carry overflow int_size = int(sollya.floor(sollya.log2(input_precision.get_bit_size()))) + 1 frac_size = 0 return fixed_point( int_size, frac_size, signed=False ) else: Log.report(Log.Warning , "unsupported format in solve_format_CLZ") return optree.get_precision()
def generate_random_fixed_value(precision): """ Generate a random fixed-point value of format precision """ assert is_fixed_point(precision) # fixed point format lo_value = precision.get_min_value() hi_value = precision.get_max_value() value = random.uniform(lo_value, hi_value) rounded_value = precision.round_sollya_object(value) return rounded_value
def solve_format_shift(optree): """ Legalize shift node """ assert isinstance(optree, BitLogicRightShift) or isinstance( optree, BitLogicLeftShift) shift_input = optree.get_input(0) shift_input_precision = shift_input.get_precision() shift_amount = optree.get_input(1) shift_amount_prec = shift_amount.get_precision() if is_fixed_point(shift_amount_prec): sa_range = evaluate_range(shift_amount) if sollya.inf(sa_range) < 0: Log.report( Log.Error, "shift amount of {} may be negative {}\n".format( optree, sa_range)) if is_fixed_point(shift_input_precision): return shift_input_precision else: return optree.get_precision()
def format_does_fit(cst_optree, new_format): """ Test if @p cst_optree fits into the precision @p new_format """ assert is_constant(cst_optree) assert is_fixed_point(new_format) min_format = solve_format_Constant(cst_optree) sign_bias = 1 if (new_format.get_signed() and not min_format.get_signed()) \ else 0 return (new_format.get_integer_size() - sign_bias) >= \ min_format.get_integer_size() and \ new_format.get_frac_size() >= min_format.get_frac_size() and \ (new_format.get_signed() or not min_format.get_signed())
def solve_format_bitwise_op(optree): """ legalize format of bitwise logical operation Args: optree (ML_Operation): bitwise logical input node Returns: (ML_Format): legal format for input node """ lhs = optree.get_input(0) rhs = optree.get_input(1) lhs_precision = lhs.get_precision() rhs_precision = rhs.get_precision() if is_fixed_point(lhs_precision) and is_fixed_point(rhs_precision): assert(lhs_precision.get_integer_size() == rhs_precision.get_integer_size()) assert(lhs_precision.get_frac_size() == rhs_precision.get_frac_size()) return lhs_precision else: return optree.get_precision()
def format_does_fit(cst_optree, new_format): """ Test if @p cst_optree fits into the precision @p new_format """ assert is_constant(cst_optree) assert is_fixed_point(new_format) # min_format is a dummy format used simply to check # if constant fits in new_format min_format = determine_minimal_fixed_format_cst(cst_optree.get_value()) sign_bias = 1 if (new_format.get_signed() and not min_format.get_signed()) \ else 0 return (new_format.get_integer_size() - sign_bias) >= \ min_format.get_integer_size() and \ new_format.get_frac_size() >= min_format.get_frac_size() and \ (new_format.get_signed() or not min_format.get_signed())
def generate_bitfield_extraction(target_format, input_node, lo_index, hi_index): shift = lo_index mask_size = hi_index - lo_index + 1 input_format = input_node.get_precision().get_base_format() if is_fixed_point(input_format) and is_fixed_point(target_format): frac_size = target_format.get_frac_size() int_size = input_format.get_bit_size() - frac_size cast_format = ML_Custom_FixedPoint_Format(int_size, frac_size, signed=False) else: cast_format = None # 1st step: shifting the input node the right amount shifted_node = input_node if shift == 0 else BitLogicRightShift( input_node, Constant(shift, precision=ML_Int32), precision=input_format) raw_format = ML_Custom_FixedPoint_Format(input_format.get_bit_size(), 0, signed=False) # 2nd step: masking the input node # TODO/FIXME: check thast mask does not overflow or wrap-around masked_node = BitLogicAnd(TypeCast(shifted_node, precision=raw_format), Constant((2**mask_size - 1), precision=raw_format), precision=raw_format) if not cast_format is None: casted_node = TypeCast(masked_node, precision=cast_format) else: casted_node = masked_node converted_node = Conversion(casted_node, precision=target_format) return converted_node
def largest_format(format0, format1): if is_fixed_point(format0) and is_fixed_point(format1): # unsigned_int_size = format0.get_integer_size() if format1.get_signed() \ else format1.get_integer_size() signed_int_size = format1.get_integer_size() if format1.get_signed() \ else format0.get_integer_size() xor_signed = (format0.get_signed() != format1.get_signed()) and \ (unsigned_int_size >= signed_int_size) int_size = max(format0.get_integer_size(), format1.get_integer_size()) + (1 if xor_signed else 0) frac_size = max(format0.get_frac_size(), format1.get_frac_size()) return fixed_point(int_size, frac_size, signed=format0.get_signed() or format1.get_signed()) elif format0 is None or format0 is ML_Integer: # TODO: fix for abstract format return format1 elif format1 is None or format1 is ML_Integer: # TODO: fix for abstract format return format0 elif format0.get_bit_size() == format1.get_bit_size(): return format0 else: Log.report(Log.Error, "unable to determine largest format") raise NotImplementedError
def solve_format_SubSignalSelection(optree): """ Dummy legalization of SubSignalSelection operation node """ if optree.get_precision() is None: select_input = optree.get_input(0) input_prec = select_input.get_precision() inf_index = evaluate_cst_graph(optree.get_inf_index(), input_prec_solver=solve_format_rec) sup_index = evaluate_cst_graph(optree.get_sup_index(), input_prec_solver=solve_format_rec) if is_fixed_point(input_prec): frac_size = input_prec.get_frac_size() - inf_index integer_size = input_prec.get_integer_size() - ( input_prec.get_bit_size() - 1 - sup_index) return fixed_point(integer_size, frac_size) else: return ML_StdLogicVectorFormat(sup_index - inf_index + 1) else: return optree.get_precision()