示例#1
0
 def get_default_args(entity_name="my_compound_adder", **kw):
     DEFAULT_VALUES = {
         "precision":
         fixed_point(34, 0, signed=False),
         "debug_flag":
         False,
         "target":
         vhdl_backend.VHDLBackend(),
         "output_file":
         "my_compound_adder.vhd",
         "io_formats": {
             "x": fixed_point(32, 0, signed=False),
             "y": fixed_point(32, 0, signed=False)
         },
         "passes": [
             "beforepipelining:size_datapath",
             "beforepipelining:rtl_legalize",
             "beforepipelining:unify_pipeline_stages"
         ],
         "entity_name":
         entity_name,
         "language":
         VHDL_Code,
         "lower_limit":
         1,
     }
     DEFAULT_VALUES.update(kw)
     return DefaultEntityArgTemplate(**DEFAULT_VALUES, )
示例#2
0
    def generate_scheme(self):
        """ main scheme generation """
        Log.report(Log.Info, "width parameter is {}".format(self.width))
        int_size = 3
        frac_size = self.width - int_size

        input_precision = fixed_point(int_size, frac_size)
        output_precision = fixed_point(int_size, frac_size)

        # declaring main input variable
        var_x = self.implementation.add_input_signal("x", input_precision)
        var_y = self.implementation.add_input_signal("y", input_precision)
        var_x.set_attributes(debug = debug_fixed)
        var_y.set_attributes(debug = debug_fixed)

        test = (var_x > 1)
        test.set_attributes(tag = "test", debug = debug_std)

        large_add = (var_x + var_y)

        pre_result = Select(
            test,
            1,
            large_add,
            tag = "pre_result",
            debug = debug_fixed
        )

        result = Conversion(pre_result, precision=output_precision)

        self.implementation.add_output_signal("vr_out", result)

        return [self.implementation]
示例#3
0
    def __init__(self, arg_template=None):
        """ Initialize """
        # building default arg_template if necessary
        arg_template = SubComponentInstance.get_default_args() if \
            arg_template is None else arg_template
        # initializing I/O precision
        self.width = arg_template.width
        precision = arg_template.precision
        io_precisions = [precision] * 2
        Log.report(
            Log.Info,
            "generating Adaptative Entity with width={}".format(self.width)
        )

        # initializing base class
        ML_EntityBasis.__init__(self,
                                base_name="adaptative_design",
                                arg_template=arg_template
                                )

        self.accuracy = arg_template.accuracy
        self.precision = arg_template.precision

        int_size = 3
        frac_size = 7

        self.input_precision = fixed_point(int_size, frac_size)
        self.output_precision = fixed_point(int_size, frac_size)
示例#4
0
    def generate_scheme(self):
        """ main scheme generation """
        Log.report(Log.Info, "width parameter is {}".format(self.width))
        int_size = 3
        frac_size = self.width - int_size

        input_precision = fixed_point(int_size, frac_size)
        output_precision = fixed_point(int_size, frac_size)

        # declaring main input variable
        var_x = self.implementation.add_input_signal("x", input_precision)
        var_y = self.implementation.add_input_signal("y", input_precision)
        var_x.set_attributes(debug = debug_fixed)
        var_y.set_attributes(debug = debug_fixed)

        sub = var_x - var_y
        c = Constant(0)

        self.implementation.start_new_stage()

        #pre_result = Select(
        #    c > sub,
        #    c,
        #    sub
        #)
        pre_result = Max(0, sub)

        self.implementation.start_new_stage()

        result = Conversion(pre_result + var_x, precision=output_precision)

        self.implementation.add_output_signal("vr_out", result)

        return [self.implementation]
示例#5
0
def solve_format_SignCast(optree):
    """ Resolve the format for a SignCast node """
    assert isinstance(optree, SignCast)
    precision = optree.get_input(0).get_precision()
    int_size = precision.get_integer_size()
    frac_size = precision.get_frac_size()

    if optree.specifier is SignCast.Signed:
        signed_precision = fixed_point(int_size, frac_size, signed=True)
        return signed_precision
    elif optree.specifier is SignCast.Unsigned:
        unsigned_precision = fixed_point(int_size, frac_size, signed=False)
        return unsigned_precision
    else:
        Log.report(Log.Error, "unknown specifier {} in solve_format_SignCast".format(optree.specifier))
