Exemple #1
0
 def __lshift__(self, d):
     """Apply a left shift of d bits onto integer values and FxPF of a copy of self."""
     SELF = self.copy()
     SELF._integer_inf <<= d
     SELF._integer_sup <<= d
     wl, m, lsb = SELF.FPF.wml()
     lsb = lsb - d
     SELF._FPF = FPF(wl=wl, lsb=lsb, signed=self.FPF._signed)
     return SELF
Exemple #2
0
 def copy(self):
     v_inf, v_sup = self.values
     N_inf, N_sup = self.integers
     w, m, l = self.FPF.wml()
     fpf = FPF(wl=w, msb=m, signed=self.FPF._signed)
     return Variable(value_inf=v_inf,
                     value_sup=v_sup,
                     fpf=fpf,
                     integer_inf=N_inf,
                     integer_sup=N_sup)
Exemple #3
0
    def mult(self, cst, wl=None, lsb=None):
        """Multiplication between constant and variable on wl_op bits (for the wordlength)"""
        # if cst is not a Constant object, then return an AssertionError
        assert (
            isinstance(cst, Constant)
        ), "Constant type expected for 'cst', not %s" % type(cst).__name__

        # compute real values
        X = (cst.value * self.values[0], cst.value * self.values[1])
        inf = min(X)
        sup = max(X)

        # compute msb

        if not Variable.formatting:
            # constant shift is computed as the difference between optimal wordlength (wl_cst + wl_var) and operator wordlength (wl_op)
            rshift = cst.FPF.wl + self.FPF.wl - wl
            # if rshift < 0 then rshift equals 0 (only positive shift is considered)
            rshift = max(rshift, 0)

            # compute integer values with a positive (or zero) shift onto the constant
            #NX = ((cst.integer >> cst_rshift)*self.integers[0] , (cst.integer >> cst_rshift)*self.integers[1])
            NX = ((cst.mantissa * self.integers[0]) >> rshift,
                  (cst.mantissa * self.integers[1]) >> rshift)
            # if cst.value > 0 then Ninf <-- NX[0], else Ninf <-- NX[1]. In both cases Ninf <-- min(NX)
            Ninf = min(NX)
            # same reasoning for Nsup, Nsup <-- max(NX)
            Nsup = max(NX)
            fpf = FPF(wl=wl, msb=cst.FPF.msb + self.FPF.msb + 1)
            V = Variable(value_inf=inf,
                         value_sup=sup,
                         fpf=fpf,
                         integer_inf=int(Ninf),
                         integer_sup=int(Nsup))
        else:
            lsb_prod = cst.FPF._lsb + self.FPF._lsb
            rshift = max(lsb - lsb_prod, 0)
            Cx = Constant(max(abs(inf), abs(sup)), wl=16)
            wl = Cx.FPF._msb + 1 - lsb
            V = Variable(value_inf=inf, value_sup=sup, wl=wl)
        return V, rshift
Exemple #4
0
    def add(self, other, wl_op, msb_final=None, fpf_add=None):
        # if other is not a Variable object, then return an AssertionError
        assert (
            isinstance(other, Variable)
        ), "Variable type expected for 'other', not %s" % type(other).__name__
        # the function computes sum between two variables where other variable has the smaller lsb,
        # then if it's not the case, addition is re-called with arguments interchanged
        if other.lsb < self.lsb:
            V, var1, var2, rshift = other.add(self,
                                              wl_op,
                                              msb_final=msb_final,
                                              fpf_add=fpf_add)
            return V, var2, var1, [rshift[1], rshift[0]]
        rshift = [0, 0]
        SELF = self.copy()
        OTHER = other.copy()

        # 1. FxPF of addition
        if fpf_add:
            msb_add = min(max(SELF.FPF.msb, OTHER.FPF.msb), fpf_add.msb)
            if Variable.formatting is True:
                l_add = fpf_add.lsb
            else:
                l_add = msb_add - fpf_add.wl + 1
            fpf_add = FPF(msb=msb_add, lsb=l_add, signed=fpf_add._signed)
        else:  #normally never happens
            msb_add = max(SELF.FPF.msb, OTHER.FPF.msb)
            l_add = msb_add + 1 - wl_op

        # 2. Formatting of the two operands into the format of the addition
        # rshift is computed by this formatting
        SELF, rshift[0] = SELF.Formatting(fpf_add)
        OTHER, rshift[1] = OTHER.Formatting(fpf_add)

        # 3. Addition
        inf = SELF._integer_inf + OTHER._integer_inf
        sup = SELF._integer_sup + OTHER._integer_sup

        # 4. Overflow
        # in case of overflow for inf or sup, sums are recomputed with one bit shifted integers
        if ((inf < -2**(wl_op - 1)) or (sup > 2**(wl_op - 1) - 1)):
            if (msb_add == msb_final):
                inf = -2**(wl_op - 1)
                sup = 2**(wl_op - 1) - 1
            else:
                SELF = SELF >> 1
                if OTHER != SELF:
                    OTHER = OTHER >> 1
                inf = SELF.integers[0] + OTHER.integers[0]
                sup = SELF.integers[1] + OTHER.integers[1]
                l_add -= 1

        # the result Variable is created with real values, integer values and computed fpf (from wl_op and l_add)
        V = Variable(value_inf=SELF.values[0] + OTHER.values[0],
                     value_sup=SELF.values[1] + OTHER.values[1],
                     fpf=fpf_add,
                     integer_inf=inf,
                     integer_sup=sup)
        # operands rshifts are computed as the difference between operand lsb and l_add if positive, 0 else

        return V, SELF, OTHER, rshift
