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_rec(self, optree): """ Recursively legalize formats from @p optree, using memoization_map to store resolved results """ if optree in self.memoization_map: return self.memoization_map[optree] elif isinstance(optree, ML_LeafNode): new_format = optree.get_precision() if isinstance(optree, Constant): new_format = solve_format_Constant(optree, input_prec_solver=self) Log.report( Log.Verbose, "new format {} determined for Constant {}", str(new_format), optree.get_str(display_precision=True) if Log.is_level_enabled(Log.Verbose) else "") # updating optree format #optree.set_precision(new_format) format_set_if_undef(optree, new_format) self.memoization_map[optree] = new_format return optree.get_precision() elif isinstance(optree, Statement): for op_input in optree.get_inputs(): self.solve_format_rec(op_input) self.memoization_map[optree] = None return None elif isinstance(optree, ReferenceAssign): dst = optree.get_input(0) src = optree.get_input(1) src_precision = self.solve_format_rec(src) format_set_if_undef(dst, src_precision) elif solve_skip_test(optree): Log.report( Log.Verbose, "[solve_format_rec] skipping: {}", optree.get_str(display_precision=True, depth=2) if Log.is_level_enabled(Log.Verbose) else "") self.memoization_map[optree] = None return None else: for op_input in optree.get_inputs(): self.solve_format_rec(op_input) new_format = optree.get_precision() if not new_format is None and not is_unevaluated_format( new_format): Log.report( Log.Verbose, "format {} has already been determined for {}", str(new_format), optree.get_str(display_precision=True) if Log.is_level_enabled(Log.Verbose) else "") elif isinstance(optree, LogicalOr) or isinstance( optree, LogicalAnd) or isinstance(optree, LogicalNot): new_format = solve_format_BooleanOp(optree) elif isinstance(optree, Comparison): new_format = solve_format_Comparison(optree) elif isinstance(optree, CountLeadingZeros): new_format = solve_format_CLZ(optree) elif isinstance(optree, Multiplication): new_format = solve_format_Multiplication(optree, format_solver=self) elif isinstance(optree, Addition): new_format = solve_format_Addition(optree, format_solver=self) elif isinstance(optree, Subtraction): new_format = solve_format_Subtraction(optree, format_solver=self) elif isinstance(optree, SpecificOperation): new_format = solve_format_SpecificOperation(optree) elif isinstance(optree, Select): new_format = solve_format_Select(optree) elif isinstance(optree, Min) or isinstance(optree, Max): new_format = solve_format_MinMax(optree) elif isinstance(optree, BitLogicNegate): new_format = solve_format_BitLogicNegate(optree) elif isinstance(optree, Negation): new_format = solve_format_Negation(optree) elif isinstance(optree, BitLogicRightShift) or isinstance( optree, BitLogicLeftShift) or isinstance( optree, BitArithmeticRightShift): new_format = solve_format_shift(optree) elif isinstance(optree, Concatenation): new_format = solve_format_Concatenation(optree) elif isinstance(optree, SubSignalSelection): new_format = solve_format_SubSignalSelection(optree, self) elif isinstance(optree, FixedPointPosition): new_format = solve_format_FixedPointPosition(optree) elif isinstance(optree, SignCast): new_format = solve_format_SignCast(optree) elif isinstance(optree, TypeCast): new_format = solve_format_TypeCast(optree, format_solver=self) elif isinstance(optree, Conversion): Log.report( Log.Error, "Conversion {} must have a defined format, has {}".format( optree.get_str(), str(optree.get_precision(display_precision=True)))) elif isinstance(optree, Return): # unmodified new_format = optree.get_precision() elif isinstance(optree, (BitLogicAnd, BitLogicOr, BitLogicXor)): new_format = solve_format_bitwise_op(optree) else: Log.report( Log.Error, "unsupported operation in solve_format_rec: {}".format( optree.get_str(display_precision=True))) # updating optree format Log.report( Log.Verbose, "new format {} determined for {}", str(new_format), optree.get_str(display_precision=True) if Log.is_level_enabled(Log.Verbose) else "") # optree.set_precision(new_format) real_format = format_set_if_undef(optree, new_format) self.memoization_map[optree] = real_format # format propagation prop_index_list = does_node_propagate_format(optree) propagate_format_to_input(new_format, optree, prop_index_list) return optree.get_precision()