示例#6
0
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()
示例#7
0
def solve_format_Constant(optree):
    """ Legalize Constant node """
    assert isinstance(optree, Constant)
    value = optree.get_value()
    if FP_SpecialValue.is_special_value(value):
        return optree.get_precision()
    elif not optree.get_precision() is None:
        # if precision is already set (manually forced), returns it
        return optree.get_precision()
    else:
        # fixed-point format solving
        frac_size = -1
        FRAC_THRESHOLD = 100 # maximum number of frac bit to be tested
        # TODO: fix
        for i in range(FRAC_THRESHOLD):
            if int(value*2**i) == value * 2**i:
                frac_size = i
                break
        if frac_size < 0:
            Log.report(Log.Error, "value {} is not an integer, from node:\n{}", value, optree)
        abs_value = abs(value)
        signed = value < 0
        # int_size = max(int(sollya.ceil(sollya.log2(abs_value+2**frac_size))), 0) + (1 if signed else 0)
        int_size = max(int(sollya.ceil(sollya.log2(abs_value + 1))), 0) + (1 if signed else 0)
        if frac_size == 0 and int_size == 0:
            int_size = 1
        return fixed_point(int_size, frac_size, signed=signed)
示例#8
0
    def generate_scheme(self):
        """ main scheme generation """
        Log.report(Log.Info, "input_precision is {}".format(self.input_precision))
        Log.report(Log.Info, "output_precision is {}".format(self.output_precision))

        shift_amount_precision = fixed_point(3, 0, signed=False)

        # declaring main input variable
        var_x = self.implementation.add_input_signal("x", self.input_precision)
        var_y = self.implementation.add_input_signal("s", shift_amount_precision)

        cst_8 = Constant(9, precision=ML_Integer)
        cst_7 = Constant(7, precision=ML_Integer)

        cst_right_shifted_x = BitLogicRightShift(var_x, cst_8)
        cst_left_shifted_x = BitLogicLeftShift(var_x, cst_7)

        dyn_right_shifted_x = BitLogicRightShift(var_x, var_y)
        dyn_left_shifted_x = BitLogicLeftShift(var_x, var_y)

        result = cst_right_shifted_x + cst_left_shifted_x + dyn_right_shifted_x + dyn_left_shifted_x

        # output
        self.implementation.add_output_signal("vr_out", result)

        return [self.implementation]
示例#9
0
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()
示例#10
0
 def get_default_args(**kw):
     default_dict = {
         "precision":
         fixed_point(32, 0),
         "target":
         VHDLBackend(),
         "output_file":
         "mult_array.vhd",
         "entity_name":
         "mult_array",
         "language":
         VHDL_Code,
         "Method":
         ReductionMethod.Wallace_4to2,
         "pipelined":
         False,
         "dummy_mode":
         False,
         "booth_mode":
         False,
         "method":
         ReductionMethod.Wallace,
         "op_expr":
         multiplication_descriptor_parser("FS9.0xFS13.0"),
         "stage_height_limit": [None],
         "passes": [
             ("beforepipelining:size_datapath"),
             ("beforepipelining:rtl_legalize"),
             ("beforepipelining:unify_pipeline_stages"),
         ],
     }
     default_dict.update(kw)
     return DefaultEntityArgTemplate(**default_dict)
示例#11
0
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()
示例#12
0
def solve_format_Concatenation(optree):
    """ legalize Concatenation operation node """
    if not optree.get_precision() is None:
        return optree.get_precision()
    else:
        bit_size = reduce(lambda x, y: x + y, [op.get_precision().get_bit_size() for op in optree.get_inputs()], 0)
        return fixed_point(bit_size, 0, signed = False)
示例#13
0
    def numeric_emulate(self, io_map):
        """ Meta-Function numeric emulation """
        int_size = 3
        frac_size = self.width - int_size
        input_precision = fixed_point(int_size, frac_size)
        output_precision = fixed_point(int_size, frac_size)

        value_x = io_map["x"]
        value_y = io_map["y"]
        test = value_x > 1
        large_add = output_precision.truncate(value_x + value_y)
        result_value = 1 if test else large_add
        result = {
            "vr_out": result_value
        }
        print(io_map, result)
        return result
示例#14
0
def raw_fp_field_extraction(optree):
    """ generate an operation sub-graph to extract the fp field
        (mantissa without implicit digit) of a fp node """
    size = optree.get_precision().get_base_format().get_bit_size()
    field_size = optree.get_precision().get_base_format().get_field_size()
    return TypeCast(SubSignalSelection(
        TypeCast(optree, precision=ML_StdLogicVectorFormat(size)), 0,
        field_size - 1),
                    precision=fixed_point(field_size, 0, signed=False))