Exemple #5
0
def best_oSoP_gen_from_dict(D):

    if isinstance(D, list):
        Osop = []
        for i, d in enumerate(D):
            Osop.append(best_oSoP_gen_from_dict(d))
        return Osop
    else:
        variables = D["list_var"]
        constants = D["list_cst"]
        constants_wordlength = D["wl_cst"]
        multipliers_wordlength = D["wl_mult"]
        adders_wordlength = D["wl_add"]
        fpf_final = D["fpf_final"]
        formatting = D["formatting"]
        RndOff = "RAM"

        # args
        N = len(constants)
        delta = 0

        if formatting:
            Variable.formatting = True
            Adder.formatting = True
            Multiplier.formatting = True

            if N == 1:
                delta = 0
            else:
                delta = int(floor(log(N - 1, 2))) + 1
            Adder.wl = adders_wordlength + delta
            multipliers_wordlength += delta
            lsb_final = fpf_final.lsb - delta
        else:
            Variable.formatting = False
            Adder.formatting = False
            Multiplier.formatting = False
            lsb_final = 0
            Adder.wl = adders_wordlength

        if not isinstance(constants_wordlength, list):
            constants_wordlength = [constants_wordlength] * N
        if not isinstance(multipliers_wordlength, list):
            multipliers_wordlength = [multipliers_wordlength] * N

        var_final = Variable(fpf=fpf_final)

        # Multipliers creation from args
        #Q&D
        multipliers = []
        for i in range(N):
            M = None
            if constants_wordlength[i] > 0:
                try:
                    M= Multiplier(constants[i], constants_wordlength[i], variables[i], variables[i]._name,\
                     multipliers_wordlength[i], i, RndOff=RndOff, lsb_final=lsb_final)
                except:
                    print("Erreur création multiplieur")
            if M:
                multipliers.append(M)
        #multipliers = [Multiplier(constants[i], constants_wordlength[i], variables[i], variables[i]._name,\
        #                         multipliers_wordlength[i], i, RndOff=RndOff, lsb_final=lsb_final) for i in range(N) if constants_wordlength[i] >0]
        multipliers.sort(Multiplier.cmp_lsb)

        # for m in multipliers:
        # 	print m._name,m._cst.integer, m.result.FxPF, m.result.values

        # Heuristic for non-exhaustive generation
        # Computation of max_lsb, the maximum difference of lsb between two consecutive multipliers (in the sorted list)
        max_lsb = 0
        N = len(multipliers)
        for i in range(N - 1):
            max_lsb = max(
                max_lsb,
                abs(multipliers[i + 1].result.lsb - multipliers[i].result.lsb))

        best_osop = None
        h = N

        # formatting is the bits cleaning option
        if formatting == True:
            # Computation of fpf_add, ie fpf_final 'plus' delta bits considered for additions
            fpf_add = FPF(wl=fpf_final.wl + delta,
                          msb=fpf_final.msb,
                          lsb=fpf_final.lsb - delta,
                          signed=fpf_final._signed)
            if N == 1:
                best_osop = oSoP(multipliers[0])
                # print best_osop._var_final
            elif N < 10:
                best_osop = oSoP_Generator2(multipliers,
                                            max_lsb,
                                            fpf_add,
                                            var_final,
                                            formatting=formatting)
            else:
                osop = multipliers[0]
                for m in multipliers[1:]:
                    osop = osop.add(m, (False, False, fpf_add))
                best_osop = oSoP(osop, var_final)
                best_osop.Calc_var_result((False, False, fpf_add))

        # if formatting == False we use default parameters
        elif formatting == False:
            fpf_add = FPF(wl=adders_wordlength, msb=fpf_final.msb)

            LT = []
            best_mean = 10000
            # if  7>N >1:
            # 	best_osop = oSoP_Generator2(multipliers, max_lsb, fpf_add, var_final, formatting=formatting)
            if N == 1:
                best_osop = oSoP(multipliers[0])
            else:
                osop = multipliers[0]
                for m in multipliers[1:]:
                    osop = osop.add(m, (False, False, fpf_add))
                best_osop = oSoP(osop, var_final)
                best_osop.Calc_var_result((False, False, fpf_add))

            #for L in oSoP_Generator2(multipliers, max_lsb, fpf_add, var_final):
            # 	#if L.height() == ceil(log(N,2)):
            # 	#	return L
            # 	if L._Top._total_error.mean <= best_mean:
            # 		if L._Top._total_error.mean < best_mean:
            # 			LT=[]
            # 		LT.append(L)
            # 		best_mean = L._Top._total_error.mean
            # 		best_osop = L
            # 	else:
            # 		L._Top.kill()

            # h = LT[0].height()
            # for L in LT:
            # 	if L.height() <=h:
            # 		h=L.height()
            # 		best_osop = L

        return best_osop
