Ejemplo n.º 1
0
        def mul_fault(self, other, fault):
                (mi, mj) = self.shape
                M = self
		if isinstance(other, Matrix_):
		        N = other
		elif isinstance(other, Matrix):
		        N = Matrix_(other._data, dtype=self.dtype)
		else :
			N = Matrix_(other, dtype=self.dtype)
		(mi, mj) = M.shape
		(ni, nj) = N.shape

                R = Matrix_(np.zeros((mi, nj)), dtype=self.dtype)

                # TODO: finish
                for i in xrange(mi):
                        for j in xrange(nj):
                                v = 0.
                                for k in xrange(mj):
                                        xm = M[i, k]
                                        xn = N[k, j]
                                        if (xm != 0. and xn != 0.):
                                                no_fault = xm * xn
                                                if (fault["loc"] == (i, j) and fault["k"] == k and fault["origin"] == "self"):
                                                        xm = U.bitflip(xm, fault["bit"], type=self.dtype)
                                                v += xm * xn
                                R[i, j] = v
                return R
Ejemplo n.º 2
0
    def product(self, M, N):
        """
        Compute the product of two matrices
        A fault may occur according to the parameters
        """
        if np.isscalar(N):
            #todo
	    return M * N
	else:
            # Non-faulty product
            product =M.dot(N)

            fault = self.parameters.get("fault", None)
            if fault:
                loc = fault["loc"]
                i, j, k = loc["i"], loc["j"], loc["k"]
                bit_flipped = fault["bit"]
                timer = fault["timer"]
                register = fault["register"]
            else:
                fault_indices = self.parameters.get("fault_indices", None)
                if fault_indices != None and "i" in fault_indices:
                    i = fault_indices["i"]
                else:
                    i = int(M.shape[0] * np.random.rand())

                if fault_indices != None and "j" in fault_indices:
                    j = fault_indices["j"]
                else:
                    j = int(N.shape[1] * np.random.rand()) if len(N.shape) == 2 else 0

                if fault_indices != None and "k" in fault_indices:
                    k = fault_indices["k"]
                else:
                    k = int(M.shape[1] * np.random.rand()) if len(M.shape) == 2 else 0


                register = self.parameters.get("register", None)
                if (register == None):
                    register = np.random.choice(["left", "middle", "right"])

                bits = self.parameters.get("vulnerable_bits", [bit for bit in xrange(64)])
                bit_flipped = bits[int(np.floor(np.random.rand() * len(bits)))]
                timer = self.parameters.get("timer", None)


            callback = self.parameters.get("fault_callback", None)			    
            max_fault = self.parameters.get("max_fault", 1)

            safe_product_because_not_vulnerable = not (self.parameters.get("vulnerable", True))
            safe_product_because_max_fault = (max_fault <= len(self.faults))
            safe_product_because_timer = (np.random.rand() > self.parameters.get("p", 1./(M.shape[0]))) if (timer == None) else (self.timer != timer)
            perform_safe_product = (safe_product_because_max_fault or
                                    safe_product_because_timer or
                                    safe_product_because_not_vulnerable)

            if perform_safe_product:
                self.timer += 1
                return product
				        
	    fault = {}
	    fault["register"] = register
            fault["bit"] = bit_flipped
            fault["timer"] = self.timer              

            # looking for the closest non-zero couple (M[i, k], N[k, j])
            n = M.shape[0]
            m = N.shape[0]
            if len(N.shape) == 2:
                l = N.shape[1]
            else:
                l = 1


	    increment_i = 1
	    oscillation_i = 1			
	    fault_occured = False
	    for s in xrange(2 * max(n-i, i)):
		#next i index
                if len(self.faults) >= max_fault:
		    break
                if (i >= 0 and i < n):
		    increment_j = 1
		    oscillation_j = 1
		    for t in xrange(2 * max(l-j, j)):
		        #next j index
                        if len(self.faults) >= max_fault:
			    break
                        if (j >= 0 and j < n):
		            increment_k = 1
		            oscillation_k = 1
		            for u in xrange(2 * max(m-k, k)):
			        #next k index
			        if (k >= 0 and k < m):
			            if (M[i, k] != 0. and 
                                        ((len(N.shape) == 2 and N[k, j] != 0.) or
                                        (len(N.shape) == 1 and N[k] != 0.))):
                                        
                                        fault["loc"] = {"i":i, "j":j, "k": k}
                                        
				        xm_before = M[i, k]
				        xn_before = N[k, j] if len(N.shape) == 2 else N[k]
				        xp_before = xm_before * xn_before
                                        
                                        fault["value_before"] = product[i, j] if len(product.shape) == 2 else product[i]
                                        if (register == "left"):    
                                            xm_after = U.bitflip(xm_before, bit_flipped, type=M.dtype.type)
                                            xn_after = xn_before
                                            fault["register_before"] = xm_before
                                            fault["register_after"] = xm_after
                                            
                                            xp_after = xm_after * xn_after
                                    
                                        if (register == "right"):
                                            xm_after = xm_before
                                            xn_after = U.bitflip(xn_before, bit_flipped, type=M.dtype.type)
                                            fault["register_before"] = xn_before
                                            fault["register_after"] = xn_after

                                            xp_after = xm_after * xn_after
                                    
                                        if (register == "middle"):
                                            xm_after = xm_before
                                            xn_after = xn_before
                                            xp_after = U.bitflip(xp_before, bit_flipped, type=M.dtype.type)
                                            fault["register_before"] = xp_before
                                            fault["register_after"] = xp_after
                                            
                                        self.faults += [fault]

                                        difference = xp_after - xp_before

                                        if len(product.shape) == 2:
                                            product[i, j] += difference
                                        if len(product.shape) == 1:
                                            product[i] += difference
                                        
                                        fault["value_after"] = product[i, j] if len(product.shape) == 2 else product[i]
                                        
                                        if callback:
                                            callback(fault)
                                        break
				k += oscillation_k * increment_k
				oscillation_k *= -1
				increment_k += 1
			j += oscillation_j * increment_j
			oscillation_j *= -1
			increment_j += 1
		i += oscillation_i * increment_i
                oscillation_i *= -1
		increment_i += 1
            self.timer += 1
	    return product