示例#15
0
    def generate_scheme(self):
        """ main scheme generation """
        Log.report(Log.Info, "width parameter is {}".format(self.width))
        int_size = 3
        frac_size = self.width - int_size

        input_precision = fixed_point(int_size, frac_size)
        output_precision = fixed_point(int_size, frac_size)

        # declaring main input variable
        var_x = self.implementation.add_input_signal("x", input_precision)
        var_y = self.implementation.add_input_signal("y", input_precision)
        var_x.set_attributes(debug=debug_fixed)
        var_y.set_attributes(debug=debug_fixed)

        test = (var_x > 1)
        test.set_attributes(tag="test", debug=debug_std)

        sub = var_x - var_y
        c = Constant(0)

        pre_result_select = Select(c > sub,
                                   Select(c < var_y,
                                          sub,
                                          Select(LogicalAnd(
                                              c > var_x,
                                              c < var_y,
                                              tag="last_lev_cond"),
                                                 var_x,
                                                 c,
                                                 tag="last_lev_sel"),
                                          tag="pre_select"),
                                   var_y,
                                   tag="pre_result_select")
        pre_result = Max(0, var_x - var_y, tag="pre_result")

        result = Conversion(Addition(pre_result, pre_result_select, tag="add"),
                            precision=output_precision)

        self.implementation.add_output_signal("vr_out", result)

        return [self.implementation]
示例#16
0
    def generate_scheme(self):
        """ main scheme generation """

        int_size = 3
        frac_size = self.width - int_size

        input_precision = fixed_point(int_size, frac_size)
        output_precision = fixed_point(int_size, frac_size)

        # declaring main input variable
        var_x = self.implementation.add_input_signal("x", input_precision)

        var_y = self.implementation.add_input_signal("y", input_precision)

        var_z = self.implementation.add_input_signal("z", input_precision)

        abstract_formulae = var_x + var_y * var_z + 7

        round_bit = BitSelection(
            abstract_formulae,
            FixedPointPosition(abstract_formulae,
                               0,
                               align=FixedPointPosition.FromPointToLSB),
        )
        msb_bit = BitSelection(
            abstract_formulae,
            FixedPointPosition(abstract_formulae,
                               0,
                               align=FixedPointPosition.FromMSBToLSB))
        lsb_bit = BitSelection(
            abstract_formulae,
            FixedPointPosition(abstract_formulae,
                               0,
                               align=FixedPointPosition.FromLSBToLSB))

        self.implementation.add_output_signal("round", round_bit)
        self.implementation.add_output_signal("msb", msb_bit)
        self.implementation.add_output_signal("lsb", lsb_bit)

        return [self.implementation]
示例#17
0
def comp_3to2(a, b, c):
    """ 3 digits to 2 digits compressor """
    s = BitLogicXor(a,
                    BitLogicXor(b, c, precision=ML_StdLogic),
                    precision=ML_StdLogic)
    c = BitLogicOr(BitLogicAnd(a, b, precision=ML_StdLogic),
                   BitLogicOr(BitLogicAnd(a, c, precision=ML_StdLogic),
                              BitLogicAnd(c, b, precision=ML_StdLogic),
                              precision=ML_StdLogic),
                   precision=ML_StdLogic)
    return c, s

    a = TypeCast(a, precision=fixed_point(1, 0, signed=False))
    b = TypeCast(b, precision=fixed_point(1, 0, signed=False))
    c = TypeCast(c, precision=fixed_point(1, 0, signed=False))

    full = TypeCast(Conversion(a + b + c,
                               precision=fixed_point(2, 0, signed=False)),
                    precision=ML_StdLogicVectorFormat(2))
    carry = BitSelection(full, 1)
    digit = BitSelection(full, 0)
    return carry, digit
示例#18
0
def solve_format_Negation(optree):
    """ legalize format of bitwise logical operation

        Args:
            optree (ML_Operation): bitwise logical input node

        Returns:
            (ML_Format): legal format for input node
    """
    op_input = optree.get_input(0)
    input_precision = op_input.get_precision()
    # TODO: OPTIMIZATION, increment according to input range
    #       rather than according to input bit-size
    int_inc = 1 if not input_precision.get_signed() else 0

    int_size = input_precision.get_integer_size() + int_inc
    frac_size = input_precision.get_frac_size()

    return fixed_point(int_size, frac_size, signed=True)
示例#19
0
def solve_format_Constant(optree):
    """ Legalize Constant node """
    assert isinstance(optree, Constant)
    value = optree.get_value()
    if FP_SpecialValue.is_special_value(value):
        return optree.get_precision()
    elif not optree.get_precision() is None:
        # if precision is already set (manually forced), returns it
        return optree.get_precision()
    else:
        # fixed-point format solving
        assert int(value) == value
        abs_value = abs(value)
        signed = value < 0
        int_size = max(int(sollya.ceil(sollya.log2(abs_value + 1))),
                       0) + (1 if signed else 0)
        frac_size = 0
        if frac_size == 0 and int_size == 0:
            int_size = 1
        return fixed_point(int_size, frac_size, signed=signed)
