Python-ELMO is a Python library which offers an encapsulation of the binary tool ELMO, in order to manipulate it easily in Python and SageMath script.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

engine.py 8.9KB

  1. import numpy as np
  2. import os
  3. from enum import IntEnum, unique
  4. def hweight(n):
  5. c = 0
  6. while n>0:
  7. c += (n & 1)
  8. n >>= 1
  9. return c
  10. def hdistance(x,y):
  11. return hweight(x^y)
  12. def binary_writing(n, nb_bits=32, with_hamming=False):
  13. n = np.array(n)
  14. w, h = np.zeros((nb_bits, len(n))), np.zeros((len(n)))
  15. for ind in range(nb_bits):
  16. w[ind] = (n & 1)
  17. h += w[ind]
  18. n >>= 1
  19. ind += 1
  20. return (w, h) if with_hamming else w
  21. @unique
  22. class Instr(IntEnum):
  23. EOR = 0
  24. LSL = 1
  25. STR = 2
  26. LDR = 3
  27. MUL = 4
  28. OTHER = 5
  29. PREVIOUS = 0
  30. CURRENT = 1
  31. SUBSEQUENT = 2
  32. class ELMOEngine:
  33. def __init__(self):
  34. self.load_coefficients()
  35. self.reset_points()
  36. def _extract_data(self, nb):
  37. coeffs = self.coefficients[self.pos:self.pos+nb]
  38. self.pos += nb
  39. return coeffs
  40. def load_coefficients(self):
  41. filename = os.path.dirname(os.path.abspath(__file__))+'/elmo/coeffs.txt'
  42. self.coefficients = None
  43. with open(filename, 'r') as _file:
  44. self.coefficients = np.array([list(map(float, line.split())) for line in _file.readlines()[:2153]])
  45. if self.coefficients is None:
  46. raise IOError('Problem to read the coefficients.')
  47. self.pos = 0
  48. self.constant = np.squeeze(self._extract_data(1))
  49. self.PrvInstr = self._extract_data(4)
  50. self.SubInstr = self._extract_data(4)
  51. self.Operand1 = self._extract_data(32)
  52. self.Operand2 = self._extract_data(32)
  53. self.BitFlip1 = self._extract_data(32)
  54. self.BitFlip2 = self._extract_data(32)
  55. self.HWOp1PrvInstr = self._extract_data(4)
  56. self.HWOp2PrvInstr = self._extract_data(4)
  57. self.HDOp1PrvInstr = self._extract_data(4)
  58. self.HDOp2PrvInstr = self._extract_data(4)
  59. self.HWOp1SubInstr = self._extract_data(4)
  60. self.HWOp2SubInstr = self._extract_data(4)
  61. self.HDOp1SubInstr = self._extract_data(4)
  62. self.HDOp2SubInstr = self._extract_data(4)
  63. self.Operand1_bitinteractions = self._extract_data(496)
  64. self.Operand2_bitinteractions = self._extract_data(496)
  65. self.BitFlip1_bitinteractions = self._extract_data(496)
  66. self.BitFlip2_bitinteractions = self._extract_data(496)
  67. def reset_points(self):
  68. self.points = []
  69. self.power = None
  70. def add_point(self, triplet, previous_ops, current_ops):
  71. self.points.append((triplet, previous_ops, current_ops))
  72. def _dot(self, a, b):
  73. return np.sum(a * b, axis=0)
  74. def calculate_point(self, triplet, previous_ops, current_ops, debug=False):
  75. nb_points = triplet.shape[1]
  76. instructiontype = triplet[CURRENT]
  77. instructiontype = instructiontype % 5 # Type 5 = Instruction was not profiled
  78. # Previous
  79. previous_instruction_typedec = triplet[PREVIOUS]
  80. previous_instruction_type = np.zeros((5, nb_points))
  81. for i in range(nb_points):
  82. if previous_instruction_typedec[i] < 5:
  83. previous_instruction_type[previous_instruction_typedec[i],i] = 1
  84. # Current
  85. (current_op1_binary, hw_op1) = binary_writing(current_ops[0], with_hamming=True)
  86. (current_op2_binary, hw_op2) = binary_writing(current_ops[1], with_hamming=True)
  87. (current_op1_bitflip, hd_op1) = binary_writing(previous_ops[0] ^ current_ops[0], with_hamming=True)
  88. (current_op2_bitflip, hd_op2) = binary_writing(previous_ops[1] ^ current_ops[1], with_hamming=True)
  89. current_instruction_typedec = instructiontype
  90. current_instruction_type = np.zeros((5, nb_points))
  91. for i in range(nb_points):
  92. if triplet[CURRENT,i] < 5:
  93. current_instruction_type[current_instruction_typedec[i],i] = 1
  94. # Subsequent
  95. subsequent_instruction_typedec = triplet[SUBSEQUENT]
  96. subsequent_instruction_type = np.zeros((5, nb_points))
  97. for i in range(nb_points):
  98. if subsequent_instruction_typedec[i] < 5:
  99. subsequent_instruction_type[subsequent_instruction_typedec[i],i] = 1
  100. # Component variables
  101. PrvInstr_data = self._dot( previous_instruction_type[1:], self.PrvInstr[:,instructiontype] )
  102. SubInstr_data = self._dot( subsequent_instruction_type[1:], self.SubInstr[:,instructiontype] )
  103. Operand1_data = self._dot( current_op1_binary, self.Operand1[:,instructiontype] )
  104. Operand2_data = self._dot( current_op2_binary, self.Operand2[:,instructiontype] )
  105. BitFlip1_data = self._dot( current_op1_bitflip, self.BitFlip1[:,instructiontype] )
  106. BitFlip2_data = self._dot( current_op2_bitflip, self.BitFlip2[:,instructiontype] )
  107. HWOp1PrvInstr_data = hw_op1 * self._dot(previous_instruction_type[1:], self.HWOp1PrvInstr[:,instructiontype])
  108. HWOp2PrvInstr_data = hw_op2 * self._dot(previous_instruction_type[1:], self.HWOp2PrvInstr[:,instructiontype])
  109. HDOp1PrvInstr_data = hd_op1 * self._dot(previous_instruction_type[1:], self.HDOp1PrvInstr[:,instructiontype])
  110. HDOp2PrvInstr_data = hd_op2 * self._dot(previous_instruction_type[1:], self.HDOp2PrvInstr[:,instructiontype])
  111. HWOp1SubInstr_data = hw_op1 * self._dot(subsequent_instruction_type[1:], self.HWOp1SubInstr[:,instructiontype])
  112. HWOp2SubInstr_data = hw_op2 * self._dot(subsequent_instruction_type[1:], self.HWOp2SubInstr[:,instructiontype])
  113. HDOp1SubInstr_data = hd_op1 * self._dot(subsequent_instruction_type[1:], self.HDOp1SubInstr[:,instructiontype])
  114. HDOp2SubInstr_data = hd_op2 * self._dot(subsequent_instruction_type[1:], self.HDOp2SubInstr[:,instructiontype])
  115. Operand1_bitinteractions_data = np.zeros((nb_points))
  116. Operand2_bitinteractions_data = np.zeros((nb_points))
  117. BitFlip1_bitinteractions_data = np.zeros((nb_points))
  118. BitFlip2_bitinteractions_data = np.zeros((nb_points))
  119. count = 0
  120. for i in range(32):
  121. for j in range(i+1,32):
  122. Operand1_bitinteractions_data += self.Operand1_bitinteractions[count,instructiontype] * current_op1_binary[i] * current_op1_binary[j]
  123. Operand2_bitinteractions_data += self.Operand2_bitinteractions[count,instructiontype] * current_op2_binary[i] * current_op2_binary[j]
  124. BitFlip1_bitinteractions_data += self.BitFlip1_bitinteractions[count,instructiontype] * current_op1_bitflip[i] * current_op1_bitflip[j]
  125. BitFlip2_bitinteractions_data += self.BitFlip2_bitinteractions[count,instructiontype] * current_op2_bitflip[i] * current_op2_bitflip[j]
  126. count += 1
  127. power = self.constant[instructiontype] \
  128. + PrvInstr_data + SubInstr_data \
  129. + Operand1_data + Operand2_data \
  130. + BitFlip1_data + BitFlip2_data \
  131. + HWOp1PrvInstr_data + HWOp2PrvInstr_data \
  132. + HDOp1PrvInstr_data + HDOp2PrvInstr_data \
  133. + HWOp1SubInstr_data + HWOp2SubInstr_data \
  134. + HDOp1SubInstr_data + HDOp2SubInstr_data \
  135. + Operand1_bitinteractions_data + Operand2_bitinteractions_data \
  136. + BitFlip1_bitinteractions_data + BitFlip2_bitinteractions_data
  137. for i in range(nb_points):
  138. if triplet[CURRENT,i] == 5:
  139. power[i] = self.constant[triplet[CURRENT,i]]
  140. if debug:
  141. print([self.constant[instructiontype], \
  142. PrvInstr_data, SubInstr_data, \
  143. Operand1_data, Operand2_data, \
  144. BitFlip1_data, BitFlip2_data, \
  145. HWOp1PrvInstr_data, HWOp2PrvInstr_data, \
  146. HDOp1PrvInstr_data, HDOp2PrvInstr_data, \
  147. HWOp1SubInstr_data, HWOp2SubInstr_data, \
  148. HDOp1SubInstr_data, HDOp2SubInstr_data, \
  149. Operand1_bitinteractions_data, Operand2_bitinteractions_data, \
  150. BitFlip1_bitinteractions_data, BitFlip2_bitinteractions_data])
  151. return power
  152. def run(self):
  153. nb_points = len(self.points)
  154. triplet = np.array([p[0] for p in self.points]).T # shape = (3, nb_points)
  155. previous_ops = np.array([p[1] for p in self.points]).T # shape = (2, nb_points)
  156. current_ops = np.array([p[2] for p in self.points]).T # shape = (2, nb_points)
  157. self.power = self.calculate_point(triplet, previous_ops, current_ops)
  158. def oneshot_point(self, triplet, previous_ops, current_ops):
  159. self.reset_points()
  160. self.add_point(triplet, previous_ops, current_ops)
  161. self.run()
  162. return self.power