Ejemplo n.º 3
0
	def __mul__(self, other):
		if np.isscalar(other):
			return Matrix(self._data * other, dtype=self.dtype)
		else:
                        if (type(self.timer) is int) and self.vulnerable:
                                self.timer = self.timer + 1
                        if isinstance(other, Matrix) and type(other.timer) is int and other.vulnerable:
                                other.timer = other.timer + 1

                        
			perform_safe_product = not self.is_vulnerable()
                        if (isinstance(other, Matrix)):
				perform_safe_product &= not other.is_vulnerable()

			product = Matrix(np.dot(self._data, other._data), dtype=self.dtype)
                        if perform_safe_product:
                                return product
			
			else:
				
				vulnerable_self = self.is_vulnerable()
				vulnerable_other = other.is_vulnerable()
				if vulnerable_self or vulnerable_other:
					(i,j,k) = self.vulnerability_parameters.get("fault_indices", (int(self.shape[0]), 0, int(self.shape[1] * np.random.rand())))
					# looking for the closest non-zero couple (self[i, k], other[k, j])

					(n, m) = self.shape
					(m, l) = other.shape

					increment_i = 1
					oscillation_i = 1			
					fault_occured = False
					for s in xrange(2 * max(n-i, i)):
						#next i index
						increment_j = 1
						oscillation_j = 1
						for t in xrange(2 * max(l-j, j)):
							#next j index
							increment_k = 1
							oscillation_k = 1
							for u in xrange(2 * max(m-k, k)):
								#next k index
								if (i < 0 or i >= n):
									break
								if (k >= 0 and k < m):
									if self.__get__((i, k)) != 0. and other[k, j] != 0.:
										x_self = self.__get__((i, k))
										x_other = other[k, j]
										x_product = x_self * x_other
								
										if vulnerable_self:
											bits = self.vulnerability_parameters.get("vulnerable_bits", [i for i in xrange(64)])
											callback = self.vulnerability_paramaters("fault_callback", None)
										else:
											bits = other.vulnerability_parameters.get("vulnerable_bits", [i for i in xrange(64)])
											callback = other.vulnerability_paramaters("fault_callback", None)
										
										bit_flipped = bits[int(np.floor(np.random.rand() * len(bits)))]
										which_register = np.random.rand()
										
										fault_self = {}
										fault_self["loc"] = (i, j, k)

										fault["value_before"] = x_product
										if which_register < 1./3:
											fault["register"] = "left"
											fault["register_before"] = x_self
											x_self = U.bitflip(x_self, bit_flipped, type=self.dtype)
											fault["register_after"] = x_self
											fault["timer"] = self.timer
											x_product = x_self * x_other
										elif which_register < 2./3:
											fault["register"] = "right"
											fault["register_before"] = x_other
											x_other = U.bitflip(x_other, bit_flipped, type=other.dtype)
											fault["register_after"] = x_other
											x_product = x_self * x_other
										else:
											fault["register"] = "middle"
											fault["register_before"] = x_product
											x_product = U.bitflip(x_product, bit_flipped, type=self.dtype)
											fault["register_after"] = x_product
										fault["value_after"] = x_product


										fault = {"loc":(i, j, k), "value_before": M[i,k], "value_after" : xm, "bit" :bit_flipped, "origin":"left", "without_fault" : no_fault, "with_fault":xn*xm, "timer":M.timer}
										R.faults += [fault]
										fault = {"loc":(i, j, k), "value_before": M[i,k], "value_after" : xm, "bit" :bit_flipped, "origin":"self", "without_fault" : no_fault, "with_fault":xn*xm, "timer":M.timer}
										M.faults += [fault]
										callback_self = self.vulnerability_paramaters("fault_callback", None)
										if self_callback:
											fault_callback_m(fault)

										fault_occured = True
										break
								k += oscillation_k * increment_k
								oscillation_k *= -1
								increment_k += 1
							if fault_occured:
								break
							j += oscillation_j * increment_j
							oscillation_j *= -1
							increment_j += 1
						if fault_occured:
							break
						i += oscillation_i * increment_i
						oscillation_i *= -1
						increment_i += 1
					return product