示例#20
0
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()
示例#21
0
def determine_minimal_fixed_format_cst(value):
    """ determine the minimal size format which can encode
        exactly the constant value value """
    # fixed-point format solving
    frac_size = -1
    FRAC_THRESHOLD = 100  # maximum number of frac bit to be tested
    # TODO: fix
    for i in range(FRAC_THRESHOLD):
        if int(value * 2**i) == value * 2**i:
            frac_size = i
            break
    if frac_size < 0:
        Log.report(Log.Error, "value {} is not an integer, from node:\n{}",
                   value, optree)
    abs_value = abs(value)
    signed = value < 0
    # int_size = max(int(sollya.ceil(sollya.log2(abs_value+2**frac_size))), 0) + (1 if signed else 0)
    int_size = max(int(sollya.ceil(sollya.log2(abs_value + 1))),
                   0) + (1 if signed else 0)
    if frac_size == 0 and int_size == 0:
        int_size = 1
    return fixed_point(int_size, frac_size, signed=signed)
示例#22
0
    def __init__(self,
                 arg_template=DefaultEntityArgTemplate,
                 precision=fixed_point(32, 0, signed=False),
                 accuracy=ML_Faithful,
                 debug_flag=False,
                 target=VHDLBackend(),
                 output_file="mult_array.vhd",
                 entity_name="mult_array",
                 language=VHDL_Code,
                 acc_prec=None,
                 pipelined=False):
        # initializing I/O precision
        precision = arg_template.precision
        io_precisions = [precision] * 2

        # initializing base class
        ML_EntityBasis.__init__(self,
                                base_name="mult_array",
                                entity_name=entity_name,
                                output_file=output_file,
                                io_precisions=io_precisions,
                                backend=target,
                                debug_flag=debug_flag,
                                language=language,
                                arg_template=arg_template)

        self.accuracy = accuracy
        # main precision (used for product operand and default for accumulator)
        self.precision = precision
        # enable operator pipelining
        self.pipelined = pipelined
        # multiplication input descriptor
        self.op_expr = arg_template.op_expr
        self.dummy_mode = arg_template.dummy_mode
        self.booth_mode = arg_template.booth_mode
        # reduction method
        self.reduction_method = arg_template.method
        # limit of height for each compression stage
        self.stage_height_limit = arg_template.stage_height_limit
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
示例#24
0
def convert_bit_heap_to_fixed_point(current_bit_heap, signed=False):
    # final propagating sum
    op_index = 0
    op_list = []
    op_statement = Statement()
    while current_bit_heap.max_count() > 0:
        op_size = current_bit_heap.max_index - current_bit_heap.min_index + 1
        op_format = ML_StdLogicVectorFormat(op_size)
        op_reduce = Signal("op_%d" % op_index,
                           precision=op_format,
                           var_type=Variable.Local)

        offset_index = current_bit_heap.min_index

        for index in range(current_bit_heap.min_index,
                           current_bit_heap.max_index + 1):
            out_index = index - offset_index
            bit_list = current_bit_heap.pop_bits(index, 1)
            if len(bit_list) == 0:
                op_statement.push(
                    ReferenceAssign(BitSelection(op_reduce, out_index),
                                    Constant(0, precision=ML_StdLogic)))
            else:
                assert len(bit_list) == 1
                op_statement.push(
                    ReferenceAssign(BitSelection(op_reduce, out_index),
                                    bit_list[0]))

        op_precision = fixed_point(op_size + offset_index,
                                   -offset_index,
                                   signed=signed)
        op_list.append(
            PlaceHolder(TypeCast(op_reduce, precision=op_precision),
                        op_statement))
        op_index += 1
    return op_list, op_statement