Exemple #6
0
def best_oSoP_gen(variables_name, variables, constants, constants_wordlength, multipliers_wordlength,\
                  adders_wordlength, fpf_final, alfix = False,plus = False, RndOff = "RAM", formatting = True):

    # args
    N = len(constants)
    delta = 0

    if formatting:
        Variable.formatting = True
        Adder.formatting = True
        Multiplier.formatting = True

        delta = int(ceil(log(N, 2)))
        Adder.wl = adders_wordlength + delta
        multipliers_wordlength += delta
        lsb_final = fpf_final.lsb - delta
    else:
        Variable.formatting = False
        Adder.formatting = False
        Multiplier.formatting = False
        lsb_final = 0

    if not isinstance(constants_wordlength, list):
        constants_wordlength = [constants_wordlength] * N
    if not isinstance(multipliers_wordlength, list):
        multipliers_wordlength = [multipliers_wordlength] * N
    if RndOff and (not isinstance(RndOff, list)):
        RndOff = [RndOff] * N
    if not isinstance(variables_name, list):
        variables_name = [variables_name + repr(i) for i in range(N)]
    Adder.wl_add = adders_wordlength
    var_final = Variable(fpf=fpf_final)

    # Multipliers creation from args
    multipliers = [Multiplier(constants[i], constants_wordlength[i], variables[i], variables_name[i],\
                              multipliers_wordlength[i], i, RndOff=RndOff[i], lsb_final=lsb_final) for i in range(N)]
    multipliers.sort(Multiplier.cmp_lsb)

    # Heuristic for non-exhaustive generation
    # Computation of max_lsb, the maximum difference of lsb between two consecutive multipliers (in the sorted list)
    max_lsb = 0
    for i in range(N - 1):
        max_lsb = max(
            max_lsb,
            abs(multipliers[i + 1].result.lsb - multipliers[i].result.lsb))

    best_osop = None
    h = N

    # formatting is the bits cleaning option
    if formatting:
        # Computation of fpf_add, ie fpf_final 'plus' delta bits considered for additions
        fpf_add = FPF(wl=fpf_final.wl + delta,
                      msb=fpf_final.msb,
                      lsb=fpf_final.lsb - delta,
                      signed=fpf_final._signed)
        for L in oSoP_Generator2(multipliers,
                                 max_lsb,
                                 fpf_add,
                                 var_final,
                                 alfix=False,
                                 plus=False,
                                 formatting=formatting):
            if L.height() == ceil(log(N, 2)):
                h = L.height()
                best_osop = L
                break

    # if formatting == False we use default parameters
    else:
        fpf_add = FPF(wl=adders_wordlength, msb=fpf_final.msb)

        nb = 0
        LT = []
        best_mean = 10000
        for L in oSoP_Generator2(multipliers,
                                 max_lsb,
                                 fpf_add,
                                 var_final,
                                 alfix=False,
                                 plus=False,
                                 formatting=formatting):
            nb += 1
            if nb % 10000 == 0:
                print(nb)
                #LT.append(L)
                #break
            if L._Top._total_error.mean <= best_mean:
                if L._Top._total_error.mean < best_mean:
                    LT = []
                LT.append(L)
                best_mean = L._Top._total_error.mean
                best_osop = L

        h = LT[0].height()
        for L in LT:
            if L.height() <= h:
                h = L.height()
                best_osop = L

    return best_osop