Ejemplo n.º 4
0
	def mul_type1(self, other, p = 1.e-6):
		# Type 1 vulnerable multiplication : Fault (bitflip) may occur on each operation, with probability p
		# Slow ! Full python implementation
		# M x N
		M = self
		if isinstance(other, Matrix_):
			N = other
		elif isinstance(other, Matrix):
			N = Matrix_(other._data, dtype=self.dtype)
		else :
			N = Matrix_(other, dtype=self.dtype)
		(mi, mj) = M.shape
		(ni, nj) = N.shape
		# if mj != ni ... todo

		max_fault_count_m = M._p.get("max_fault_count", mi*mj)
		max_fault_count_n = N._p.get("max_fault_count", ni*nj)
		
		bits_m = M._p.get("vulnerable_bits", [i for i in xrange(64)]) # TODO: check if double precision
		bits_n = N._p.get("vulnerable_bits", [i for i in xrange(64)])

		fault_indices_m = M._p.get("fault_indices", [])
		fault_indices_n = N._p.get("fault_indices", [])
		
		random_m = M._p.get("random", False)
		random_n = N._p.get("random", False)

		p_m = M._p.get("p", p)
		p_n = N._p.get("p", p)

		fault_callback_m = M._p["fault_callback"]
		fault_callback_n = N._p["fault_callback"]

		R = Matrix_(np.zeros((mi, nj)), dtype=self.dtype)


		# TODO: Priority system for parameters inheritance (Here priority(M) > priority(N))
		if (N._p["inherit"]):
			R.set_parameters(N._p)
		if (M._p["inherit"]):
			R.set_parameters(M._p)

		if N._p["inherited_parameters"]:
			R.set_parameters(N._p["inherited_parameters"])
		if M._p["inherited_parameters"]:
			R.set_parameters(M._p["inherited_parameters"])


		for i in xrange(mi):
			for j in xrange(nj):
				v = 0.
				for k in xrange(mj):
					xm = M[i, k]
					xn = N[k, j]
					if (xm != 0. and xn != 0.):
                                                no_fault = xm * xn
						### TODO: change to make it more generic
						if (M.vulnerable and 
                                                    max_fault_count_m > len(M.faults) and
                                                    ((random_m and np.random.rand() < p_m) or
                                                     ((i,j,k) in fault_indices_m)) and
                                                    (M._p["timer"] == M.timer or M._p["timer"] == None)):
							bit_flipped = bits_m[int(np.floor(np.random.rand() * len(bits_m)))]
							xm = U.bitflip(xm, bit_flipped, type=self.dtype)

							fault = {"loc":(i, j), "k": k, "value_before": M[i,k], "value_after" : xm, "bit" :bit_flipped, "origin":"left", "without_fault" : no_fault, "with_fault":xn*xm, "timer":M.timer}
							R.faults += [fault]
							fault = {"loc":(i, j), "k": k, "value_before": M[i,k], "value_after" : xm, "bit" :bit_flipped, "origin":"self", "without_fault" : no_fault, "with_fault":xn*xm, "timer":M.timer}
							M.faults += [fault]
							if fault_callback_m:
								fault_callback_m(fault)

						if (N.vulnerable and 
                                                    max_fault_count_n > len(N.faults) and 
                                                    ((random_n and np.random.rand() < p_n) or
                                                     ((i,j,k) in fault_indices_n)) and
                                                    (N._p["timer"] == None or N.timer == N._p["timer"])):
							bit_flipped = bits_n[int(np.floor(np.random.rand() * len(bits_n)))]
							xn = U.bitflip(xn, bit_flipped, type=self.dtype)

							fault = {"loc":(i, j), "k": k, "value_before": N[k, j], "value_after" : xn, "bit" :bit_flipped, "origin":"right",  "without_fault" : no_fault, "with_fault":xn*xm, "timer":N.timer}
							R.faults += [fault]
							fault = {"loc":(i, j), "k": k, "value_before" : N[k,j], "value_after" : xn, "bit" :bit_flipped, "origin":"self",  "without_fault" : no_fault, "with_fault":xn*xm, "timer":N.timer}
							N.faults += [fault]
							if fault_callback_n:
								fault_callback_n(fault)
						v += xm * xn
				R[i, j] = v
		return R