示例#25
0
        def rec_add(op_x, op_y, level=0, lower_limit=1):
            print("calling rec_add")
            n_x = op_x.get_precision().get_bit_size()
            n_y = op_y.get_precision().get_bit_size()
            n = max(n_x, n_y)
            if n <= lower_limit:
                if n == 1:
                    # end of recursion
                    def LSB(op):
                        return BitSelection(op, 0)

                    bit_x = LSB(op_x)
                    bit_y = LSB(op_y)
                    return (
                        # add
                        Conversion(BitLogicXor(bit_x,
                                               bit_y,
                                               precision=ML_StdLogic),
                                   precision=ML_StdLogicVectorFormat(1)),
                        # add + 1
                        Conversion(BitLogicNegate(BitLogicXor(
                            bit_x, bit_y, precision=ML_StdLogic),
                                                  precision=ML_StdLogic),
                                   precision=ML_StdLogicVectorFormat(1)),
                        # generate
                        BitLogicAnd(bit_x, bit_y, precision=ML_StdLogic),
                        # propagate
                        BitLogicXor(bit_x, bit_y, precision=ML_StdLogic))
                else:
                    numeric_x = TypeCast(op_x,
                                         precision=fixed_point(n_x,
                                                               0,
                                                               signed=False))
                    numeric_y = TypeCast(op_y,
                                         precision=fixed_point(n_y,
                                                               0,
                                                               signed=False))
                    pre_add = numeric_x + numeric_y
                    pre_addp1 = pre_add + 1
                    add = SubSignalSelection(pre_add, 0, n - 1)
                    addp1 = SubSignalSelection(pre_addp1, 0, n - 1)
                    generate = BitSelection(pre_add, n)
                    # TODO/FIXME: padd when op_x's size does not match op_y' size
                    bitwise_xor = BitLogicXor(
                        op_x, op_y, precision=ML_StdLogicVectorFormat(n))
                    op_list = [BitSelection(bitwise_xor, i) for i in range(n)]
                    propagate = logical_reduce(op_list,
                                               op_ctor=BitLogicAnd,
                                               precision=ML_StdLogic)

                    return add, addp1, generate, propagate

            half_n = int(n / 2)

            def subdivide(op, split_index_list):
                """ subdivide op node in len(split_index_list) + 1 slices
                    [0 to split_index_list[0]],
                    [split_index_list[0] + 1: split_index_list[1]], .... """
                n = op.get_precision().get_bit_size()
                sub_list = []
                lo_index = 0
                hi_index = None
                for s in split_index_list:
                    if lo_index >= n:
                        break
                    hi_index = min(s, n - 1)
                    local_slice = SubSignalSelection(
                        op, lo_index, hi_index
                    )  #, precision=fixed_point(hi_index - lo_index + 1, 0, signed=False))
                    sub_list.append(local_slice)
                    # key invariant to allow adding multiple subdivision together:
                    # the LSB weight must be uniform
                    lo_index = s + 1
                if hi_index < n - 1:
                    local_slice = SubSignalSelection(op, lo_index, n - 1)
                    sub_list.append(local_slice)
                # padding list
                while len(sub_list) < len(split_index_list) + 1:
                    sub_list.append(Constant(0))
                return sub_list

            x_slices = subdivide(op_x, [half_n - 1])
            y_slices = subdivide(op_y, [half_n - 1])

            # list of (x + y), (x + y + 1), generate, propagate
            add_slices = [
                rec_add(sub_x, sub_y, level=level + 1, lower_limit=lower_limit)
                for sub_x, sub_y in zip(x_slices, y_slices)
            ]

            NUM_SLICES = len(add_slices)

            def tree_reduce(gen_list, prop_list):
                return LogicalOr(
                    gen_list[-1],
                    LogicalAnd(prop_list[-1],
                               tree_reduce(gen_list[:-1], prop_list[:-1])))

            add_list = [op[0] for op in add_slices]
            addp1_list = [op[1] for op in add_slices]
            generate_list = [op[2] for op in add_slices]
            propagate_list = [op[3] for op in add_slices]

            carry_propagate = [propagate_list[0]]
            carry_generate = [generate_list[0]]
            add_result = [add_list[0]]
            addp1_result = [addp1_list[0]]
            for i in range(1, NUM_SLICES):

                def sub_name(prefix, index):
                    return "%s_%d_%d" % (prefix, level, index)

                carry_propagate.append(
                    BitLogicAnd(propagate_list[i],
                                carry_propagate[i - 1],
                                tag=sub_name("carry_propagate", i),
                                precision=ML_StdLogic))
                carry_generate.append(
                    BitLogicOr(generate_list[i],
                               BitLogicAnd(propagate_list[i],
                                           carry_generate[i - 1],
                                           precision=ML_StdLogic),
                               tag=sub_name("carry_generate", i),
                               precision=ML_StdLogic))
                add_result.append(
                    Select(carry_generate[i - 1],
                           addp1_list[i],
                           add_list[i],
                           tag=sub_name("add_result", i),
                           precision=addp1_list[i].get_precision()))
                addp1_result.append(
                    Select(BitLogicOr(carry_propagate[i - 1],
                                      carry_generate[i - 1],
                                      precision=ML_StdLogic),
                           addp1_list[i],
                           add_list[i],
                           tag=sub_name("addp1_result", i),
                           precision=addp1_list[i].get_precision()))
            add_result_full = vector_concatenation(
                #Conversion(carry_generate[-1], precision=ML_StdLogicVectorFormat(1)),
                *tuple(add_result[::-1]))
            addp1_result_full = vector_concatenation(
                #Conversion(BitLogicOr(carry_generate[-1], carry_propagate[-1], precision=ML_StdLogic), precision=ML_StdLogicVectorFormat(1)),
                *tuple(addp1_result[::-1]))
            return add_result_full, addp1_result_full, carry_generate[
                -1], carry_propagate[-1]
示例#26
0
    def generate_advanced_scheme(self):
        ## Generate Fused multiply and add comput <x> . <y> + <z>
        Log.report(
            Log.Info,
            "generating MultArray with output precision {precision}".format(
                precision=self.precision))

        acc = None

        def merge_product_in_heap(operand_list, pos_bit_heap, neg_bit_heap):
            """ generate product operand_list[0] * operand_list[1] and
                insert all the partial products into the heaps
                @p pos_bit_heap (positive bits) and @p neg_bit_heap (negative
                bits) """
            a_i, b_i = operand_list
            if self.booth_mode:
                booth_radix4_multiply(a_i, b_i, pos_bit_heap, neg_bit_heap)
            else:
                # non-booth product generation
                a_i_precision = a_i.get_precision()
                b_i_precision = b_i.get_precision()
                a_i_signed = a_i_precision.get_signed()
                b_i_signed = b_i.get_precision().get_signed()
                unsigned_prod = not (a_i_signed) and not (b_i_signed)
                a_i_size = a_i_precision.get_bit_size()
                b_i_size = b_i_precision.get_bit_size()
                for pp_index in range(a_i_size):
                    a_j_signed = a_i_signed and (pp_index == a_i_size - 1)
                    bit_a_j = BitSelection(a_i, pp_index)
                    pp = Select(equal_to(bit_a_j, 1), b_i, 0)
                    offset = pp_index - a_i_precision.get_frac_size()
                    for b_index in range(b_i_size):
                        b_k_signed = b_i_signed and (b_index == b_i_size - 1)
                        pp_signed = a_j_signed ^ b_k_signed
                        pp_weight = offset + b_index
                        local_bit = BitSelection(pp, b_index)
                        if pp_signed:
                            neg_bit_heap.insert_bit(pp_weight, local_bit)
                        else:
                            pos_bit_heap.insert_bit(pp_weight, local_bit)

        def merge_addition_in_heap(operand_list, pos_bit_heap, neg_bit_heap):
            """ expand addition of operand_list[0] to the bit heaps """
            add_op = operand_list[0]
            precision = add_op.get_precision()
            size = precision.get_bit_size()
            offset = -precision.get_frac_size()
            # most significant bit
            if precision.get_signed():
                neg_bit_heap.insert_bit(size - 1 + offset,
                                        BitSelection(add_op, size - 1))
            else:
                pos_bit_heap.insert_bit(size - 1 + offset,
                                        BitSelection(add_op, size - 1))
            # any other bit
            for index in range(size - 1):
                pos_bit_heap.insert_bit(index + offset,
                                        BitSelection(add_op, index))

        # generating input signals
        stage_operation_map = self.instanciate_inputs(
            insert_mul_callback=lambda a, b: (merge_product_in_heap, [a, b]),
            insert_op_callback=lambda op: (merge_addition_in_heap, [op]))

        # heap of positive bits
        pos_bit_heap = BitHeap()
        # heap of negative bits
        neg_bit_heap = BitHeap()

        def reduce_heap(pos_bit_heap, neg_bit_heap, limit=2):
            """ reduce both pos_bit_heap and neg_bit_heap until their height
                is lower or equal to @p limit """
            # Partial Product reduction
            while pos_bit_heap.max_count() > limit:
                pos_bit_heap = REDUCTION_METHOD_MAP[self.reduction_method](
                    pos_bit_heap)
                dump_heap_stats("pos_bit_heap", pos_bit_heap)
            while neg_bit_heap.max_count() > limit:
                neg_bit_heap = REDUCTION_METHOD_MAP[self.reduction_method](
                    neg_bit_heap)
                dump_heap_stats("neg_bit_heap", neg_bit_heap)
            return pos_bit_heap, neg_bit_heap

        def dump_heap_stats(title, bit_heap):
            Log.report(Log.Verbose, "  {} max count: {}", title,
                       bit_heap.max_count())

        stage_index_list = sorted(stage_operation_map.keys())
        for stage_id in stage_index_list:
            Log.report(Log.Verbose, "considering stage: {}".format(stage_id))
            # synchronizing pipeline stage
            if stage_id is None:
                pass
            else:
                while stage_id > self.implementation.get_current_stage():
                    current_stage_id = self.implementation.get_current_stage()
                    pos_bit_heap, neg_bit_heap = reduce_heap(
                        pos_bit_heap,
                        neg_bit_heap,
                        limit=self.stage_height_limit[current_stage_id])
                    Log.report(
                        Log.Verbose,
                        "Inserting a new pipeline stage, stage_id={}, current_stage={}",
                        stage_id, self.implementation.get_current_stage())
                    self.implementation.start_new_stage()

            # inserting input operations that appears at this stage
            operation_list = stage_operation_map[stage_id]
            for merge_ctor, operand_list in operation_list:
                Log.report(Log.Verbose, "merging a new operation result")
                merge_ctor(operand_list, pos_bit_heap, neg_bit_heap)

        Log.report(Log.Verbose, "final stage reduction")

        # final stage reduction
        pos_bit_heap, neg_bit_heap = reduce_heap(pos_bit_heap, neg_bit_heap)

        # final conversion to scalar operands
        pos_op_list, pos_assign_statement = convert_bit_heap_to_fixed_point(
            pos_bit_heap, signed=False)
        neg_op_list, neg_assign_statement = convert_bit_heap_to_fixed_point(
            neg_bit_heap, signed=False)

        # a PlaceHolder is inserted to force forwarding of op_statement
        # which will be removed otherwise as it does not appear anywhere in
        # the final operation graph
        acc = None
        if len(pos_op_list) > 0:
            reduced_pos_sum = reduce(operator.__add__, pos_op_list)
            reduced_pos_sum.set_attributes(tag="reduced_pos_sum",
                                           debug=debug_fixed)
            pos_acc = PlaceHolder(reduced_pos_sum, pos_assign_statement)
            acc = pos_acc
        if len(neg_op_list) > 0:
            reduced_neg_sum = reduce(operator.__add__, neg_op_list)
            reduced_neg_sum.set_attributes(tag="reduced_neg_sum",
                                           debug=debug_fixed)
            neg_acc = PlaceHolder(reduced_neg_sum, neg_assign_statement)
            acc = neg_acc if acc is None else acc - neg_acc

        acc.set_attributes(tag="raw_acc", debug=debug_fixed)

        self.precision = fixed_point(self.precision.get_integer_size(),
                                     self.precision.get_frac_size(),
                                     signed=self.precision.get_signed())
        result = Conversion(acc,
                            tag="result",
                            precision=self.precision,
                            debug=debug_fixed)
        self.implementation.add_output_signal("result_o", result)

        return [self.implementation]
示例#27
0
    def generate_scheme(self):
        """ main scheme generation """

        int_size = 3
        frac_size = self.width - int_size

        input_precision = fixed_point(int_size, frac_size)
        output_precision = fixed_point(int_size, frac_size)

        expected_interval = {}

        # declaring main input variable
        var_x = self.implementation.add_input_signal("x", input_precision)
        x_interval = Interval(-10.3,10.7)
        var_x.set_interval(x_interval)
        expected_interval[var_x] = x_interval

        var_y = self.implementation.add_input_signal("y", input_precision)
        y_interval = Interval(-17.9,17.2)
        var_y.set_interval(y_interval)
        expected_interval[var_y] = y_interval

        var_z = self.implementation.add_input_signal("z", input_precision)
        z_interval = Interval(-7.3,7.7)
        var_z.set_interval(z_interval)
        expected_interval[var_z] = z_interval

        cst = Constant(42.5, tag = "cst")
        expected_interval[cst] = Interval(42.5)

        conv_ceil = Ceil(var_x, tag = "ceil")
        expected_interval[conv_ceil] = sollya.ceil(x_interval)

        conv_floor = Floor(var_y, tag = "floor")
        expected_interval[conv_floor] = sollya.floor(y_interval)

        mult = var_z * var_x
        mult.set_tag("mult")
        mult_interval = z_interval * x_interval
        expected_interval[mult] = mult_interval

        large_add = (var_x + var_y) - mult
        large_add.set_attributes(tag = "large_add")
        large_add_interval = (x_interval + y_interval) - mult_interval
        expected_interval[large_add] = large_add_interval

        var_x_lzc = CountLeadingZeros(var_x, tag="var_x_lzc")
        expected_interval[var_x_lzc] = Interval(0, input_precision.get_bit_size())

        reduced_result = Max(0, Min(large_add, 13))
        reduced_result.set_tag("reduced_result")
        reduced_result_interval = interval_max(
            Interval(0),
            interval_min(
                large_add_interval,
                Interval(13)
            )
        )
        expected_interval[reduced_result] = reduced_result_interval

        select_result = Select(
            var_x > var_y,
            reduced_result,
            var_z,
            tag = "select_result"
        )
        select_interval = interval_union(reduced_result_interval, z_interval)
        expected_interval[select_result] = select_interval

        # floating-point operation on mantissa and exponents
        fp_x_range = Interval(-0.01, 100)

        unbound_fp_var = Variable("fp_x", precision=ML_Binary32, interval=fp_x_range)
        mant_fp_x = MantissaExtraction(unbound_fp_var, tag="mant_fp_x", precision=ML_Binary32)
        exp_fp_x = ExponentExtraction(unbound_fp_var, tag="exp_fp_x", precision=ML_Int32)
        ins_exp_fp_x = ExponentInsertion(exp_fp_x, tag="ins_exp_fp_x", precision=ML_Binary32)

        expected_interval[unbound_fp_var] = fp_x_range
        expected_interval[exp_fp_x] = Interval(
            sollya.floor(sollya.log2(sollya.inf(abs(fp_x_range)))),
            sollya.floor(sollya.log2(sollya.sup(abs(fp_x_range))))
        )
        expected_interval[mant_fp_x] = Interval(1, 2)
        expected_interval[ins_exp_fp_x] = Interval(
            S2**sollya.inf(expected_interval[exp_fp_x]),
            S2**sollya.sup(expected_interval[exp_fp_x])
        )


        # checking interval evaluation
        for var in [var_x_lzc, exp_fp_x, unbound_fp_var, mant_fp_x, ins_exp_fp_x, cst, var_x, var_y, mult, large_add, reduced_result, select_result, conv_ceil, conv_floor]:
            interval = evaluate_range(var)
            expected = expected_interval[var]
            print("{}: {}".format(var.get_tag(), interval))
            print("  vs expected {}".format(expected))
            assert not interval is None
            assert interval == expected


        return [self.implementation]
示例#28
0
    def generate_scheme(self):
        """ main scheme generation """

        int_size = 3
        frac_size = self.width - int_size

        input_precision = fixed_point(int_size, frac_size)
        output_precision = fixed_point(int_size, frac_size)

        expected_interval = {}

        # declaring main input variable
        var_x = self.implementation.add_input_signal("x", input_precision)
        x_interval = Interval(-10.3, 10.7)
        var_x.set_interval(x_interval)
        expected_interval[var_x] = x_interval

        var_y = self.implementation.add_input_signal("y", input_precision)
        y_interval = Interval(-17.9, 17.2)
        var_y.set_interval(y_interval)
        expected_interval[var_y] = y_interval

        var_z = self.implementation.add_input_signal("z", input_precision)
        z_interval = Interval(-7.3, 7.7)
        var_z.set_interval(z_interval)
        expected_interval[var_z] = z_interval

        cst = Constant(42.5, tag="cst")
        expected_interval[cst] = Interval(42.5)

        conv_ceil = Ceil(var_x, tag="ceil")
        expected_interval[conv_ceil] = sollya.ceil(x_interval)

        conv_floor = Floor(var_y, tag="floor")
        expected_interval[conv_floor] = sollya.floor(y_interval)

        mult = var_z * var_x
        mult.set_tag("mult")
        mult_interval = z_interval * x_interval
        expected_interval[mult] = mult_interval

        large_add = (var_x + var_y) - mult
        large_add.set_attributes(tag="large_add")
        large_add_interval = (x_interval + y_interval) - mult_interval
        expected_interval[large_add] = large_add_interval

        reduced_result = Max(0, Min(large_add, 13))
        reduced_result.set_tag("reduced_result")
        reduced_result_interval = interval_max(
            Interval(0), interval_min(large_add_interval, Interval(13)))
        expected_interval[reduced_result] = reduced_result_interval

        select_result = Select(var_x > var_y,
                               reduced_result,
                               var_z,
                               tag="select_result")
        select_interval = interval_union(reduced_result_interval, z_interval)
        expected_interval[select_result] = select_interval

        # checking interval evaluation
        for var in [
                cst, var_x, var_y, mult, large_add, reduced_result,
                select_result, conv_ceil, conv_floor
        ]:
            interval = evaluate_range(var)
            expected = expected_interval[var]
            print("{}: {} vs expected {}".format(var.get_tag(), interval,
                                                 expected))
            assert not interval is None
            assert interval == expected

        return [self.implementation]